/*
 * Copyright (C) 2011 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_THREAD_H_
#define ART_RUNTIME_THREAD_H_

#include <setjmp.h>

#include <bitset>
#include <deque>
#include <iosfwd>
#include <list>
#include <memory>
#include <string>

#include "arch/context.h"
#include "arch/instruction_set.h"
#include "atomic.h"
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "globals.h"
#include "handle_scope.h"
#include "instrumentation.h"
#include "jvalue.h"
#include "managed_stack.h"
#include "offsets.h"
#include "read_barrier_config.h"
#include "runtime_stats.h"
#include "suspend_reason.h"
#include "thread_state.h"

class BacktraceMap;

namespace art {

namespace gc {
namespace accounting {
template<class T> class AtomicStack;
}  // namespace accounting
namespace collector {
class SemiSpace;
}  // namespace collector
}  // namespace gc

namespace mirror {
class Array;
class Class;
class ClassLoader;
class Object;
template<class T> class ObjectArray;
template<class T> class PrimitiveArray;
typedef PrimitiveArray<int32_t> IntArray;
class StackTraceElement;
class String;
class Throwable;
}  // namespace mirror

namespace verifier {
class MethodVerifier;
class VerifierDeps;
}  // namespace verifier

class ArtMethod;
class BaseMutex;
class ClassLinker;
class Closure;
class Context;
struct DebugInvokeReq;
class DeoptimizationContextRecord;
class DexFile;
class FrameIdToShadowFrame;
class JavaVMExt;
struct JNIEnvExt;
class Monitor;
class RootVisitor;
class ScopedObjectAccessAlreadyRunnable;
class ShadowFrame;
class SingleStepControl;
class StackedShadowFrameRecord;
class Thread;
class ThreadList;
enum VisitRootFlags : uint8_t;

// Thread priorities. These must match the Thread.MIN_PRIORITY,
// Thread.NORM_PRIORITY, and Thread.MAX_PRIORITY constants.
enum ThreadPriority {
  kMinThreadPriority = 1,
  kNormThreadPriority = 5,
  kMaxThreadPriority = 10,
};

enum ThreadFlag {
  kSuspendRequest   = 1,  // If set implies that suspend_count_ > 0 and the Thread should enter the
                          // safepoint handler.
  kCheckpointRequest = 2,  // Request that the thread do some checkpoint work and then continue.
  kEmptyCheckpointRequest = 4,  // Request that the thread do empty checkpoint and then continue.
  kActiveSuspendBarrier = 8,  // Register that at least 1 suspend barrier needs to be passed.
};

enum class StackedShadowFrameType {
  kShadowFrameUnderConstruction,
  kDeoptimizationShadowFrame,
};

// The type of method that triggers deoptimization. It contains info on whether
// the deoptimized method should advance dex_pc.
enum class DeoptimizationMethodType {
  kKeepDexPc,  // dex pc is required to be kept upon deoptimization.
  kDefault     // dex pc may or may not advance depending on other conditions.
};

// This should match RosAlloc::kNumThreadLocalSizeBrackets.
static constexpr size_t kNumRosAllocThreadLocalSizeBracketsInThread = 16;

// Thread's stack layout for implicit stack overflow checks:
//
//   +---------------------+  <- highest address of stack memory
//   |                     |
//   .                     .  <- SP
//   |                     |
//   |                     |
//   +---------------------+  <- stack_end
//   |                     |
//   |  Gap                |
//   |                     |
//   +---------------------+  <- stack_begin
//   |                     |
//   | Protected region    |
//   |                     |
//   +---------------------+  <- lowest address of stack memory
//
// The stack always grows down in memory.  At the lowest address is a region of memory
// that is set mprotect(PROT_NONE).  Any attempt to read/write to this region will
// result in a segmentation fault signal.  At any point, the thread's SP will be somewhere
// between the stack_end and the highest address in stack memory.  An implicit stack
// overflow check is a read of memory at a certain offset below the current SP (4K typically).
// If the thread's SP is below the stack_end address this will be a read into the protected
// region.  If the SP is above the stack_end address, the thread is guaranteed to have
// at least 4K of space.  Because stack overflow checks are only performed in generated code,
// if the thread makes a call out to a native function (through JNI), that native function
// might only have 4K of memory (if the SP is adjacent to stack_end).

class Thread {
 public:
  static const size_t kStackOverflowImplicitCheckSize;
  static constexpr bool kVerifyStack = kIsDebugBuild;

  // Creates a new native thread corresponding to the given managed peer.
  // Used to implement Thread.start.
  static void CreateNativeThread(JNIEnv* env, jobject peer, size_t stack_size, bool daemon);

  // Attaches the calling native thread to the runtime, returning the new native peer.
  // Used to implement JNI AttachCurrentThread and AttachCurrentThreadAsDaemon calls.
  static Thread* Attach(const char* thread_name, bool as_daemon, jobject thread_group,
                        bool create_peer);
  // Attaches the calling native thread to the runtime, returning the new native peer.
  static Thread* Attach(const char* thread_name, bool as_daemon, jobject thread_peer);

  // Reset internal state of child thread after fork.
  void InitAfterFork();

  // Get the currently executing thread, frequently referred to as 'self'. This call has reasonably
  // high cost and so we favor passing self around when possible.
  // TODO: mark as PURE so the compiler may coalesce and remove?
  static Thread* Current();

  // On a runnable thread, check for pending thread suspension request and handle if pending.
  void AllowThreadSuspension() REQUIRES_SHARED(Locks::mutator_lock_);

  // Process pending thread suspension request and handle if pending.
  void CheckSuspend() REQUIRES_SHARED(Locks::mutator_lock_);

  // Process a pending empty checkpoint if pending.
  void CheckEmptyCheckpointFromWeakRefAccess(BaseMutex* cond_var_mutex);
  void CheckEmptyCheckpointFromMutex();

  static Thread* FromManagedThread(const ScopedObjectAccessAlreadyRunnable& ts,
                                   ObjPtr<mirror::Object> thread_peer)
      REQUIRES(Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  static Thread* FromManagedThread(const ScopedObjectAccessAlreadyRunnable& ts, jobject thread)
      REQUIRES(Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Translates 172 to pAllocArrayFromCode and so on.
  template<PointerSize size_of_pointers>
  static void DumpThreadOffset(std::ostream& os, uint32_t offset);

  // Dumps a one-line summary of thread state (used for operator<<).
  void ShortDump(std::ostream& os) const;

  // Dumps the detailed thread state and the thread stack (used for SIGQUIT).
  void Dump(std::ostream& os,
            bool dump_native_stack = true,
            BacktraceMap* backtrace_map = nullptr,
            bool force_dump_stack = false) const
      REQUIRES(!Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void DumpJavaStack(std::ostream& os,
                     bool check_suspended = true,
                     bool dump_locks = true) const
      REQUIRES(!Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Dumps the SIGQUIT per-thread header. 'thread' can be null for a non-attached thread, in which
  // case we use 'tid' to identify the thread, and we'll include as much information as we can.
  static void DumpState(std::ostream& os, const Thread* thread, pid_t tid)
      REQUIRES(!Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ThreadState GetState() const {
    DCHECK_GE(tls32_.state_and_flags.as_struct.state, kTerminated);
    DCHECK_LE(tls32_.state_and_flags.as_struct.state, kSuspended);
    return static_cast<ThreadState>(tls32_.state_and_flags.as_struct.state);
  }

  ThreadState SetState(ThreadState new_state);

  int GetSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_) {
    return tls32_.suspend_count;
  }

  int GetUserCodeSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_,
                                               Locks::user_code_suspension_lock_) {
    return tls32_.user_code_suspend_count;
  }

  int GetDebugSuspendCount() const REQUIRES(Locks::thread_suspend_count_lock_) {
    return tls32_.debug_suspend_count;
  }

  bool IsSuspended() const {
    union StateAndFlags state_and_flags;
    state_and_flags.as_int = tls32_.state_and_flags.as_int;
    return state_and_flags.as_struct.state != kRunnable &&
        (state_and_flags.as_struct.flags & kSuspendRequest) != 0;
  }

  // If delta > 0 and (this != self or suspend_barrier is not null), this function may temporarily
  // release thread_suspend_count_lock_ internally.
  ALWAYS_INLINE
  bool ModifySuspendCount(Thread* self,
                          int delta,
                          AtomicInteger* suspend_barrier,
                          SuspendReason reason)
      WARN_UNUSED
      REQUIRES(Locks::thread_suspend_count_lock_);

  bool RequestCheckpoint(Closure* function)
      REQUIRES(Locks::thread_suspend_count_lock_);

  // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution. This is
  // due to the fact that Thread::Current() needs to go to sleep to allow the targeted thread to
  // execute the checkpoint for us if it is Runnable.
  bool RequestSynchronousCheckpoint(Closure* function)
      REQUIRES_SHARED(Locks::mutator_lock_)
      RELEASE(Locks::thread_list_lock_)
      REQUIRES(!Locks::thread_suspend_count_lock_);
  bool RequestEmptyCheckpoint()
      REQUIRES(Locks::thread_suspend_count_lock_);

  void SetFlipFunction(Closure* function);
  Closure* GetFlipFunction();

  gc::accounting::AtomicStack<mirror::Object>* GetThreadLocalMarkStack() {
    CHECK(kUseReadBarrier);
    return tlsPtr_.thread_local_mark_stack;
  }
  void SetThreadLocalMarkStack(gc::accounting::AtomicStack<mirror::Object>* stack) {
    CHECK(kUseReadBarrier);
    tlsPtr_.thread_local_mark_stack = stack;
  }

  // Called when thread detected that the thread_suspend_count_ was non-zero. Gives up share of
  // mutator_lock_ and waits until it is resumed and thread_suspend_count_ is zero.
  void FullSuspendCheck()
      REQUIRES(!Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Transition from non-runnable to runnable state acquiring share on mutator_lock_.
  ALWAYS_INLINE ThreadState TransitionFromSuspendedToRunnable()
      REQUIRES(!Locks::thread_suspend_count_lock_)
      SHARED_LOCK_FUNCTION(Locks::mutator_lock_);

  // Transition from runnable into a state where mutator privileges are denied. Releases share of
  // mutator lock.
  ALWAYS_INLINE void TransitionFromRunnableToSuspended(ThreadState new_state)
      REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
      UNLOCK_FUNCTION(Locks::mutator_lock_);

  // Once called thread suspension will cause an assertion failure.
  const char* StartAssertNoThreadSuspension(const char* cause) ACQUIRE(Roles::uninterruptible_) {
    Roles::uninterruptible_.Acquire();  // No-op.
    if (kIsDebugBuild) {
      CHECK(cause != nullptr);
      const char* previous_cause = tlsPtr_.last_no_thread_suspension_cause;
      tls32_.no_thread_suspension++;
      tlsPtr_.last_no_thread_suspension_cause = cause;
      return previous_cause;
    } else {
      return nullptr;
    }
  }

  // End region where no thread suspension is expected.
  void EndAssertNoThreadSuspension(const char* old_cause) RELEASE(Roles::uninterruptible_) {
    if (kIsDebugBuild) {
      CHECK(old_cause != nullptr || tls32_.no_thread_suspension == 1);
      CHECK_GT(tls32_.no_thread_suspension, 0U);
      tls32_.no_thread_suspension--;
      tlsPtr_.last_no_thread_suspension_cause = old_cause;
    }
    Roles::uninterruptible_.Release();  // No-op.
  }

  void AssertThreadSuspensionIsAllowable(bool check_locks = true) const;

  // Return true if thread suspension is allowable.
  bool IsThreadSuspensionAllowable() const;

  bool IsDaemon() const {
    return tls32_.daemon;
  }

  size_t NumberOfHeldMutexes() const;

  bool HoldsLock(ObjPtr<mirror::Object> object) const REQUIRES_SHARED(Locks::mutator_lock_);

  /*
   * Changes the priority of this thread to match that of the java.lang.Thread object.
   *
   * We map a priority value from 1-10 to Linux "nice" values, where lower
   * numbers indicate higher priority.
   */
  void SetNativePriority(int newPriority);

  /*
   * Returns the thread priority for the current thread by querying the system.
   * This is useful when attaching a thread through JNI.
   *
   * Returns a value from 1 to 10 (compatible with java.lang.Thread values).
   */
  static int GetNativePriority();

  // Guaranteed to be non-zero.
  uint32_t GetThreadId() const {
    return tls32_.thin_lock_thread_id;
  }

  pid_t GetTid() const {
    return tls32_.tid;
  }

  // Returns the java.lang.Thread's name, or null if this Thread* doesn't have a peer.
  mirror::String* GetThreadName() const REQUIRES_SHARED(Locks::mutator_lock_);

  // Sets 'name' to the java.lang.Thread's name. This requires no transition to managed code,
  // allocation, or locking.
  void GetThreadName(std::string& name) const;

  // Sets the thread's name.
  void SetThreadName(const char* name) REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns the thread-specific CPU-time clock in microseconds or -1 if unavailable.
  uint64_t GetCpuMicroTime() const;

  mirror::Object* GetPeer() const REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(Thread::Current() == this) << "Use GetPeerFromOtherThread instead";
    CHECK(tlsPtr_.jpeer == nullptr);
    return tlsPtr_.opeer;
  }
  // GetPeer is not safe if called on another thread in the middle of the CC thread flip and
  // the thread's stack may have not been flipped yet and peer may be a from-space (stale) ref.
  // This function will explicitly mark/forward it.
  mirror::Object* GetPeerFromOtherThread() const REQUIRES_SHARED(Locks::mutator_lock_);

  bool HasPeer() const {
    return tlsPtr_.jpeer != nullptr || tlsPtr_.opeer != nullptr;
  }

  RuntimeStats* GetStats() {
    return &tls64_.stats;
  }

  bool IsStillStarting() const;

  bool IsExceptionPending() const {
    return tlsPtr_.exception != nullptr;
  }

  bool IsAsyncExceptionPending() const {
    return tlsPtr_.async_exception != nullptr;
  }

  mirror::Throwable* GetException() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return tlsPtr_.exception;
  }

  void AssertPendingException() const;
  void AssertPendingOOMException() const REQUIRES_SHARED(Locks::mutator_lock_);
  void AssertNoPendingException() const;
  void AssertNoPendingExceptionForNewException(const char* msg) const;

  void SetException(ObjPtr<mirror::Throwable> new_exception) REQUIRES_SHARED(Locks::mutator_lock_);

  // Set an exception that is asynchronously thrown from a different thread. This will be checked
  // periodically and might overwrite the current 'Exception'. This can only be called from a
  // checkpoint.
  //
  // The caller should also make sure that the thread has been deoptimized so that the exception
  // could be detected on back-edges.
  void SetAsyncException(ObjPtr<mirror::Throwable> new_exception)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void ClearException() REQUIRES_SHARED(Locks::mutator_lock_) {
    tlsPtr_.exception = nullptr;
  }

  // Move the current async-exception to the main exception. This should be called when the current
  // thread is ready to deal with any async exceptions. Returns true if there is an async exception
  // that needs to be dealt with, false otherwise.
  bool ObserveAsyncException() REQUIRES_SHARED(Locks::mutator_lock_);

  // Find catch block and perform long jump to appropriate exception handle
  NO_RETURN void QuickDeliverException() REQUIRES_SHARED(Locks::mutator_lock_);

  Context* GetLongJumpContext();
  void ReleaseLongJumpContext(Context* context) {
    if (tlsPtr_.long_jump_context != nullptr) {
      // Each QuickExceptionHandler gets a long jump context and uses
      // it for doing the long jump, after finding catch blocks/doing deoptimization.
      // Both finding catch blocks and deoptimization can trigger another
      // exception such as a result of class loading. So there can be nested
      // cases of exception handling and multiple contexts being used.
      // ReleaseLongJumpContext tries to save the context in tlsPtr_.long_jump_context
      // for reuse so there is no need to always allocate a new one each time when
      // getting a context. Since we only keep one context for reuse, delete the
      // existing one since the passed in context is yet to be used for longjump.
      delete tlsPtr_.long_jump_context;
    }
    tlsPtr_.long_jump_context = context;
  }

  // Get the current method and dex pc. If there are errors in retrieving the dex pc, this will
  // abort the runtime iff abort_on_error is true.
  ArtMethod* GetCurrentMethod(uint32_t* dex_pc,
                              bool check_suspended = true,
                              bool abort_on_error = true) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns whether the given exception was thrown by the current Java method being executed
  // (Note that this includes native Java methods).
  bool IsExceptionThrownByCurrentMethod(ObjPtr<mirror::Throwable> exception) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  void SetTopOfStack(ArtMethod** top_method) {
    tlsPtr_.managed_stack.SetTopQuickFrame(top_method);
  }

  void SetTopOfShadowStack(ShadowFrame* top) {
    tlsPtr_.managed_stack.SetTopShadowFrame(top);
  }

  bool HasManagedStack() const {
    return (tlsPtr_.managed_stack.GetTopQuickFrame() != nullptr) ||
        (tlsPtr_.managed_stack.GetTopShadowFrame() != nullptr);
  }

  // If 'msg' is null, no detail message is set.
  void ThrowNewException(const char* exception_class_descriptor, const char* msg)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);

  // If 'msg' is null, no detail message is set. An exception must be pending, and will be
  // used as the new exception's cause.
  void ThrowNewWrappedException(const char* exception_class_descriptor, const char* msg)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);

  void ThrowNewExceptionF(const char* exception_class_descriptor, const char* fmt, ...)
      __attribute__((format(printf, 3, 4)))
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);

  void ThrowNewExceptionV(const char* exception_class_descriptor, const char* fmt, va_list ap)
      REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);

  // OutOfMemoryError is special, because we need to pre-allocate an instance.
  // Only the GC should call this.
  void ThrowOutOfMemoryError(const char* msg) REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Roles::uninterruptible_);

  static void Startup();
  static void FinishStartup();
  static void Shutdown();

  // JNI methods
  JNIEnvExt* GetJniEnv() const {
    return tlsPtr_.jni_env;
  }

  // Convert a jobject into a Object*
  ObjPtr<mirror::Object> DecodeJObject(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
  // Checks if the weak global ref has been cleared by the GC without decoding it.
  bool IsJWeakCleared(jweak obj) const REQUIRES_SHARED(Locks::mutator_lock_);

  mirror::Object* GetMonitorEnterObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return tlsPtr_.monitor_enter_object;
  }

  void SetMonitorEnterObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
    tlsPtr_.monitor_enter_object = obj;
  }

  // Implements java.lang.Thread.interrupted.
  bool Interrupted();
  // Implements java.lang.Thread.isInterrupted.
  bool IsInterrupted();
  void Interrupt(Thread* self) REQUIRES(!*wait_mutex_);
  void SetInterrupted(bool i) {
    tls32_.interrupted.StoreSequentiallyConsistent(i);
  }
  void Notify() REQUIRES(!*wait_mutex_);

  ALWAYS_INLINE void PoisonObjectPointers() {
    ++poison_object_cookie_;
  }

  ALWAYS_INLINE static void PoisonObjectPointersIfDebug();

  ALWAYS_INLINE uintptr_t GetPoisonObjectCookie() const {
    return poison_object_cookie_;
  }

 private:
  void NotifyLocked(Thread* self) REQUIRES(wait_mutex_);

 public:
  Mutex* GetWaitMutex() const LOCK_RETURNED(wait_mutex_) {
    return wait_mutex_;
  }

  ConditionVariable* GetWaitConditionVariable() const REQUIRES(wait_mutex_) {
    return wait_cond_;
  }

  Monitor* GetWaitMonitor() const REQUIRES(wait_mutex_) {
    return wait_monitor_;
  }

  void SetWaitMonitor(Monitor* mon) REQUIRES(wait_mutex_) {
    wait_monitor_ = mon;
  }

  // Waiter link-list support.
  Thread* GetWaitNext() const {
    return tlsPtr_.wait_next;
  }

  void SetWaitNext(Thread* next) {
    tlsPtr_.wait_next = next;
  }

  jobject GetClassLoaderOverride() {
    return tlsPtr_.class_loader_override;
  }

  void SetClassLoaderOverride(jobject class_loader_override);

  // Create the internal representation of a stack trace, that is more time
  // and space efficient to compute than the StackTraceElement[].
  template<bool kTransactionActive>
  jobject CreateInternalStackTrace(const ScopedObjectAccessAlreadyRunnable& soa) const
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Convert an internal stack trace representation (returned by CreateInternalStackTrace) to a
  // StackTraceElement[]. If output_array is null, a new array is created, otherwise as many
  // frames as will fit are written into the given array. If stack_depth is non-null, it's updated
  // with the number of valid frames in the returned array.
  static jobjectArray InternalStackTraceToStackTraceElementArray(
      const ScopedObjectAccessAlreadyRunnable& soa, jobject internal,
      jobjectArray output_array = nullptr, int* stack_depth = nullptr)
      REQUIRES_SHARED(Locks::mutator_lock_);

  bool HasDebuggerShadowFrames() const {
    return tlsPtr_.frame_id_to_shadow_frame != nullptr;
  }

  void VisitRoots(RootVisitor* visitor, VisitRootFlags flags)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void VerifyStack() REQUIRES_SHARED(Locks::mutator_lock_) {
    if (kVerifyStack) {
      VerifyStackImpl();
    }
  }

  //
  // Offsets of various members of native Thread class, used by compiled code.
  //

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThinLockIdOffset() {
    return ThreadOffset<pointer_size>(
        OFFSETOF_MEMBER(Thread, tls32_) +
        OFFSETOF_MEMBER(tls_32bit_sized_values, thin_lock_thread_id));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> InterruptedOffset() {
    return ThreadOffset<pointer_size>(
        OFFSETOF_MEMBER(Thread, tls32_) +
        OFFSETOF_MEMBER(tls_32bit_sized_values, interrupted));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadFlagsOffset() {
    return ThreadOffset<pointer_size>(
        OFFSETOF_MEMBER(Thread, tls32_) +
        OFFSETOF_MEMBER(tls_32bit_sized_values, state_and_flags));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> IsGcMarkingOffset() {
    return ThreadOffset<pointer_size>(
        OFFSETOF_MEMBER(Thread, tls32_) +
        OFFSETOF_MEMBER(tls_32bit_sized_values, is_gc_marking));
  }

  static constexpr size_t IsGcMarkingSize() {
    return sizeof(tls32_.is_gc_marking);
  }

  // Deoptimize the Java stack.
  void DeoptimizeWithDeoptimizationException(JValue* result) REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadOffsetFromTlsPtr(size_t tls_ptr_offset) {
    size_t base = OFFSETOF_MEMBER(Thread, tlsPtr_);
    size_t scale;
    size_t shrink;
    if (pointer_size == kRuntimePointerSize) {
      scale = 1;
      shrink = 1;
    } else if (pointer_size > kRuntimePointerSize) {
      scale = static_cast<size_t>(pointer_size) / static_cast<size_t>(kRuntimePointerSize);
      shrink = 1;
    } else {
      DCHECK_GT(kRuntimePointerSize, pointer_size);
      scale = 1;
      shrink = static_cast<size_t>(kRuntimePointerSize) / static_cast<size_t>(pointer_size);
    }
    return ThreadOffset<pointer_size>(base + ((tls_ptr_offset * scale) / shrink));
  }

 public:
  static uint32_t QuickEntryPointOffsetWithSize(size_t quick_entrypoint_offset,
                                                PointerSize pointer_size) {
    if (pointer_size == PointerSize::k32) {
      return QuickEntryPointOffset<PointerSize::k32>(quick_entrypoint_offset).
          Uint32Value();
    } else {
      return QuickEntryPointOffset<PointerSize::k64>(quick_entrypoint_offset).
          Uint32Value();
    }
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> QuickEntryPointOffset(size_t quick_entrypoint_offset) {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, quick_entrypoints) + quick_entrypoint_offset);
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> JniEntryPointOffset(size_t jni_entrypoint_offset) {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, jni_entrypoints) + jni_entrypoint_offset);
  }

  // Return the entry point offset integer value for ReadBarrierMarkRegX, where X is `reg`.
  template <PointerSize pointer_size>
  static int32_t ReadBarrierMarkEntryPointsOffset(size_t reg) {
    // The entry point list defines 30 ReadBarrierMarkRegX entry points.
    DCHECK_LT(reg, 30u);
    // The ReadBarrierMarkRegX entry points are ordered by increasing
    // register number in Thread::tls_Ptr_.quick_entrypoints.
    return QUICK_ENTRYPOINT_OFFSET(pointer_size, pReadBarrierMarkReg00).Int32Value()
        + static_cast<size_t>(pointer_size) * reg;
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> SelfOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values, self));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> MterpCurrentIBaseOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, mterp_current_ibase));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> MterpDefaultIBaseOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, mterp_default_ibase));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> MterpAltIBaseOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, mterp_alt_ibase));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ExceptionOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values, exception));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> PeerOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values, opeer));
  }


  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> CardTableOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values, card_table));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadSuspendTriggerOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, suspend_trigger));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadLocalPosOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                thread_local_pos));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadLocalEndOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                thread_local_end));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadLocalObjectsOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                thread_local_objects));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> RosAllocRunsOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                rosalloc_runs));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadLocalAllocStackTopOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                thread_local_alloc_stack_top));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> ThreadLocalAllocStackEndOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                thread_local_alloc_stack_end));
  }

  // Size of stack less any space reserved for stack overflow
  size_t GetStackSize() const {
    return tlsPtr_.stack_size - (tlsPtr_.stack_end - tlsPtr_.stack_begin);
  }

  uint8_t* GetStackEndForInterpreter(bool implicit_overflow_check) const {
    if (implicit_overflow_check) {
      // The interpreter needs the extra overflow bytes that stack_end does
      // not include.
      return tlsPtr_.stack_end + GetStackOverflowReservedBytes(kRuntimeISA);
    } else {
      return tlsPtr_.stack_end;
    }
  }

  uint8_t* GetStackEnd() const {
    return tlsPtr_.stack_end;
  }

  // Set the stack end to that to be used during a stack overflow
  void SetStackEndForStackOverflow() REQUIRES_SHARED(Locks::mutator_lock_);

  // Set the stack end to that to be used during regular execution
  void ResetDefaultStackEnd() {
    // Our stacks grow down, so we want stack_end_ to be near there, but reserving enough room
    // to throw a StackOverflowError.
    tlsPtr_.stack_end = tlsPtr_.stack_begin + GetStackOverflowReservedBytes(kRuntimeISA);
  }

  bool IsHandlingStackOverflow() const {
    return tlsPtr_.stack_end == tlsPtr_.stack_begin;
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> StackEndOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, stack_end));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> JniEnvOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, jni_env));
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> TopOfManagedStackOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, managed_stack) +
        ManagedStack::TopQuickFrameOffset());
  }

  const ManagedStack* GetManagedStack() const {
    return &tlsPtr_.managed_stack;
  }

  // Linked list recording fragments of managed stack.
  void PushManagedStackFragment(ManagedStack* fragment) {
    tlsPtr_.managed_stack.PushManagedStackFragment(fragment);
  }
  void PopManagedStackFragment(const ManagedStack& fragment) {
    tlsPtr_.managed_stack.PopManagedStackFragment(fragment);
  }

  ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame);
  ALWAYS_INLINE ShadowFrame* PopShadowFrame();

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> TopShadowFrameOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(
        OFFSETOF_MEMBER(tls_ptr_sized_values, managed_stack) +
        ManagedStack::TopShadowFrameOffset());
  }

  // Is the given obj in this thread's stack indirect reference table?
  bool HandleScopeContains(jobject obj) const;

  void HandleScopeVisitRoots(RootVisitor* visitor, pid_t thread_id)
      REQUIRES_SHARED(Locks::mutator_lock_);

  BaseHandleScope* GetTopHandleScope() {
    return tlsPtr_.top_handle_scope;
  }

  void PushHandleScope(BaseHandleScope* handle_scope) {
    DCHECK_EQ(handle_scope->GetLink(), tlsPtr_.top_handle_scope);
    tlsPtr_.top_handle_scope = handle_scope;
  }

  BaseHandleScope* PopHandleScope() {
    BaseHandleScope* handle_scope = tlsPtr_.top_handle_scope;
    DCHECK(handle_scope != nullptr);
    tlsPtr_.top_handle_scope = tlsPtr_.top_handle_scope->GetLink();
    return handle_scope;
  }

  template<PointerSize pointer_size>
  static ThreadOffset<pointer_size> TopHandleScopeOffset() {
    return ThreadOffsetFromTlsPtr<pointer_size>(OFFSETOF_MEMBER(tls_ptr_sized_values,
                                                                top_handle_scope));
  }

  DebugInvokeReq* GetInvokeReq() const {
    return tlsPtr_.debug_invoke_req;
  }

  SingleStepControl* GetSingleStepControl() const {
    return tlsPtr_.single_step_control;
  }

  // Indicates whether this thread is ready to invoke a method for debugging. This
  // is only true if the thread has been suspended by a debug event.
  bool IsReadyForDebugInvoke() const {
    return tls32_.ready_for_debug_invoke;
  }

  void SetReadyForDebugInvoke(bool ready) {
    tls32_.ready_for_debug_invoke = ready;
  }

  bool IsDebugMethodEntry() const {
    return tls32_.debug_method_entry_;
  }

  void SetDebugMethodEntry() {
    tls32_.debug_method_entry_ = true;
  }

  void ClearDebugMethodEntry() {
    tls32_.debug_method_entry_ = false;
  }

  bool GetIsGcMarking() const {
    CHECK(kUseReadBarrier);
    return tls32_.is_gc_marking;
  }

  void SetIsGcMarkingAndUpdateEntrypoints(bool is_marking);

  bool GetWeakRefAccessEnabled() const {
    CHECK(kUseReadBarrier);
    return tls32_.weak_ref_access_enabled;
  }

  void SetWeakRefAccessEnabled(bool enabled) {
    CHECK(kUseReadBarrier);
    tls32_.weak_ref_access_enabled = enabled;
  }

  uint32_t GetDisableThreadFlipCount() const {
    CHECK(kUseReadBarrier);
    return tls32_.disable_thread_flip_count;
  }

  void IncrementDisableThreadFlipCount() {
    CHECK(kUseReadBarrier);
    ++tls32_.disable_thread_flip_count;
  }

  void DecrementDisableThreadFlipCount() {
    CHECK(kUseReadBarrier);
    DCHECK_GT(tls32_.disable_thread_flip_count, 0U);
    --tls32_.disable_thread_flip_count;
  }

  // Returns true if the thread is allowed to call into java.
  bool CanCallIntoJava() const {
    return can_call_into_java_;
  }

  void SetCanCallIntoJava(bool can_call_into_java) {
    can_call_into_java_ = can_call_into_java;
  }

  // Activates single step control for debugging. The thread takes the
  // ownership of the given SingleStepControl*. It is deleted by a call
  // to DeactivateSingleStepControl or upon thread destruction.
  void ActivateSingleStepControl(SingleStepControl* ssc);

  // Deactivates single step control for debugging.
  void DeactivateSingleStepControl();

  // Sets debug invoke request for debugging. When the thread is resumed,
  // it executes the method described by this request then sends the reply
  // before suspending itself. The thread takes the ownership of the given
  // DebugInvokeReq*. It is deleted by a call to ClearDebugInvokeReq.
  void SetDebugInvokeReq(DebugInvokeReq* req);

  // Clears debug invoke request for debugging. When the thread completes
  // method invocation, it deletes its debug invoke request and suspends
  // itself.
  void ClearDebugInvokeReq();

  // Returns the fake exception used to activate deoptimization.
  static mirror::Throwable* GetDeoptimizationException() {
    // Note that the mirror::Throwable must be aligned to kObjectAlignment or else it cannot be
    // represented by ObjPtr.
    return reinterpret_cast<mirror::Throwable*>(0x100);
  }

  // Currently deoptimization invokes verifier which can trigger class loading
  // and execute Java code, so there might be nested deoptimizations happening.
  // We need to save the ongoing deoptimization shadow frames and return
  // values on stacks.
  // 'from_code' denotes whether the deoptimization was explicitly made from
  // compiled code.
  // 'method_type' contains info on whether deoptimization should advance
  // dex_pc.
  void PushDeoptimizationContext(const JValue& return_value,
                                 bool is_reference,
                                 ObjPtr<mirror::Throwable> exception,
                                 bool from_code,
                                 DeoptimizationMethodType method_type)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void PopDeoptimizationContext(JValue* result,
                                ObjPtr<mirror::Throwable>* exception,
                                bool* from_code,
                                DeoptimizationMethodType* method_type)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void AssertHasDeoptimizationContext()
      REQUIRES_SHARED(Locks::mutator_lock_);
  void PushStackedShadowFrame(ShadowFrame* sf, StackedShadowFrameType type);
  ShadowFrame* PopStackedShadowFrame(StackedShadowFrameType type, bool must_be_present = true);

  // For debugger, find the shadow frame that corresponds to a frame id.
  // Or return null if there is none.
  ShadowFrame* FindDebuggerShadowFrame(size_t frame_id)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // For debugger, find the bool array that keeps track of the updated vreg set
  // for a frame id.
  bool* GetUpdatedVRegFlags(size_t frame_id) REQUIRES_SHARED(Locks::mutator_lock_);
  // For debugger, find the shadow frame that corresponds to a frame id. If
  // one doesn't exist yet, create one and track it in frame_id_to_shadow_frame.
  ShadowFrame* FindOrCreateDebuggerShadowFrame(size_t frame_id,
                                               uint32_t num_vregs,
                                               ArtMethod* method,
                                               uint32_t dex_pc)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Delete the entry that maps from frame_id to shadow_frame.
  void RemoveDebuggerShadowFrameMapping(size_t frame_id)
      REQUIRES_SHARED(Locks::mutator_lock_);

  std::deque<instrumentation::InstrumentationStackFrame>* GetInstrumentationStack() {
    return tlsPtr_.instrumentation_stack;
  }

  std::vector<ArtMethod*>* GetStackTraceSample() const {
    DCHECK(!IsAotCompiler());
    return tlsPtr_.deps_or_stack_trace_sample.stack_trace_sample;
  }

  void SetStackTraceSample(std::vector<ArtMethod*>* sample) {
    DCHECK(!IsAotCompiler());
    tlsPtr_.deps_or_stack_trace_sample.stack_trace_sample = sample;
  }

  verifier::VerifierDeps* GetVerifierDeps() const {
    DCHECK(IsAotCompiler());
    return tlsPtr_.deps_or_stack_trace_sample.verifier_deps;
  }

  // It is the responsability of the caller to make sure the verifier_deps
  // entry in the thread is cleared before destruction of the actual VerifierDeps
  // object, or the thread.
  void SetVerifierDeps(verifier::VerifierDeps* verifier_deps) {
    DCHECK(IsAotCompiler());
    DCHECK(verifier_deps == nullptr || tlsPtr_.deps_or_stack_trace_sample.verifier_deps == nullptr);
    tlsPtr_.deps_or_stack_trace_sample.verifier_deps = verifier_deps;
  }

  uint64_t GetTraceClockBase() const {
    return tls64_.trace_clock_base;
  }

  void SetTraceClockBase(uint64_t clock_base) {
    tls64_.trace_clock_base = clock_base;
  }

  BaseMutex* GetHeldMutex(LockLevel level) const {
    return tlsPtr_.held_mutexes[level];
  }

  void SetHeldMutex(LockLevel level, BaseMutex* mutex) {
    tlsPtr_.held_mutexes[level] = mutex;
  }

  void ClearSuspendBarrier(AtomicInteger* target)
      REQUIRES(Locks::thread_suspend_count_lock_);

  bool ReadFlag(ThreadFlag flag) const {
    return (tls32_.state_and_flags.as_struct.flags & flag) != 0;
  }

  bool TestAllFlags() const {
    return (tls32_.state_and_flags.as_struct.flags != 0);
  }

  void AtomicSetFlag(ThreadFlag flag) {
    tls32_.state_and_flags.as_atomic_int.FetchAndOrSequentiallyConsistent(flag);
  }

  void AtomicClearFlag(ThreadFlag flag) {
    tls32_.state_and_flags.as_atomic_int.FetchAndAndSequentiallyConsistent(-1 ^ flag);
  }

  void ResetQuickAllocEntryPointsForThread(bool is_marking);

  // Returns the remaining space in the TLAB.
  size_t TlabSize() const {
    return tlsPtr_.thread_local_end - tlsPtr_.thread_local_pos;
  }

  // Returns the remaining space in the TLAB if we were to expand it to maximum capacity.
  size_t TlabRemainingCapacity() const {
    return tlsPtr_.thread_local_limit - tlsPtr_.thread_local_pos;
  }

  // Expand the TLAB by a fixed number of bytes. There must be enough capacity to do so.
  void ExpandTlab(size_t bytes) {
    tlsPtr_.thread_local_end += bytes;
    DCHECK_LE(tlsPtr_.thread_local_end, tlsPtr_.thread_local_limit);
  }

  // Doesn't check that there is room.
  mirror::Object* AllocTlab(size_t bytes);
  void SetTlab(uint8_t* start, uint8_t* end, uint8_t* limit);
  bool HasTlab() const;
  uint8_t* GetTlabStart() {
    return tlsPtr_.thread_local_start;
  }
  uint8_t* GetTlabPos() {
    return tlsPtr_.thread_local_pos;
  }

  // Remove the suspend trigger for this thread by making the suspend_trigger_ TLS value
  // equal to a valid pointer.
  // TODO: does this need to atomic?  I don't think so.
  void RemoveSuspendTrigger() {
    tlsPtr_.suspend_trigger = reinterpret_cast<uintptr_t*>(&tlsPtr_.suspend_trigger);
  }

  // Trigger a suspend check by making the suspend_trigger_ TLS value an invalid pointer.
  // The next time a suspend check is done, it will load from the value at this address
  // and trigger a SIGSEGV.
  void TriggerSuspend() {
    tlsPtr_.suspend_trigger = nullptr;
  }


  // Push an object onto the allocation stack.
  bool PushOnThreadLocalAllocationStack(mirror::Object* obj)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Set the thread local allocation pointers to the given pointers.
  void SetThreadLocalAllocationStack(StackReference<mirror::Object>* start,
                                     StackReference<mirror::Object>* end);

  // Resets the thread local allocation pointers.
  void RevokeThreadLocalAllocationStack();

  size_t GetThreadLocalBytesAllocated() const {
    return tlsPtr_.thread_local_end - tlsPtr_.thread_local_start;
  }

  size_t GetThreadLocalObjectsAllocated() const {
    return tlsPtr_.thread_local_objects;
  }

  void* GetRosAllocRun(size_t index) const {
    return tlsPtr_.rosalloc_runs[index];
  }

  void SetRosAllocRun(size_t index, void* run) {
    tlsPtr_.rosalloc_runs[index] = run;
  }

  bool ProtectStack(bool fatal_on_error = true);
  bool UnprotectStack();

  void SetMterpDefaultIBase(void* ibase) {
    tlsPtr_.mterp_default_ibase = ibase;
  }

  void SetMterpCurrentIBase(void* ibase) {
    tlsPtr_.mterp_current_ibase = ibase;
  }

  void SetMterpAltIBase(void* ibase) {
    tlsPtr_.mterp_alt_ibase = ibase;
  }

  const void* GetMterpDefaultIBase() const {
    return tlsPtr_.mterp_default_ibase;
  }

  const void* GetMterpCurrentIBase() const {
    return tlsPtr_.mterp_current_ibase;
  }

  const void* GetMterpAltIBase() const {
    return tlsPtr_.mterp_alt_ibase;
  }

  bool HandlingSignal() const {
    return tls32_.handling_signal_;
  }

  void SetHandlingSignal(bool handling_signal) {
    tls32_.handling_signal_ = handling_signal;
  }

  bool IsTransitioningToRunnable() const {
    return tls32_.is_transitioning_to_runnable;
  }

  void SetIsTransitioningToRunnable(bool value) {
    tls32_.is_transitioning_to_runnable = value;
  }

  void PushVerifier(verifier::MethodVerifier* verifier);
  void PopVerifier(verifier::MethodVerifier* verifier);

  void InitStringEntryPoints();

  void ModifyDebugDisallowReadBarrier(int8_t delta) {
    debug_disallow_read_barrier_ += delta;
  }

  uint8_t GetDebugDisallowReadBarrierCount() const {
    return debug_disallow_read_barrier_;
  }

  void* GetCustomTLS() const REQUIRES(Locks::thread_list_lock_) {
    return custom_tls_;
  }

  void SetCustomTLS(void* data) REQUIRES(Locks::thread_list_lock_) {
    custom_tls_ = data;
  }

  // Returns true if the current thread is the jit sensitive thread.
  bool IsJitSensitiveThread() const {
    return this == jit_sensitive_thread_;
  }

  // Returns true if StrictMode events are traced for the current thread.
  static bool IsSensitiveThread() {
    if (is_sensitive_thread_hook_ != nullptr) {
      return (*is_sensitive_thread_hook_)();
    }
    return false;
  }

  // Set to the read barrier marking entrypoints to be non-null.
  void SetReadBarrierEntrypoints();

  static jobject CreateCompileTimePeer(JNIEnv* env,
                                       const char* name,
                                       bool as_daemon,
                                       jobject thread_group)
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  explicit Thread(bool daemon);
  ~Thread() REQUIRES(!Locks::mutator_lock_, !Locks::thread_suspend_count_lock_);
  void Destroy();

  // Attaches the calling native thread to the runtime, returning the new native peer.
  // Used to implement JNI AttachCurrentThread and AttachCurrentThreadAsDaemon calls.
  template <typename PeerAction>
  static Thread* Attach(const char* thread_name,
                        bool as_daemon,
                        PeerAction p);

  void CreatePeer(const char* name, bool as_daemon, jobject thread_group);

  template<bool kTransactionActive>
  static void InitPeer(ScopedObjectAccessAlreadyRunnable& soa,
                       ObjPtr<mirror::Object> peer,
                       jboolean thread_is_daemon,
                       jobject thread_group,
                       jobject thread_name,
                       jint thread_priority)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Avoid use, callers should use SetState. Used only by SignalCatcher::HandleSigQuit, ~Thread and
  // Dbg::ManageDeoptimization.
  ThreadState SetStateUnsafe(ThreadState new_state) {
    ThreadState old_state = GetState();
    if (old_state == kRunnable && new_state != kRunnable) {
      // Need to run pending checkpoint and suspend barriers. Run checkpoints in runnable state in
      // case they need to use a ScopedObjectAccess. If we are holding the mutator lock and a SOA
      // attempts to TransitionFromSuspendedToRunnable, it results in a deadlock.
      TransitionToSuspendedAndRunCheckpoints(new_state);
      // Since we transitioned to a suspended state, check the pass barrier requests.
      PassActiveSuspendBarriers();
    } else {
      tls32_.state_and_flags.as_struct.state = new_state;
    }
    return old_state;
  }

  void VerifyStackImpl() REQUIRES_SHARED(Locks::mutator_lock_);

  void DumpState(std::ostream& os) const REQUIRES_SHARED(Locks::mutator_lock_);
  void DumpStack(std::ostream& os,
                 bool dump_native_stack = true,
                 BacktraceMap* backtrace_map = nullptr,
                 bool force_dump_stack = false) const
      REQUIRES(!Locks::thread_suspend_count_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Out-of-line conveniences for debugging in gdb.
  static Thread* CurrentFromGdb();  // Like Thread::Current.
  // Like Thread::Dump(std::cerr).
  void DumpFromGdb() const REQUIRES_SHARED(Locks::mutator_lock_);

  static void* CreateCallback(void* arg);

  void HandleUncaughtExceptions(ScopedObjectAccessAlreadyRunnable& soa)
      REQUIRES_SHARED(Locks::mutator_lock_);
  void RemoveFromThreadGroup(ScopedObjectAccessAlreadyRunnable& soa)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Initialize a thread.
  //
  // The third parameter is not mandatory. If given, the thread will use this JNIEnvExt. In case
  // Init succeeds, this means the thread takes ownership of it. If Init fails, it is the caller's
  // responsibility to destroy the given JNIEnvExt. If the parameter is null, Init will try to
  // create a JNIEnvExt on its own (and potentially fail at that stage, indicated by a return value
  // of false).
  bool Init(ThreadList*, JavaVMExt*, JNIEnvExt* jni_env_ext = nullptr)
      REQUIRES(Locks::runtime_shutdown_lock_);
  void InitCardTable();
  void InitCpu();
  void CleanupCpu();
  void InitTlsEntryPoints();
  void InitTid();
  void InitPthreadKeySelf();
  bool InitStackHwm();

  void SetUpAlternateSignalStack();
  void TearDownAlternateSignalStack();

  ALWAYS_INLINE void TransitionToSuspendedAndRunCheckpoints(ThreadState new_state)
      REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_);

  ALWAYS_INLINE void PassActiveSuspendBarriers()
      REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_);

  // Registers the current thread as the jit sensitive thread. Should be called just once.
  static void SetJitSensitiveThread() {
    if (jit_sensitive_thread_ == nullptr) {
      jit_sensitive_thread_ = Thread::Current();
    } else {
      LOG(WARNING) << "Attempt to set the sensitive thread twice. Tid:"
          << Thread::Current()->GetTid();
    }
  }

  static void SetSensitiveThreadHook(bool (*is_sensitive_thread_hook)()) {
    is_sensitive_thread_hook_ = is_sensitive_thread_hook;
  }

  bool ModifySuspendCountInternal(Thread* self,
                                  int delta,
                                  AtomicInteger* suspend_barrier,
                                  SuspendReason reason)
      WARN_UNUSED
      REQUIRES(Locks::thread_suspend_count_lock_);

  // Runs a single checkpoint function. If there are no more pending checkpoint functions it will
  // clear the kCheckpointRequest flag. The caller is responsible for calling this in a loop until
  // the kCheckpointRequest flag is cleared.
  void RunCheckpointFunction();
  void RunEmptyCheckpoint();

  bool PassActiveSuspendBarriers(Thread* self)
      REQUIRES(!Locks::thread_suspend_count_lock_);

  // Install the protected region for implicit stack checks.
  void InstallImplicitProtection();

  template <bool kPrecise>
  void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);

  static bool IsAotCompiler();

  // 32 bits of atomically changed state and flags. Keeping as 32 bits allows and atomic CAS to
  // change from being Suspended to Runnable without a suspend request occurring.
  union PACKED(4) StateAndFlags {
    StateAndFlags() {}
    struct PACKED(4) {
      // Bitfield of flag values. Must be changed atomically so that flag values aren't lost. See
      // ThreadFlags for bit field meanings.
      volatile uint16_t flags;
      // Holds the ThreadState. May be changed non-atomically between Suspended (ie not Runnable)
      // transitions. Changing to Runnable requires that the suspend_request be part of the atomic
      // operation. If a thread is suspended and a suspend_request is present, a thread may not
      // change to Runnable as a GC or other operation is in progress.
      volatile uint16_t state;
    } as_struct;
    AtomicInteger as_atomic_int;
    volatile int32_t as_int;

   private:
    // gcc does not handle struct with volatile member assignments correctly.
    // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47409
    DISALLOW_COPY_AND_ASSIGN(StateAndFlags);
  };
  static_assert(sizeof(StateAndFlags) == sizeof(int32_t), "Weird state_and_flags size");

  static void ThreadExitCallback(void* arg);

  // Maximum number of suspend barriers.
  static constexpr uint32_t kMaxSuspendBarriers = 3;

  // Has Thread::Startup been called?
  static bool is_started_;

  // TLS key used to retrieve the Thread*.
  static pthread_key_t pthread_key_self_;

  // Used to notify threads that they should attempt to resume, they will suspend again if
  // their suspend count is > 0.
  static ConditionVariable* resume_cond_ GUARDED_BY(Locks::thread_suspend_count_lock_);

  // Hook passed by framework which returns true
  // when StrictMode events are traced for the current thread.
  static bool (*is_sensitive_thread_hook_)();
  // Stores the jit sensitive thread (which for now is the UI thread).
  static Thread* jit_sensitive_thread_;

  /***********************************************************************************************/
  // Thread local storage. Fields are grouped by size to enable 32 <-> 64 searching to account for
  // pointer size differences. To encourage shorter encoding, more frequently used values appear
  // first if possible.
  /***********************************************************************************************/

  struct PACKED(4) tls_32bit_sized_values {
    // We have no control over the size of 'bool', but want our boolean fields
    // to be 4-byte quantities.
    typedef uint32_t bool32_t;

    explicit tls_32bit_sized_values(bool is_daemon) :
      suspend_count(0), debug_suspend_count(0), thin_lock_thread_id(0), tid(0),
      daemon(is_daemon), throwing_OutOfMemoryError(false), no_thread_suspension(0),
      thread_exit_check_count(0), handling_signal_(false),
      is_transitioning_to_runnable(false), ready_for_debug_invoke(false),
      debug_method_entry_(false), is_gc_marking(false), weak_ref_access_enabled(true),
      disable_thread_flip_count(0), user_code_suspend_count(0) {
    }

    union StateAndFlags state_and_flags;
    static_assert(sizeof(union StateAndFlags) == sizeof(int32_t),
                  "Size of state_and_flags and int32 are different");

    // A non-zero value is used to tell the current thread to enter a safe point
    // at the next poll.
    int suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);

    // How much of 'suspend_count_' is by request of the debugger, used to set things right
    // when the debugger detaches. Must be <= suspend_count_.
    int debug_suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);

    // Thin lock thread id. This is a small integer used by the thin lock implementation.
    // This is not to be confused with the native thread's tid, nor is it the value returned
    // by java.lang.Thread.getId --- this is a distinct value, used only for locking. One
    // important difference between this id and the ids visible to managed code is that these
    // ones get reused (to ensure that they fit in the number of bits available).
    uint32_t thin_lock_thread_id;

    // System thread id.
    uint32_t tid;

    // Is the thread a daemon?
    const bool32_t daemon;

    // A boolean telling us whether we're recursively throwing OOME.
    bool32_t throwing_OutOfMemoryError;

    // A positive value implies we're in a region where thread suspension isn't expected.
    uint32_t no_thread_suspension;

    // How many times has our pthread key's destructor been called?
    uint32_t thread_exit_check_count;

    // True if signal is being handled by this thread.
    bool32_t handling_signal_;

    // True if the thread is in TransitionFromSuspendedToRunnable(). This is used to distinguish the
    // non-runnable threads (eg. kNative, kWaiting) that are about to transition to runnable from
    // the rest of them.
    bool32_t is_transitioning_to_runnable;

    // True if the thread has been suspended by a debugger event. This is
    // used to invoke method from the debugger which is only allowed when
    // the thread is suspended by an event.
    bool32_t ready_for_debug_invoke;

    // True if the thread enters a method. This is used to detect method entry
    // event for the debugger.
    bool32_t debug_method_entry_;

    // True if the GC is in the marking phase. This is used for the CC collector only. This is
    // thread local so that we can simplify the logic to check for the fast path of read barriers of
    // GC roots.
    bool32_t is_gc_marking;

    // Thread "interrupted" status; stays raised until queried or thrown.
    Atomic<bool32_t> interrupted;

    // True if the thread is allowed to access a weak ref (Reference::GetReferent() and system
    // weaks) and to potentially mark an object alive/gray. This is used for concurrent reference
    // processing of the CC collector only. This is thread local so that we can enable/disable weak
    // ref access by using a checkpoint and avoid a race around the time weak ref access gets
    // disabled and concurrent reference processing begins (if weak ref access is disabled during a
    // pause, this is not an issue.) Other collectors use Runtime::DisallowNewSystemWeaks() and
    // ReferenceProcessor::EnableSlowPath().
    bool32_t weak_ref_access_enabled;

    // A thread local version of Heap::disable_thread_flip_count_. This keeps track of how many
    // levels of (nested) JNI critical sections the thread is in and is used to detect a nested JNI
    // critical section enter.
    uint32_t disable_thread_flip_count;

    // How much of 'suspend_count_' is by request of user code, used to distinguish threads
    // suspended by the runtime from those suspended by user code.
    // This should have GUARDED_BY(Locks::user_code_suspension_lock_) but auto analysis cannot be
    // told that AssertHeld should be good enough.
    int user_code_suspend_count GUARDED_BY(Locks::thread_suspend_count_lock_);
  } tls32_;

  struct PACKED(8) tls_64bit_sized_values {
    tls_64bit_sized_values() : trace_clock_base(0) {
    }

    // The clock base used for tracing.
    uint64_t trace_clock_base;

    RuntimeStats stats;
  } tls64_;

  struct PACKED(sizeof(void*)) tls_ptr_sized_values {
      tls_ptr_sized_values() : card_table(nullptr), exception(nullptr), stack_end(nullptr),
      managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), tmp_jni_env(nullptr),
      self(nullptr), opeer(nullptr), jpeer(nullptr), stack_begin(nullptr), stack_size(0),
      deps_or_stack_trace_sample(), wait_next(nullptr), monitor_enter_object(nullptr),
      top_handle_scope(nullptr), class_loader_override(nullptr), long_jump_context(nullptr),
      instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr),
      stacked_shadow_frame_record(nullptr), deoptimization_context_stack(nullptr),
      frame_id_to_shadow_frame(nullptr), name(nullptr), pthread_self(0),
      last_no_thread_suspension_cause(nullptr), checkpoint_function(nullptr),
      thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr),
      thread_local_limit(nullptr),
      thread_local_objects(0), mterp_current_ibase(nullptr), mterp_default_ibase(nullptr),
      mterp_alt_ibase(nullptr), thread_local_alloc_stack_top(nullptr),
      thread_local_alloc_stack_end(nullptr),
      flip_function(nullptr), method_verifier(nullptr), thread_local_mark_stack(nullptr),
      async_exception(nullptr) {
      std::fill(held_mutexes, held_mutexes + kLockLevelCount, nullptr);
    }

    // The biased card table, see CardTable for details.
    uint8_t* card_table;

    // The pending exception or null.
    mirror::Throwable* exception;

    // The end of this thread's stack. This is the lowest safely-addressable address on the stack.
    // We leave extra space so there's room for the code that throws StackOverflowError.
    uint8_t* stack_end;

    // The top of the managed stack often manipulated directly by compiler generated code.
    ManagedStack managed_stack;

    // In certain modes, setting this to 0 will trigger a SEGV and thus a suspend check.  It is
    // normally set to the address of itself.
    uintptr_t* suspend_trigger;

    // Every thread may have an associated JNI environment
    JNIEnvExt* jni_env;

    // Temporary storage to transfer a pre-allocated JNIEnvExt from the creating thread to the
    // created thread.
    JNIEnvExt* tmp_jni_env;

    // Initialized to "this". On certain architectures (such as x86) reading off of Thread::Current
    // is easy but getting the address of Thread::Current is hard. This field can be read off of
    // Thread::Current to give the address.
    Thread* self;

    // Our managed peer (an instance of java.lang.Thread). The jobject version is used during thread
    // start up, until the thread is registered and the local opeer_ is used.
    mirror::Object* opeer;
    jobject jpeer;

    // The "lowest addressable byte" of the stack.
    uint8_t* stack_begin;

    // Size of the stack.
    size_t stack_size;

    // Sampling profiler and AOT verification cannot happen on the same run, so we share
    // the same entry for the stack trace and the verifier deps.
    union DepsOrStackTraceSample {
      DepsOrStackTraceSample() {
        verifier_deps = nullptr;
        stack_trace_sample = nullptr;
      }
      // Pointer to previous stack trace captured by sampling profiler.
      std::vector<ArtMethod*>* stack_trace_sample;
      // When doing AOT verification, per-thread VerifierDeps.
      verifier::VerifierDeps* verifier_deps;
    } deps_or_stack_trace_sample;

    // The next thread in the wait set this thread is part of or null if not waiting.
    Thread* wait_next;

    // If we're blocked in MonitorEnter, this is the object we're trying to lock.
    mirror::Object* monitor_enter_object;

    // Top of linked list of handle scopes or null for none.
    BaseHandleScope* top_handle_scope;

    // Needed to get the right ClassLoader in JNI_OnLoad, but also
    // useful for testing.
    jobject class_loader_override;

    // Thread local, lazily allocated, long jump context. Used to deliver exceptions.
    Context* long_jump_context;

    // Additional stack used by method instrumentation to store method and return pc values.
    // Stored as a pointer since std::deque is not PACKED.
    std::deque<instrumentation::InstrumentationStackFrame>* instrumentation_stack;

    // JDWP invoke-during-breakpoint support.
    DebugInvokeReq* debug_invoke_req;

    // JDWP single-stepping support.
    SingleStepControl* single_step_control;

    // For gc purpose, a shadow frame record stack that keeps track of:
    // 1) shadow frames under construction.
    // 2) deoptimization shadow frames.
    StackedShadowFrameRecord* stacked_shadow_frame_record;

    // Deoptimization return value record stack.
    DeoptimizationContextRecord* deoptimization_context_stack;

    // For debugger, a linked list that keeps the mapping from frame_id to shadow frame.
    // Shadow frames may be created before deoptimization happens so that the debugger can
    // set local values there first.
    FrameIdToShadowFrame* frame_id_to_shadow_frame;

    // A cached copy of the java.lang.Thread's name.
    std::string* name;

    // A cached pthread_t for the pthread underlying this Thread*.
    pthread_t pthread_self;

    // If no_thread_suspension_ is > 0, what is causing that assertion.
    const char* last_no_thread_suspension_cause;

    // Pending checkpoint function or null if non-pending. If this checkpoint is set and someone\
    // requests another checkpoint, it goes to the checkpoint overflow list.
    Closure* checkpoint_function GUARDED_BY(Locks::thread_suspend_count_lock_);

    // Pending barriers that require passing or NULL if non-pending. Installation guarding by
    // Locks::thread_suspend_count_lock_.
    // They work effectively as art::Barrier, but implemented directly using AtomicInteger and futex
    // to avoid additional cost of a mutex and a condition variable, as used in art::Barrier.
    AtomicInteger* active_suspend_barriers[kMaxSuspendBarriers];

    // Thread-local allocation pointer. Moved here to force alignment for thread_local_pos on ARM.
    uint8_t* thread_local_start;

    // thread_local_pos and thread_local_end must be consecutive for ldrd and are 8 byte aligned for
    // potentially better performance.
    uint8_t* thread_local_pos;
    uint8_t* thread_local_end;

    // Thread local limit is how much we can expand the thread local buffer to, it is greater or
    // equal to thread_local_end.
    uint8_t* thread_local_limit;

    size_t thread_local_objects;

    // Entrypoint function pointers.
    // TODO: move this to more of a global offset table model to avoid per-thread duplication.
    JniEntryPoints jni_entrypoints;
    QuickEntryPoints quick_entrypoints;

    // Mterp jump table bases.
    void* mterp_current_ibase;
    void* mterp_default_ibase;
    void* mterp_alt_ibase;

    // There are RosAlloc::kNumThreadLocalSizeBrackets thread-local size brackets per thread.
    void* rosalloc_runs[kNumRosAllocThreadLocalSizeBracketsInThread];

    // Thread-local allocation stack data/routines.
    StackReference<mirror::Object>* thread_local_alloc_stack_top;
    StackReference<mirror::Object>* thread_local_alloc_stack_end;

    // Support for Mutex lock hierarchy bug detection.
    BaseMutex* held_mutexes[kLockLevelCount];

    // The function used for thread flip.
    Closure* flip_function;

    // Current method verifier, used for root marking.
    verifier::MethodVerifier* method_verifier;

    // Thread-local mark stack for the concurrent copying collector.
    gc::accounting::AtomicStack<mirror::Object>* thread_local_mark_stack;

    // The pending async-exception or null.
    mirror::Throwable* async_exception;
  } tlsPtr_;

  // Guards the 'wait_monitor_' members.
  Mutex* wait_mutex_ DEFAULT_MUTEX_ACQUIRED_AFTER;

  // Condition variable waited upon during a wait.
  ConditionVariable* wait_cond_ GUARDED_BY(wait_mutex_);
  // Pointer to the monitor lock we're currently waiting on or null if not waiting.
  Monitor* wait_monitor_ GUARDED_BY(wait_mutex_);

  // Debug disable read barrier count, only is checked for debug builds and only in the runtime.
  uint8_t debug_disallow_read_barrier_ = 0;

  // Note that it is not in the packed struct, may not be accessed for cross compilation.
  uintptr_t poison_object_cookie_ = 0;

  // Pending extra checkpoints if checkpoint_function_ is already used.
  std::list<Closure*> checkpoint_overflow_ GUARDED_BY(Locks::thread_suspend_count_lock_);

  // Custom TLS field that can be used by plugins.
  // TODO: Generalize once we have more plugins.
  void* custom_tls_;

  // True if the thread is allowed to call back into java (for e.g. during class resolution).
  // By default this is true.
  bool can_call_into_java_;

  friend class Dbg;  // For SetStateUnsafe.
  friend class gc::collector::SemiSpace;  // For getting stack traces.
  friend class Runtime;  // For CreatePeer.
  friend class QuickExceptionHandler;  // For dumping the stack.
  friend class ScopedThreadStateChange;
  friend class StubTest;  // For accessing entrypoints.
  friend class ThreadList;  // For ~Thread and Destroy.

  friend class EntrypointsOrderTest;  // To test the order of tls entries.

  DISALLOW_COPY_AND_ASSIGN(Thread);
};

