/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_

#include "jni.h"

#include "base/locks.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "thread_state.h"

namespace art {

class JavaVMExt;
class JNIEnvExt;
template<class MirrorType> class ObjPtr;
class Thread;

namespace mirror {
class Object;
}  // namespace mirror

// Scoped change into and out of a particular state. Handles Runnable transitions that require
// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
// the unchecked variant doesn't aid annotalysis.
class ScopedThreadStateChange : public ValueObject {
 public:
  ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE Thread* Self() const {
    return self_;
  }

 protected:
  // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
  ScopedThreadStateChange() {}

  Thread* const self_ = nullptr;
  const ThreadState thread_state_ = ThreadState::kTerminated;

 private:
  void ScopedThreadChangeDestructorCheck();

  ThreadState old_thread_state_ = ThreadState::kTerminated;
  const bool expected_has_no_thread_ = true;

  friend class ScopedObjectAccessUnchecked;
  DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
};

// Assumes we are already runnable.
class ScopedObjectAccessAlreadyRunnable : public ValueObject {
 public:
  Thread* Self() const {
    return self_;
  }

  JNIEnvExt* Env() const {
    return env_;
  }

  JavaVMExt* Vm() const {
    return vm_;
  }

  bool ForceCopy() const;

  /*
   * Add a local reference for an object to the indirect reference table associated with the
   * current stack frame.  When the native function returns, the reference will be discarded.
   *
   * We need to allow the same reference to be added multiple times, and cope with nullptr.
   *
   * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
   * it's best if we don't grab a mutex.
   */
  template<typename T>
  T AddLocalReference(ObjPtr<mirror::Object> obj) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  template<typename T>
  ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);

  ALWAYS_INLINE bool IsRunnable() const;

 protected:
  ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
  // change into Runnable or acquire a share on the mutator_lock_.
  // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
  //       as it prevents forward declaration of JavaVMExt.
  explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
      : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}

  // Here purely to force inlining.
  ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}

  static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Self thread, can be null.
  Thread* const self_;
  // The full JNIEnv.
  JNIEnvExt* const env_;
  // The full JavaVM.
  JavaVMExt* const vm_;
};

// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
//
// This class performs the necessary thread state switching to and from Runnable and lets us
// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
// is also manipulating the Object.
//
// The destructor transitions back to the previous thread state, typically Native. In this state
// GC and thread suspension may occur.
//
// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
// the mutator_lock_ will be acquired on construction.
class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
 public:
  ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {}

  // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
  // change into Runnable or acquire a share on the mutator_lock_.
  explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
      : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}

 private:
  // The scoped thread state change makes sure that we are runnable and restores the thread state
  // in the destructor.
  const ScopedThreadStateChange tsc_;

  DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
};

// Annotalysis helping variant of the above.
class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
 public:
  ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
      REQUIRES(!Locks::thread_suspend_count_lock_)
      SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

  ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_)
      SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

  // Base class will release share of lock. Invoked after this destructor.
  ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE;

 private:
  // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
  //       routines operating with just a VM are sound, they are not, but when you have just a VM
  //       you cannot call the unsound routines.
  explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
      : ScopedObjectAccessUnchecked(vm) {}

  friend class ScopedCheck;
  DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
};

// Annotalysis helper for going to a suspended state from runnable.
class ScopedThreadSuspension : public ValueObject {
 public:
  ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
      REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
      UNLOCK_FUNCTION(Locks::mutator_lock_);

  ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

 private:
  Thread* const self_;
  const ThreadState suspended_state_;
  DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
};


}  // namespace art

#endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