class SCOPED_CAPABILITY ScopedAssertNoThreadSuspension {
 public:
  ALWAYS_INLINE ScopedAssertNoThreadSuspension(const char* cause,
                                               bool enabled = true)
      ACQUIRE(Roles::uninterruptible_)
      : enabled_(enabled) {
    if (!enabled_) {
      return;
    }
    if (kIsDebugBuild) {
      self_ = Thread::Current();
      old_cause_ = self_->StartAssertNoThreadSuspension(cause);
    } else {
      Roles::uninterruptible_.Acquire();  // No-op.
    }
  }
  ALWAYS_INLINE ~ScopedAssertNoThreadSuspension() RELEASE(Roles::uninterruptible_) {
    if (!enabled_) {
      return;
    }
    if (kIsDebugBuild) {
      self_->EndAssertNoThreadSuspension(old_cause_);
    } else {
      Roles::uninterruptible_.Release();  // No-op.
    }
  }

 private:
  Thread* self_;
  const bool enabled_;
  const char* old_cause_;
};

class ScopedStackedShadowFramePusher {
 public:
  ScopedStackedShadowFramePusher(Thread* self, ShadowFrame* sf, StackedShadowFrameType type)
    : self_(self), type_(type) {
    self_->PushStackedShadowFrame(sf, type);
  }
  ~ScopedStackedShadowFramePusher() {
    self_->PopStackedShadowFrame(type_);
  }

 private:
  Thread* const self_;
  const StackedShadowFrameType type_;

  DISALLOW_COPY_AND_ASSIGN(ScopedStackedShadowFramePusher);
};

// Only works for debug builds.
class ScopedDebugDisallowReadBarriers {
 public:
  explicit ScopedDebugDisallowReadBarriers(Thread* self) : self_(self) {
    self_->ModifyDebugDisallowReadBarrier(1);
  }
  ~ScopedDebugDisallowReadBarriers() {
    self_->ModifyDebugDisallowReadBarrier(-1);
  }

 private:
  Thread* const self_;
};

class ScopedTransitioningToRunnable : public ValueObject {
 public:
  explicit ScopedTransitioningToRunnable(Thread* self)
      : self_(self) {
    DCHECK_EQ(self, Thread::Current());
    if (kUseReadBarrier) {
      self_->SetIsTransitioningToRunnable(true);
    }
  }

  ~ScopedTransitioningToRunnable() {
    if (kUseReadBarrier) {
      self_->SetIsTransitioningToRunnable(false);
    }
  }

 private:
  Thread* const self_;
};

class ThreadLifecycleCallback {
 public:
  virtual ~ThreadLifecycleCallback() {}

  virtual void ThreadStart(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
  virtual void ThreadDeath(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
};

std::ostream& operator<<(std::ostream& os, const Thread& thread);
std::ostream& operator<<(std::ostream& os, const StackedShadowFrameType& thread);

}  // namespace art

#endif  // ART_RUNTIME_THREAD_H_
