sssssss79


static OnLoadEntry_t lookup_jvm_on_load(AgentLibrary* agent) {
  const char *on_load_symbols[] = JVM_ONLOAD_SYMBOLS;
  return lookup_on_load(agent, on_load_symbols, sizeof(on_load_symbols) / sizeof(char*));
}
static OnLoadEntry_t lookup_agent_on_load(AgentLibrary* agent) {
  const char *on_load_symbols[] = AGENT_ONLOAD_SYMBOLS;
  return lookup_on_load(agent, on_load_symbols, sizeof(on_load_symbols) / sizeof(char*));
}
void Threads::convert_vm_init_libraries_to_agents() {
  AgentLibrary* agent;
  AgentLibrary* next;
  for (agent = Arguments::libraries(); agent != NULL; agent = next) {
    next = agent->next();  // cache the next agent now as this agent may get moved off this list
    OnLoadEntry_t on_load_entry = lookup_jvm_on_load(agent);
    if (on_load_entry == NULL) {
      on_load_entry = lookup_agent_on_load(agent);
      if (on_load_entry != NULL) {
        Arguments::convert_library_to_agent(agent);
      } else {
        vm_exit_during_initialization("Could not find JVM_OnLoad or Agent_OnLoad function in the library", agent->name());
      }
    }
  }
}
void Threads::create_vm_init_agents() {
  extern struct JavaVM_ main_vm;
  AgentLibrary* agent;
  JvmtiExport::enter_onload_phase();
  for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
    OnLoadEntry_t  on_load_entry = lookup_agent_on_load(agent);
    if (on_load_entry != NULL) {
      jint err = (*on_load_entry)(&main_vm, agent->options(), NULL);
      if (err != JNI_OK) {
        vm_exit_during_initialization("agent library failed to init", agent->name());
      }
    } else {
      vm_exit_during_initialization("Could not find Agent_OnLoad function in the agent library", agent->name());
    }
  }
  JvmtiExport::enter_primordial_phase();
}
extern "C" {
  typedef void (JNICALL *Agent_OnUnload_t)(JavaVM *);
}
void Threads::shutdown_vm_agents() {
  const char *on_unload_symbols[] = AGENT_ONUNLOAD_SYMBOLS;
  size_t num_symbol_entries = ARRAY_SIZE(on_unload_symbols);
  extern struct JavaVM_ main_vm;
  for (AgentLibrary* agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
    Agent_OnUnload_t unload_entry = CAST_TO_FN_PTR(Agent_OnUnload_t,
      os::find_agent_function(agent,
      false,
      on_unload_symbols,
      num_symbol_entries));
    if (unload_entry != NULL) {
      JavaThread* thread = JavaThread::current();
      ThreadToNativeFromVM ttn(thread);
      HandleMark hm(thread);
      (*unload_entry)(&main_vm);
    }
  }
}
void Threads::create_vm_init_libraries() {
  extern struct JavaVM_ main_vm;
  AgentLibrary* agent;
  for (agent = Arguments::libraries(); agent != NULL; agent = agent->next()) {
    OnLoadEntry_t on_load_entry = lookup_jvm_on_load(agent);
    if (on_load_entry != NULL) {
      JavaThread* thread = JavaThread::current();
      ThreadToNativeFromVM ttn(thread);
      HandleMark hm(thread);
      jint err = (*on_load_entry)(&main_vm, agent->options(), NULL);
      if (err != JNI_OK) {
        vm_exit_during_initialization("-Xrun library failed to init", agent->name());
      }
    } else {
      vm_exit_during_initialization("Could not find JVM_OnLoad function in -Xrun library", agent->name());
    }
  }
}
JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) {
  assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
  JavaThread* java_thread = NULL;
  for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
    oop tobj = thread->threadObj();
    if (!thread->is_exiting() &&
        tobj != NULL &&
        java_tid == java_lang_Thread::thread_id(tobj)) {
      java_thread = thread;
      break;
    }
  }
  return java_thread;
}
void JavaThread::invoke_shutdown_hooks() {
  HandleMark hm(this);
  if (this->has_pending_exception()) {
    this->clear_pending_exception();
  }
  EXCEPTION_MARK;
  Klass* k =
    SystemDictionary::resolve_or_null(vmSymbols::java_lang_Shutdown(),
                                      THREAD);
  if (k != NULL) {
    instanceKlassHandle shutdown_klass (THREAD, k);
    JavaValue result(T_VOID);
    JavaCalls::call_static(&result,
                           shutdown_klass,
                           vmSymbols::shutdown_method_name(),
                           vmSymbols::void_method_signature(),
                           THREAD);
  }
  CLEAR_PENDING_EXCEPTION;
}
bool Threads::destroy_vm() {
  JavaThread* thread = JavaThread::current();
#ifdef ASSERT
  _vm_complete = false;
#endif
  { MutexLocker nu(Threads_lock);
    while (Threads::number_of_non_daemon_threads() > 1 )
      Threads_lock->wait(!Mutex::_no_safepoint_check_flag, 0,
                         Mutex::_as_suspend_equivalent_flag);
  }
  EventShutdown e;
  if (e.should_commit()) {
    e.set_reason("No remaining non-daemon Java threads");
    e.commit();
  }
  if (ShowMessageBoxOnError && is_error_reported()) {
    os::infinite_sleep();
  }
  os::wait_for_keypress_at_exit();
  if (JDK_Version::is_jdk12x_version()) {
    HandleMark rm(thread);
    Universe::run_finalizers_on_exit();
  } else {
    thread->invoke_shutdown_hooks();
  }
  before_exit(thread);
  thread->exit(true);
  {
    MutexLocker ml(Heap_lock);
    VMThread::wait_for_vm_thread_exit();
    assert(SafepointSynchronize::is_at_safepoint(), "VM thread should exit at Safepoint");
    VMThread::destroy();
  }
#if defined(COMPILER2) && !defined(PRODUCT)
  IdealGraphPrinter::clean_up();
#endif
#ifndef PRODUCT
  TraceJNICalls = false;
  TraceJVMCalls = false;
  TraceRuntimeCalls = false;
#endif
  VM_Exit::set_vm_exited();
  notify_vm_shutdown();
  delete thread;
  exit_globals();
  return true;
}
jboolean Threads::is_supported_jni_version_including_1_1(jint version) {
  if (version == JNI_VERSION_1_1) return JNI_TRUE;
  return is_supported_jni_version(version);
}
jboolean Threads::is_supported_jni_version(jint version) {
  if (version == JNI_VERSION_1_2) return JNI_TRUE;
  if (version == JNI_VERSION_1_4) return JNI_TRUE;
  if (version == JNI_VERSION_1_6) return JNI_TRUE;
  if (version == JNI_VERSION_1_8) return JNI_TRUE;
  return JNI_FALSE;
}
void Threads::add(JavaThread* p, bool force_daemon) {
  assert_locked_or_safepoint(Threads_lock);
  p->initialize_queues();
  p->set_next(_thread_list);
  _thread_list = p;
  _number_of_threads++;
  oop threadObj = p->threadObj();
  bool daemon = true;
  if ((!force_daemon) && (threadObj == NULL || !java_lang_Thread::is_daemon(threadObj))) {
    _number_of_non_daemon_threads++;
    daemon = false;
  }
  ThreadService::add_thread(p, daemon);
  Events::log(p, "Thread added: " INTPTR_FORMAT, p);
}
void Threads::remove(JavaThread* p) {
  { MutexLocker ml(Threads_lock);
    assert(includes(p), "p must be present");
    JavaThread* current = _thread_list;
    JavaThread* prev    = NULL;
    while (current != p) {
      prev    = current;
      current = current->next();
    }
    if (prev) {
      prev->set_next(current->next());
    } else {
      _thread_list = p->next();
    }
    _number_of_threads--;
    oop threadObj = p->threadObj();
    bool daemon = true;
    if (threadObj == NULL || !java_lang_Thread::is_daemon(threadObj)) {
      _number_of_non_daemon_threads--;
      daemon = false;
      if (number_of_non_daemon_threads() == 1)
        Threads_lock->notify_all();
    }
    ThreadService::remove_thread(p, daemon);
    p->set_terminated_value();
  } // unlock Threads_lock
  Events::log(p, "Thread exited: " INTPTR_FORMAT, p);
}
bool Threads::includes(JavaThread* p) {
  assert(Threads_lock->is_locked(), "sanity check");
  ALL_JAVA_THREADS(q) {
    if (q == p ) {
      return true;
    }
  }
  return false;
}
void Threads::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
  ALL_JAVA_THREADS(p) {
    p->oops_do(f, cld_f, cf);
  }
  VMThread::vm_thread()->oops_do(f, cld_f, cf);
}
void Threads::possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
  SharedHeap* sh = SharedHeap::heap();
  bool is_par = sh->n_par_threads() > 0;
  assert(!is_par ||
         (SharedHeap::heap()->n_par_threads() ==
          SharedHeap::heap()->workers()->active_workers()), "Mismatch");
  int cp = SharedHeap::heap()->strong_roots_parity();
  ALL_JAVA_THREADS(p) {
    if (p->claim_oops_do(is_par, cp)) {
      p->oops_do(f, cld_f, cf);
    }
  }
  VMThread* vmt = VMThread::vm_thread();
  if (vmt->claim_oops_do(is_par, cp)) {
    vmt->oops_do(f, cld_f, cf);
  }
}
#if INCLUDE_ALL_GCS
void Threads::create_thread_roots_tasks(GCTaskQueue* q) {
  ALL_JAVA_THREADS(p) {
    q->enqueue(new ThreadRootsTask(p));
  }
  q->enqueue(new ThreadRootsTask(VMThread::vm_thread()));
}
void Threads::create_thread_roots_marking_tasks(GCTaskQueue* q) {
  ALL_JAVA_THREADS(p) {
    q->enqueue(new ThreadRootsMarkingTask(p));
  }
  q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread()));
}
#endif // INCLUDE_ALL_GCS
void Threads::nmethods_do(CodeBlobClosure* cf) {
  ALL_JAVA_THREADS(p) {
    p->nmethods_do(cf);
  }
  VMThread::vm_thread()->nmethods_do(cf);
}
void Threads::metadata_do(void f(Metadata*)) {
  ALL_JAVA_THREADS(p) {
    p->metadata_do(f);
  }
}
void Threads::gc_epilogue() {
  ALL_JAVA_THREADS(p) {
    p->gc_epilogue();
  }
}
void Threads::gc_prologue() {
  ALL_JAVA_THREADS(p) {
    p->gc_prologue();
  }
}
void Threads::deoptimized_wrt_marked_nmethods() {
  ALL_JAVA_THREADS(p) {
    p->deoptimized_wrt_marked_nmethods();
  }
}
GrowableArray<JavaThread*>* Threads::get_pending_threads(int count,
  address monitor, bool doLock) {
  assert(doLock || SafepointSynchronize::is_at_safepoint(),
    "must grab Threads_lock or be at safepoint");
  GrowableArray<JavaThread*>* result = new GrowableArray<JavaThread*>(count);
  int i = 0;
  {
    MutexLockerEx ml(doLock ? Threads_lock : NULL);
    ALL_JAVA_THREADS(p) {
      if (p->is_Compiler_thread()) continue;
      address pending = (address)p->current_pending_monitor();
      if (pending == monitor) {             // found a match
        if (i < count) result->append(p);   // save the first count matches
        i++;
      }
    }
  }
  return result;
}
JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock) {
  assert(doLock ||
         Threads_lock->owned_by_self() ||
         SafepointSynchronize::is_at_safepoint(),
         "must grab Threads_lock or be at safepoint");
  if (owner == NULL) return NULL;
  {
    MutexLockerEx ml(doLock ? Threads_lock : NULL);
    ALL_JAVA_THREADS(p) {
      if (owner == (address)p) return p;
    }
  }
  if (UseHeavyMonitors) return NULL;
  JavaThread* the_owner = NULL;
  {
    MutexLockerEx ml(doLock ? Threads_lock : NULL);
    ALL_JAVA_THREADS(q) {
      if (q->is_lock_owned(owner)) {
        the_owner = q;
        break;
      }
    }
  }
  return the_owner;
}
void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks) {
  char buf[32];
  st->print_cr("%s", os::local_time_string(buf, sizeof(buf)));
  st->print_cr("Full thread dump %s (%s %s):",
                Abstract_VM_Version::vm_name(),
                Abstract_VM_Version::vm_release(),
                Abstract_VM_Version::vm_info_string()
               );
  st->cr();
#if INCLUDE_ALL_GCS
  ConcurrentLocksDump concurrent_locks;
  if (print_concurrent_locks) {
    concurrent_locks.dump_at_safepoint();
  }
#endif // INCLUDE_ALL_GCS
  ALL_JAVA_THREADS(p) {
    ResourceMark rm;
    p->print_on(st);
    if (print_stacks) {
      if (internal_format) {
        p->trace_stack();
      } else {
        p->print_stack_on(st);
      }
    }
    st->cr();
#if INCLUDE_ALL_GCS
    if (print_concurrent_locks) {
      concurrent_locks.print_locks_on(p, st);
    }
#endif // INCLUDE_ALL_GCS
  }
  VMThread::vm_thread()->print_on(st);
  st->cr();
  Universe::heap()->print_gc_threads_on(st);
  WatcherThread* wt = WatcherThread::watcher_thread();
  if (wt != NULL) {
    wt->print_on(st);
    st->cr();
  }
  CompileBroker::print_compiler_threads_on(st);
  st->flush();
}
void Threads::print_on_error(outputStream* st, Thread* current, char* buf, int buflen) {
  bool found_current = false;
  st->print_cr("Java Threads: ( => current thread )");
  ALL_JAVA_THREADS(thread) {
    bool is_current = (current == thread);
    found_current = found_current || is_current;
    st->print("%s", is_current ? "=>" : "  ");
    st->print(PTR_FORMAT, thread);
    st->print(" ");
    thread->print_on_error(st, buf, buflen);
    st->cr();
  }
  st->cr();
  st->print_cr("Other Threads:");
  if (VMThread::vm_thread()) {
    bool is_current = (current == VMThread::vm_thread());
    found_current = found_current || is_current;
    st->print("%s", current == VMThread::vm_thread() ? "=>" : "  ");
    st->print(PTR_FORMAT, VMThread::vm_thread());
    st->print(" ");
    VMThread::vm_thread()->print_on_error(st, buf, buflen);
    st->cr();
  }
  WatcherThread* wt = WatcherThread::watcher_thread();
  if (wt != NULL) {
    bool is_current = (current == wt);
    found_current = found_current || is_current;
    st->print("%s", is_current ? "=>" : "  ");
    st->print(PTR_FORMAT, wt);
    st->print(" ");
    wt->print_on_error(st, buf, buflen);
    st->cr();
  }
  if (!found_current) {
    st->cr();
    st->print("=>" PTR_FORMAT " (exited) ", current);
    current->print_on_error(st, buf, buflen);
    st->cr();
  }
}
typedef volatile int SpinLockT ;
void Thread::SpinAcquire (volatile int * adr, const char * LockName) {
  if (Atomic::cmpxchg (1, adr, 0) == 0) {
     return ;   // normal fast-path return
  }
  TEVENT (SpinAcquire - ctx) ;
  int ctr = 0 ;
  int Yields = 0 ;
  for (;;) {
     while (*adr != 0) {
        ++ctr ;
        if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
           if (Yields > 5) {
             os::naked_short_sleep(1);
           } else {
             os::NakedYield() ;
             ++Yields ;
           }
        } else {
           SpinPause() ;
        }
     }
     if (Atomic::cmpxchg (1, adr, 0) == 0) return ;
  }
}
void Thread::SpinRelease (volatile int * adr) {
  assert (*adr != 0, "invariant") ;
  OrderAccess::fence() ;      // guarantee at least release consistency.
}
typedef volatile intptr_t MutexT ;      // Mux Lock-word
enum MuxBits { LOCKBIT = 1 } ;
void Thread::muxAcquire (volatile intptr_t * Lock, const char * LockName) {
  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
  if (w == 0) return ;
  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
     return ;
  }
  TEVENT (muxAcquire - Contention) ;
  ParkEvent * const Self = Thread::current()->_MuxEvent ;
  assert ((intptr_t(Self) & LOCKBIT) == 0, "invariant") ;
  for (;;) {
     int its = (os::is_MP() ? 100 : 0) + 1 ;
     while (--its >= 0) {
       w = *Lock ;
       if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
          return ;
       }
     }
     Self->reset() ;
     Self->OnList = intptr_t(Lock) ;
     OrderAccess::fence();
     for (;;) {
        w = *Lock ;
        if ((w & LOCKBIT) == 0) {
            if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
                Self->OnList = 0 ;   // hygiene - allows stronger asserts
                return ;
            }
            continue ;      // Interference -- *Lock changed -- Just retry
        }
        assert (w & LOCKBIT, "invariant") ;
        Self->ListNext = (ParkEvent *) (w & ~LOCKBIT );
        if (Atomic::cmpxchg_ptr (intptr_t(Self)|LOCKBIT, Lock, w) == w) break ;
     }
     while (Self->OnList != 0) {
        Self->park() ;
     }
  }
}
void Thread::muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) {
  intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
  if (w == 0) return ;
  if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
    return ;
  }
  TEVENT (muxAcquire - Contention) ;
  ParkEvent * ReleaseAfter = NULL ;
  if (ev == NULL) {
    ev = ReleaseAfter = ParkEvent::Allocate (NULL) ;
  }
  assert ((intptr_t(ev) & LOCKBIT) == 0, "invariant") ;
  for (;;) {
    guarantee (ev->OnList == 0, "invariant") ;
    int its = (os::is_MP() ? 100 : 0) + 1 ;
    while (--its >= 0) {
      w = *Lock ;
      if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
        if (ReleaseAfter != NULL) {
          ParkEvent::Release (ReleaseAfter) ;
        }
        return ;
      }
    }
    ev->reset() ;
    ev->OnList = intptr_t(Lock) ;
    OrderAccess::fence();
    for (;;) {
      w = *Lock ;
      if ((w & LOCKBIT) == 0) {
        if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
          ev->OnList = 0 ;
          if (ReleaseAfter != NULL) {
            ParkEvent::Release (ReleaseAfter) ;
          }
          return ;
        }
        continue ;      // Interference -- *Lock changed -- Just retry
      }
      assert (w & LOCKBIT, "invariant") ;
      ev->ListNext = (ParkEvent *) (w & ~LOCKBIT );
      if (Atomic::cmpxchg_ptr (intptr_t(ev)|LOCKBIT, Lock, w) == w) break ;
    }
    while (ev->OnList != 0) {
      ev->park() ;
    }
  }
}
void Thread::muxRelease (volatile intptr_t * Lock)  {
  for (;;) {
    const intptr_t w = Atomic::cmpxchg_ptr (0, Lock, LOCKBIT) ;
    assert (w & LOCKBIT, "invariant") ;
    if (w == LOCKBIT) return ;
    ParkEvent * List = (ParkEvent *) (w & ~LOCKBIT) ;
    assert (List != NULL, "invariant") ;
    assert (List->OnList == intptr_t(Lock), "invariant") ;
    ParkEvent * nxt = List->ListNext ;
    if (Atomic::cmpxchg_ptr (intptr_t(nxt), Lock, w) != w) {
      continue ;
    }
    List->OnList = 0 ;
    OrderAccess::fence() ;
    List->unpark () ;
    return ;
  }
}
void Threads::verify() {
  ALL_JAVA_THREADS(p) {
    p->verify();
  }
  VMThread* thread = VMThread::vm_thread();
  if (thread != NULL) thread->verify();
}
C:\hotspot-69087d08d473\src\share\vm/runtime/thread.hpp
#ifndef SHARE_VM_RUNTIME_THREAD_HPP
#define SHARE_VM_RUNTIME_THREAD_HPP
#include "memory/allocation.hpp"
#include "memory/threadLocalAllocBuffer.hpp"
#include "oops/oop.hpp"
#include "prims/jni.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/frame.hpp"
#include "runtime/javaFrameAnchor.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/park.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "runtime/thread_ext.hpp"
#include "runtime/unhandledOops.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/macros.hpp"
#include "utilities/top.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/dirtyCardQueue.hpp"
#include "gc_implementation/g1/satbQueue.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef TARGET_ARCH_zero
# include "stack_zero.hpp"
#endif
#if INCLUDE_JFR
#include "jfr/support/jfrThreadExtension.hpp"
#endif
class ThreadSafepointState;
class ThreadProfiler;
class JvmtiThreadState;
class JvmtiGetLoadedClassesClosure;
class ThreadStatistics;
class ConcurrentLocksDump;
class ParkEvent;
class Parker;
class ciEnv;
class CompileThread;
class CompileLog;
class CompileTask;
class CompileQueue;
class CompilerCounters;
class vframeArray;
class DeoptResourceMark;
class jvmtiDeferredLocalVariableSet;
class GCTaskQueue;
class ThreadClosure;
class IdealGraphPrinter;
class Metadata;
template <class T, MEMFLAGS F> class ChunkedList;
typedef ChunkedList<Metadata*, mtInternal> MetadataOnStackBuffer;
DEBUG_ONLY(class ResourceMark;)
class WorkerThread;
class Thread: public ThreadShadow {
  friend class VMStructs;
 private:
 protected:
  void*       _real_malloc_address;
 public:
  void* operator new(size_t size) throw() { return allocate(size, true); }
  void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
    return allocate(size, false); }
  void  operator delete(void* p);
 protected:
   static void* allocate(size_t size, bool throw_excpt, MEMFLAGS flags = mtThread);
 private:
  Monitor* _SR_lock;
 protected:
  enum SuspendFlags {
    _external_suspend       = 0x20000000U, // thread is asked to self suspend
    _ext_suspended          = 0x40000000U, // thread has self-suspended
    _deopt_suspend          = 0x10000000U, // thread needs to self suspend for deopt
    _has_async_exception    = 0x00000001U, // there is a pending async exception
    _critical_native_unlock = 0x00000002U, // Must call back to unlock JNI critical lock
    JFR_ONLY(_trace_flag    = 0x00000004U)  // call jfr tracing
  };
  volatile uint32_t _suspend_flags;
 private:
  int _num_nested_signal;
 public:
  void enter_signal_handler() { _num_nested_signal++; }
  void leave_signal_handler() { _num_nested_signal--; }
  bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
 private:
  static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN;
  JNIHandleBlock* _active_handles;
  JNIHandleBlock* _free_handle_block;
  HandleMark* _last_handle_mark;
  jint _oops_do_parity;
  public:
   void set_last_handle_mark(HandleMark* mark)   { _last_handle_mark = mark; }
   HandleMark* last_handle_mark() const          { return _last_handle_mark; }
  private:
  NOT_PRODUCT(int _allow_safepoint_count;)      // If 0, thread allow a safepoint to happen
  debug_only (int _allow_allocation_count;)     // If 0, the thread is allowed to allocate oops.
  NOT_PRODUCT(bool _skip_gcalot;)               // Should we elide gc-a-lot?
  friend class No_Alloc_Verifier;
  friend class No_Safepoint_Verifier;
  friend class Pause_No_Safepoint_Verifier;
  friend class ThreadLocalStorage;
  friend class GC_locker;
  ThreadLocalAllocBuffer _tlab;                 // Thread-local eden
  jlong _allocated_bytes;                       // Cumulative number of bytes allocated on
  MetadataOnStackBuffer* _metadata_on_stack_buffer;
  JFR_ONLY(DEFINE_THREAD_LOCAL_FIELD_JFR;)      // Thread-local data for jfr
  ThreadExt _ext;
  int   _vm_operation_started_count;            // VM_Operation support
  int   _vm_operation_completed_count;          // VM_Operation support
  ObjectMonitor* _current_pending_monitor;      // ObjectMonitor this thread
  bool _current_pending_monitor_is_from_java;   // locking is from Java code
  ObjectMonitor* _current_waiting_monitor;
 public:
  ObjectMonitor* omFreeList;
  int omFreeCount;                              // length of omFreeList
  int omFreeProvision;                          // reload chunk size
  ObjectMonitor* omInUseList;                   // SLL to track monitors in circulation
  int omInUseCount;                             // length of omInUseList
#ifdef ASSERT
 private:
  bool _visited_for_critical_count;
 public:
  void set_visited_for_critical_count(bool z) { _visited_for_critical_count = z; }
  bool was_visited_for_critical_count() const   { return _visited_for_critical_count; }
#endif
 public:
  enum {
    is_definitely_current_thread = true
  };
  Thread();
  virtual ~Thread();
  void initialize_thread_local_storage();
  virtual void run();
  virtual bool is_VM_thread()       const            { return false; }
  virtual bool is_Java_thread()     const            { return false; }
  virtual bool is_Compiler_thread() const            { return false; }
  virtual bool is_hidden_from_external_view() const  { return false; }
  virtual bool is_jvmti_agent_thread() const         { return false; }
  virtual bool is_GC_task_thread() const             { return false; }
  virtual bool is_Watcher_thread() const             { return false; }
  virtual bool is_ConcurrentGC_thread() const        { return false; }
  virtual bool is_Named_thread() const               { return false; }
  virtual bool is_Worker_thread() const              { return false; }
  virtual WorkerThread* as_Worker_thread() const     { return NULL; }
  virtual char* name() const { return (char*)"Unknown thread"; }
  static inline Thread* current();
  static inline Thread* current_or_null();
  static void set_priority(Thread* thread, ThreadPriority priority);
  static ThreadPriority get_priority(const Thread* const thread);
  static void start(Thread* thread);
  static void interrupt(Thread* thr);
  static bool is_interrupted(Thread* thr, bool clear_interrupted);
  void set_native_thread_name(const char *name) {
    assert(Thread::current() == this, "set_native_thread_name can only be called on the current thread");
    os::set_native_thread_name(name);
  }
  ObjectMonitor** omInUseList_addr()             { return (ObjectMonitor **)&omInUseList; }
  Monitor* SR_lock() const                       { return _SR_lock; }
  bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
  void set_suspend_flag(SuspendFlags f) {
    assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch");
    uint32_t flags;
    do {
      flags = _suspend_flags;
    }
    while (Atomic::cmpxchg((jint)(flags | f),
                           (volatile jint*)&_suspend_flags,
                           (jint)flags) != (jint)flags);
  }
  void clear_suspend_flag(SuspendFlags f) {
    assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch");
    uint32_t flags;
    do {
      flags = _suspend_flags;
    }
    while (Atomic::cmpxchg((jint)(flags & ~f),
                           (volatile jint*)&_suspend_flags,
                           (jint)flags) != (jint)flags);
  }
  void set_has_async_exception() {
    set_suspend_flag(_has_async_exception);
  }
  void clear_has_async_exception() {
    clear_suspend_flag(_has_async_exception);
  }
  bool do_critical_native_unlock() const { return (_suspend_flags & _critical_native_unlock) != 0; }
  void set_critical_native_unlock() {
    set_suspend_flag(_critical_native_unlock);
  }
  void clear_critical_native_unlock() {
    clear_suspend_flag(_critical_native_unlock);
  }
#ifdef CHECK_UNHANDLED_OOPS
 private:
  UnhandledOops* _unhandled_oops;
 public:
  UnhandledOops* unhandled_oops() { return _unhandled_oops; }
  void allow_unhandled_oop(oop *op) {
    if (CheckUnhandledOops) unhandled_oops()->allow_unhandled_oop(op);
  }
  void clear_unhandled_oops() {
    if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops();
  }
#endif // CHECK_UNHANDLED_OOPS
#ifndef PRODUCT
  bool skip_gcalot()           { return _skip_gcalot; }
  void set_skip_gcalot(bool v) { _skip_gcalot = v;    }
#endif
 public:
  static void send_async_exception(oop thread_oop, oop java_throwable);
  ResourceArea* resource_area() const            { return _resource_area; }
  void set_resource_area(ResourceArea* area)     { _resource_area = area; }
  OSThread* osthread() const                     { return _osthread;   }
  void set_osthread(OSThread* thread)            { _osthread = thread; }
  JNIHandleBlock* active_handles() const         { return _active_handles; }
  void set_active_handles(JNIHandleBlock* block) { _active_handles = block; }
  JNIHandleBlock* free_handle_block() const      { return _free_handle_block; }
  void set_free_handle_block(JNIHandleBlock* block) { _free_handle_block = block; }
  HandleArea* handle_area() const                { return _handle_area; }
  void set_handle_area(HandleArea* area)         { _handle_area = area; }
  GrowableArray<Metadata*>* metadata_handles() const          { return _metadata_handles; }
  void set_metadata_handles(GrowableArray<Metadata*>* handles){ _metadata_handles = handles; }
  ThreadLocalAllocBuffer& tlab()                 { return _tlab; }
  void initialize_tlab() {
    if (UseTLAB) {
      tlab().initialize();
    }
  }
  jlong allocated_bytes()               { return _allocated_bytes; }
  void set_allocated_bytes(jlong value) { _allocated_bytes = value; }
  void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
  inline jlong cooked_allocated_bytes();
  JFR_ONLY(DEFINE_THREAD_LOCAL_ACCESSOR_JFR;)
  JFR_ONLY(DEFINE_TRACE_SUSPEND_FLAG_METHODS)
  const ThreadExt& ext() const          { return _ext; }
  ThreadExt& ext()                      { return _ext; }
  int vm_operation_ticket()                      { return ++_vm_operation_started_count; }
  int vm_operation_completed_count()             { return _vm_operation_completed_count; }
  void increment_vm_operation_completed_count()  { _vm_operation_completed_count++; }
  ObjectMonitor* current_pending_monitor() {
    return _current_pending_monitor;
  }
  void set_current_pending_monitor(ObjectMonitor* monitor) {
    _current_pending_monitor = monitor;
  }
  void set_current_pending_monitor_is_from_java(bool from_java) {
    _current_pending_monitor_is_from_java = from_java;
  }
  bool current_pending_monitor_is_from_java() {
    return _current_pending_monitor_is_from_java;
  }
  ObjectMonitor* current_waiting_monitor() {
    return _current_waiting_monitor;
  }
  void set_current_waiting_monitor(ObjectMonitor* monitor) {
    _current_waiting_monitor = monitor;
  }
  virtual void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
private:
  bool claim_oops_do_par_case(int collection_parity);
public:
  bool claim_oops_do(bool is_par, int collection_parity) {
    if (!is_par) {
      _oops_do_parity = collection_parity;
      return true;
    } else {
      return claim_oops_do_par_case(collection_parity);
    }
  }
  void nmethods_do(CodeBlobClosure* cf);
  void metadata_do(void f(Metadata*));
  virtual bool is_lock_owned(address adr) const;
  bool is_in_stack(address adr) const;
  bool is_in_usable_stack(address adr) const;
  bool set_as_starting_thread();
  void set_metadata_on_stack_buffer(MetadataOnStackBuffer* buffer) { _metadata_on_stack_buffer = buffer; }
  MetadataOnStackBuffer* metadata_on_stack_buffer() const          { return _metadata_on_stack_buffer; }
protected:
  OSThread* _osthread;  // Platform-specific thread information
  ResourceArea* _resource_area;
  DEBUG_ONLY(ResourceMark* _current_resource_mark;)
  HandleArea* _handle_area;
  GrowableArray<Metadata*>* _metadata_handles;
  address          _stack_base;
  size_t           _stack_size;
  uintptr_t        _self_raw_id;      // used by get_thread (mutable)
  int              _lgrp_id;
 public:
  address stack_base() const           { assert(_stack_base != NULL,"Sanity check"); return _stack_base; }
  void    set_stack_base(address base) { _stack_base = base; }
  size_t  stack_size() const           { return _stack_size; }
  void    set_stack_size(size_t size)  { _stack_size = size; }
  void    record_stack_base_and_size();
  bool    on_local_stack(address adr) const {
    return (_stack_base > adr && adr >= (_stack_base - _stack_size));
  }
  uintptr_t self_raw_id()                    { return _self_raw_id; }
  void      set_self_raw_id(uintptr_t value) { _self_raw_id = value; }
  int     lgrp_id() const        { return _lgrp_id; }
  void    set_lgrp_id(int value) { _lgrp_id = value; }
  void print_on(outputStream* st) const;
  void print() const { print_on(tty); }
  virtual void print_on_error(outputStream* st, char* buf, int buflen) const;
#ifdef ASSERT
 private:
  Monitor* _owned_locks;
  friend class Mutex;
  friend class Monitor;
 public:
  void print_owned_locks_on(outputStream* st) const;
  void print_owned_locks() const                 { print_owned_locks_on(tty);    }
  Monitor* owned_locks() const                   { return _owned_locks;          }
  bool owns_locks() const                        { return owned_locks() != NULL; }
  bool owns_locks_but_compiled_lock() const;
  bool allow_allocation()                        { return _allow_allocation_count == 0; }
  ResourceMark* current_resource_mark()          { return _current_resource_mark; }
  void set_current_resource_mark(ResourceMark* rm) { _current_resource_mark = rm; }
#endif
  void check_for_valid_safepoint_state(bool potential_vm_operation) PRODUCT_RETURN;
 private:
  volatile int _jvmti_env_iteration_count;
 public:
  void entering_jvmti_env_iteration()            { ++_jvmti_env_iteration_count; }
  void leaving_jvmti_env_iteration()             { --_jvmti_env_iteration_count; }
  bool is_inside_jvmti_env_iteration()           { return _jvmti_env_iteration_count > 0; }
  static ByteSize exception_file_offset()        { return byte_offset_of(Thread, _exception_file   ); }
  static ByteSize exception_line_offset()        { return byte_offset_of(Thread, _exception_line   ); }
  static ByteSize active_handles_offset()        { return byte_offset_of(Thread, _active_handles   ); }
  static ByteSize stack_base_offset()            { return byte_offset_of(Thread, _stack_base ); }
  static ByteSize stack_size_offset()            { return byte_offset_of(Thread, _stack_size ); }
#define TLAB_FIELD_OFFSET(name) \
  static ByteSize tlab_##name##_offset()         { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
  TLAB_FIELD_OFFSET(start)
  TLAB_FIELD_OFFSET(end)
  TLAB_FIELD_OFFSET(top)
  TLAB_FIELD_OFFSET(pf_top)
  TLAB_FIELD_OFFSET(size)                   // desired_size
  TLAB_FIELD_OFFSET(refill_waste_limit)
  TLAB_FIELD_OFFSET(number_of_refills)
  TLAB_FIELD_OFFSET(fast_refill_waste)
  TLAB_FIELD_OFFSET(slow_allocations)
#undef TLAB_FIELD_OFFSET
  static ByteSize allocated_bytes_offset()       { return byte_offset_of(Thread, _allocated_bytes ); }
  JFR_ONLY(DEFINE_THREAD_LOCAL_OFFSET_JFR;)
 public:
  volatile intptr_t _Stalled ;
  volatile int _TypeTag ;
  ParkEvent * _ParkEvent ;                     // for synchronized()
  ParkEvent * _SleepEvent ;                    // for Thread.sleep
  ParkEvent * _MutexEvent ;                    // for native internal Mutex/Monitor
  ParkEvent * _MuxEvent ;                      // for low-level muxAcquire-muxRelease
  int NativeSyncRecursion ;                    // diagnostic
  volatile int _OnTrap ;                       // Resume-at IP delta
  jint _hashStateW ;                           // Marsaglia Shift-XOR thread-local RNG
  jint _hashStateX ;                           // thread-specific hashCode generator state
  jint _hashStateY ;
  jint _hashStateZ ;
  void * _schedctl ;
  volatile jint rng [4] ;                      // RNG for spin loop
  static void SpinAcquire (volatile int * Lock, const char * Name) ;
  static void SpinRelease (volatile int * Lock) ;
  static void muxAcquire  (volatile intptr_t * Lock, const char * Name) ;
  static void muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) ;
  static void muxRelease  (volatile intptr_t * Lock) ;
};
inline Thread* Thread::current() {
#ifdef ASSERT
#ifdef PARANOID
  Thread* t = ThreadLocalStorage::get_thread_slow();
  assert(t != NULL && !t->is_inside_signal_handler(),
         "Don't use Thread::current() inside signal handler");
#endif
#endif
  Thread* current = current_or_null();
  assert(current != NULL, "Thread::current() called on detached thread");
  return current;
}
inline Thread* Thread::current_or_null() {
  if (ThreadLocalStorage::is_initialized()) {
    return ThreadLocalStorage::thread();
  }
  return NULL;
}
class NamedThread: public Thread {
  friend class VMStructs;
  enum {
    max_name_len = 64
  };
 private:
  char* _name;
  JavaThread* _processed_thread;
 public:
  NamedThread();
  ~NamedThread();
  void set_name(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3);
  virtual bool is_Named_thread() const { return true; }
  virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; }
  JavaThread *processed_thread() { return _processed_thread; }
  void set_processed_thread(JavaThread *thread) { _processed_thread = thread; }
};
class WorkerThread: public NamedThread {
private:
  uint _id;
public:
  WorkerThread() : _id(0)               { }
  virtual bool is_Worker_thread() const { return true; }
  virtual WorkerThread* as_Worker_thread() const {
    assert(is_Worker_thread(), "Dubious cast to WorkerThread*?");
    return (WorkerThread*) this;
  }
  void set_id(uint work_id)             { _id = work_id; }
  uint id() const                       { return _id; }
};
class WatcherThread: public Thread {
  friend class VMStructs;
 public:
  virtual void run();
 private:
  static WatcherThread* _watcher_thread;
  static bool _startable;
  volatile static bool _should_terminate; // updated without holding lock
 public:
  enum SomeConstants {
    delay_interval = 10                          // interrupt delay in milliseconds
  };
  WatcherThread();
  bool is_Watcher_thread() const                 { return true; }
  char* name() const { return (char*)"VM Periodic Task Thread"; }
  void print_on(outputStream* st) const;
  void print() const { print_on(tty); }
  void unpark();
  static WatcherThread* watcher_thread()         { return _watcher_thread; }
  static void start();
  static void stop();
  static void make_startable();
 private:
  int sleep() const;
};
class CompilerThread;
typedef void (*ThreadFunction)(JavaThread*, TRAPS);
class JavaThread: public Thread {
  friend class VMStructs;
 private:
  JavaThread*    _next;                          // The next thread in the Threads list
  oop            _threadObj;                     // The Java level thread object
#ifdef ASSERT
 private:
  int _java_call_counter;
 public:
  int  java_call_counter()                       { return _java_call_counter; }
  void inc_java_call_counter()                   { _java_call_counter++; }
  void dec_java_call_counter() {
    assert(_java_call_counter > 0, "Invalid nesting of JavaCallWrapper");
    _java_call_counter--;
  }
 private:  // restore original namespace restriction
#endif  // ifdef ASSERT
#ifndef PRODUCT
 public:
  enum {
    jump_ring_buffer_size = 16
  };
 private:  // restore original namespace restriction
#endif
  JavaFrameAnchor _anchor;                       // Encapsulation of current java frame and it state
  ThreadFunction _entry_point;
  JNIEnv        _jni_environment;
  DeoptResourceMark*  _deopt_mark;               // Holds special ResourceMark for deoptimization
  intptr_t*      _must_deopt_id;                 // id of frame that needs to be deopted once we
  nmethod*       _deopt_nmethod;                 // nmethod that is currently being deoptimized
  vframeArray*  _vframe_array_head;              // Holds the heap of the active vframeArrays
  vframeArray*  _vframe_array_last;              // Holds last vFrameArray we popped
  GrowableArray<jvmtiDeferredLocalVariableSet*>* _deferred_locals_updates;
  Method*       _callee_target;
  oop           _vm_result;    // oop result is GC-preserved
  Metadata*     _vm_result_2;  // non-oop result
  MemRegion     _deferred_card_mark;
  MonitorChunk* _monitor_chunks;                 // Contains the off stack monitors
  enum AsyncRequests {
    _no_async_condition = 0,
    _async_exception,
    _async_unsafe_access_error
  };
  AsyncRequests _special_runtime_exit_condition; // Enum indicating pending async. request
  oop           _pending_async_exception;
 public:                                         // Expose _thread_state for SafeFetchInt()
  volatile JavaThreadState _thread_state;
 private:
  ThreadSafepointState *_safepoint_state;        // Holds information about a thread during a safepoint
  address               _saved_exception_pc;     // Saved pc of instruction where last implicit exception happened
  enum TerminatedTypes {
    _not_terminated = 0xDEAD - 2,
    _thread_exiting,                             // JavaThread::exit() has been called for this thread
    _thread_terminated,                          // JavaThread is removed from thread list
    _vm_exited                                   // JavaThread is still executing native code, but VM is terminated
  };
  volatile TerminatedTypes _terminated;
  volatile bool         _suspend_equivalent;     // Suspend equivalent condition
  jint                  _in_deopt_handler;       // count of deoptimization
  volatile bool         _doing_unsafe_access;    // Thread may fault due to unsafe access
  bool                  _do_not_unlock_if_synchronized; // Do not unlock the receiver of a synchronized method (since it was
  enum JNIAttachStates {
    _not_attaching_via_jni = 1,  // thread is not attaching via JNI
    _attaching_via_jni,          // thread is attaching via JNI
    _attached_via_jni            // thread has attached via JNI
  };
  volatile JNIAttachStates _jni_attach_state;
 public:
  enum StackGuardState {
    stack_guard_unused,         // not needed
    stack_guard_yellow_disabled,// disabled (temporarily) after stack overflow
    stack_guard_enabled         // enabled
  };
 private:
  StackGuardState  _stack_guard_state;
  address          _stack_overflow_limit;
  volatile oop     _exception_oop;               // Exception thrown in compiled code
  volatile address _exception_pc;                // PC where exception happened
  volatile address _exception_handler_pc;        // PC for handler of exception
  volatile int     _is_method_handle_return;     // true (== 1) if the current exception PC is a MethodHandle call site.
  jint    _jni_active_critical;                  // count of entries into JNI critical region
  char* _pending_jni_exception_check_fn;
  int _depth_first_number;
  int _popframe_condition;
  int _frames_to_pop_failed_realloc;
#ifndef PRODUCT
  int _jmp_ring_index;
  struct {
      intptr_t _target;
      intptr_t _instruction;
      const char*  _file;
      int _line;
  }   _jmp_ring[ jump_ring_buffer_size ];
#endif /* PRODUCT */
#if INCLUDE_ALL_GCS
  ObjPtrQueue _satb_mark_queue;          // Thread-local log for SATB barrier.
  static SATBMarkQueueSet _satb_mark_queue_set;
  DirtyCardQueue _dirty_card_queue;      // Thread-local log for dirty cards.
  static DirtyCardQueueSet _dirty_card_queue_set;
  void flush_barrier_queues();
#endif // INCLUDE_ALL_GCS
  friend class VMThread;
  friend class ThreadWaitTransition;
  friend class VM_Exit;
  void initialize();                             // Initialized the instance variables
 public:
  JavaThread(bool is_attaching_via_jni = false); // for main thread and JNI attached threads
  JavaThread(ThreadFunction entry_point, size_t stack_size = 0);
  ~JavaThread();
#ifdef ASSERT
  void verify_not_published();
#endif
  void set_jni_functions(struct JNINativeInterface_* functionTable) {
    _jni_environment.functions = functionTable;
  }
  struct JNINativeInterface_* get_jni_functions() {
    return (struct JNINativeInterface_ *)_jni_environment.functions;
  }
  void cache_global_variables();
  void invoke_shutdown_hooks();
  enum ExitType {
    normal_exit,
    jni_detach
  };
  void exit(bool destroy_vm, ExitType exit_type = normal_exit);
  void cleanup_failed_attach_current_thread();
  virtual bool is_Java_thread() const            { return true;  }
  JavaThread* next() const                       { return _next; }
  void set_next(JavaThread* p)                   { _next = p; }
  oop threadObj() const                          { return _threadObj; }
  void set_threadObj(oop p)                      { _threadObj = p; }
  ThreadPriority java_priority() const;          // Read from threadObj()
  void prepare(jobject jni_thread, ThreadPriority prio=NoPriority);
  void prepare_ext();
  void set_saved_exception_pc(address pc)        { _saved_exception_pc = pc; }
  address saved_exception_pc()                   { return _saved_exception_pc; }
  ThreadFunction entry_point() const             { return _entry_point; }
  void allocate_threadObj(Handle thread_group, char* thread_name, bool daemon, TRAPS);
  JavaFrameAnchor* frame_anchor(void)            { return &_anchor; }
  bool has_last_Java_frame() const               { return _anchor.has_last_Java_frame(); }
  intptr_t* last_Java_sp() const                 { return _anchor.last_Java_sp(); }
  address last_Java_pc(void)                     { return _anchor.last_Java_pc(); }
#if !(defined(PPC64) || defined(AARCH64))
  JavaThreadState thread_state() const           { return _thread_state; }
  void set_thread_state(JavaThreadState s)       { _thread_state = s;    }
#else
  inline JavaThreadState thread_state() const;
  inline void set_thread_state(JavaThreadState s);
#endif
  ThreadSafepointState *safepoint_state() const  { return _safepoint_state; }
  void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; }
  bool is_at_poll_safepoint()                    { return _safepoint_state->is_at_poll_safepoint(); }
  bool is_exiting()                              { return _terminated == _thread_exiting || is_terminated(); }
  bool is_terminated()                           { return _terminated != _not_terminated && _terminated != _thread_exiting; }
  void set_terminated(TerminatedTypes t)         { _terminated = t; }
  void set_terminated_value()                    { _terminated = _thread_terminated; }
  void block_if_vm_exited();
  bool doing_unsafe_access()                     { return _doing_unsafe_access; }
  void set_doing_unsafe_access(bool val)         { _doing_unsafe_access = val; }
  bool do_not_unlock_if_synchronized()             { return _do_not_unlock_if_synchronized; }
  void set_do_not_unlock_if_synchronized(bool val) { _do_not_unlock_if_synchronized = val; }
 private:
  void set_ext_suspended()       { set_suspend_flag (_ext_suspended);  }
  void clear_ext_suspended()     { clear_suspend_flag(_ext_suspended); }
 public:
  void java_suspend();
  void java_resume();
  int  java_suspend_self();
  void check_and_wait_while_suspended() {
    assert(JavaThread::current() == this, "sanity check");
    bool do_self_suspend;
    do {
      do_self_suspend = handle_special_suspend_equivalent_condition();
      if (do_self_suspend) {
        java_suspend_self();
        set_suspend_equivalent();
      }
    } while (do_self_suspend);
  }
  static void check_safepoint_and_suspend_for_native_trans(JavaThread *thread);
  static void check_special_condition_for_native_trans(JavaThread *thread);
  static void check_special_condition_for_native_trans_and_transition(JavaThread *thread);
  bool is_ext_suspend_completed(bool called_by_wait, int delay, uint32_t *bits);
  bool is_ext_suspend_completed_with_lock(uint32_t *bits) {
    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
    return is_ext_suspend_completed(false /*!called_by_wait */,
                                    SuspendRetryDelay, bits);
  }
  bool wait_for_ext_suspend_completion(int count, int delay, uint32_t *bits);
  void set_external_suspend()     { set_suspend_flag  (_external_suspend); }
  void clear_external_suspend()   { clear_suspend_flag(_external_suspend); }
  void set_deopt_suspend()        { set_suspend_flag  (_deopt_suspend); }
  void clear_deopt_suspend()      { clear_suspend_flag(_deopt_suspend); }
  bool is_deopt_suspend()         { return (_suspend_flags & _deopt_suspend) != 0; }
  bool is_external_suspend() const {
    return (_suspend_flags & _external_suspend) != 0;
  }
  bool is_suspend_after_native() const {
    return (_suspend_flags & (_external_suspend | _deopt_suspend) ) != 0;
  }
  bool is_ext_suspended() const {
    return (_suspend_flags & _ext_suspended) != 0;
  }
  bool is_external_suspend_with_lock() const {
    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
    return is_external_suspend();
  }
  bool handle_special_suspend_equivalent_condition() {
    assert(is_suspend_equivalent(),
      "should only be called in a suspend equivalence condition");
    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
    bool ret = is_external_suspend();
    if (!ret) {
      clear_suspend_equivalent();
    }
    return ret;
  }
  bool is_being_ext_suspended() const            {
    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
    return is_ext_suspended() || is_external_suspend();
  }
  bool is_suspend_equivalent() const             { return _suspend_equivalent; }
  void set_suspend_equivalent()                  { _suspend_equivalent = true; };
  void clear_suspend_equivalent()                { _suspend_equivalent = false; };
  void send_thread_stop(oop throwable);
  AsyncRequests clear_special_runtime_exit_condition() {
    AsyncRequests x = _special_runtime_exit_condition;
    _special_runtime_exit_condition = _no_async_condition;
    return x;
  }
  bool has_async_condition() { return (_special_runtime_exit_condition != _no_async_condition); }
  void check_and_handle_async_exceptions(bool check_unsafe_error = true);
  void handle_special_runtime_exit_condition(bool check_asyncs = true);
  bool has_special_runtime_exit_condition() {
    return (_special_runtime_exit_condition != _no_async_condition) ||
            is_external_suspend() || is_deopt_suspend();
  }
  void set_pending_unsafe_access_error()          { _special_runtime_exit_condition = _async_unsafe_access_error; }
  void set_pending_async_exception(oop e) {
    _pending_async_exception = e;
    _special_runtime_exit_condition = _async_exception;
    set_has_async_exception();
  }
  bool is_lock_owned(address adr) const;
  void set_vframe_array_head(vframeArray* value) { _vframe_array_head = value; }
  vframeArray* vframe_array_head() const         { return _vframe_array_head;  }
  GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred_locals() const { return _deferred_locals_updates; }
  void set_deferred_locals(GrowableArray<jvmtiDeferredLocalVariableSet *>* vf) { _deferred_locals_updates = vf; }
  void set_vframe_array_last(vframeArray* value) { _vframe_array_last = value; }
  vframeArray* vframe_array_last() const         { return _vframe_array_last;  }
  void set_deopt_mark(DeoptResourceMark* value)  { _deopt_mark = value; }
  DeoptResourceMark* deopt_mark(void)            { return _deopt_mark; }
  intptr_t* must_deopt_id()                      { return _must_deopt_id; }
  void     set_must_deopt_id(intptr_t* id)       { _must_deopt_id = id; }
  void     clear_must_deopt_id()                 { _must_deopt_id = NULL; }
  void set_deopt_nmethod(nmethod* nm)            { _deopt_nmethod = nm;   }
  nmethod* deopt_nmethod()                       { return _deopt_nmethod; }
  Method*    callee_target() const               { return _callee_target; }
  void set_callee_target  (Method* x)          { _callee_target   = x; }
  oop  vm_result() const                         { return _vm_result; }
  void set_vm_result  (oop x)                    { _vm_result   = x; }
  Metadata*    vm_result_2() const               { return _vm_result_2; }
  void set_vm_result_2  (Metadata* x)          { _vm_result_2   = x; }
  MemRegion deferred_card_mark() const           { return _deferred_card_mark; }
  void set_deferred_card_mark(MemRegion mr)      { _deferred_card_mark = mr;   }
  oop      exception_oop() const                 { return _exception_oop; }
  address  exception_pc() const                  { return _exception_pc; }
  address  exception_handler_pc() const          { return _exception_handler_pc; }
  bool     is_method_handle_return() const       { return _is_method_handle_return == 1; }
  void set_exception_oop(oop o)                  { (void)const_cast<oop&>(_exception_oop = o); }
  void set_exception_pc(address a)               { _exception_pc = a; }
  void set_exception_handler_pc(address a)       { _exception_handler_pc = a; }
  void set_is_method_handle_return(bool value)   { _is_method_handle_return = value ? 1 : 0; }
  void clear_exception_oop_and_pc() {
    set_exception_oop(NULL);
    set_exception_pc(NULL);
  }
  inline size_t stack_available(address cur_sp);
  address stack_yellow_zone_base()
    { return (address)(stack_base() - (stack_size() - (stack_red_zone_size() + stack_yellow_zone_size()))); }
  size_t  stack_yellow_zone_size()
    { return StackYellowPages * os::vm_page_size(); }
  address stack_red_zone_base()
    { return (address)(stack_base() - (stack_size() - stack_red_zone_size())); }
  size_t stack_red_zone_size()
    { return StackRedPages * os::vm_page_size(); }
  bool in_stack_yellow_zone(address a)
    { return (a <= stack_yellow_zone_base()) && (a >= stack_red_zone_base()); }
  bool in_stack_red_zone(address a)
    { return (a <= stack_red_zone_base()) && (a >= (address)((intptr_t)stack_base() - stack_size())); }
  void create_stack_guard_pages();
  void remove_stack_guard_pages();
  void enable_stack_yellow_zone();
  void disable_stack_yellow_zone();
  void enable_stack_red_zone();
  void disable_stack_red_zone();
  inline bool stack_guard_zone_unused();
  inline bool stack_yellow_zone_disabled();
  inline bool stack_yellow_zone_enabled();
  bool reguard_stack(address cur_sp);
  bool reguard_stack(void);
  address stack_overflow_limit() { return _stack_overflow_limit; }
  void set_stack_overflow_limit() {
    _stack_overflow_limit = _stack_base - _stack_size +
                            ((StackShadowPages +
                              StackYellowPages +
                              StackRedPages) * os::vm_page_size());
  }
  void set_do_not_unlock(void)                   { _do_not_unlock_if_synchronized = true; }
  void clr_do_not_unlock(void)                   { _do_not_unlock_if_synchronized = false; }
  bool do_not_unlock(void)                       { return _do_not_unlock_if_synchronized; }
#ifndef PRODUCT
  void record_jump(address target, address instr, const char* file, int line);
#endif /* PRODUCT */
  static ByteSize threadObj_offset()             { return byte_offset_of(JavaThread, _threadObj           ); }
#ifndef PRODUCT
  static ByteSize jmp_ring_index_offset()        { return byte_offset_of(JavaThread, _jmp_ring_index      ); }
  static ByteSize jmp_ring_offset()              { return byte_offset_of(JavaThread, _jmp_ring            ); }
#endif /* PRODUCT */
  static ByteSize jni_environment_offset()       { return byte_offset_of(JavaThread, _jni_environment     ); }
  static ByteSize last_Java_sp_offset()          {
    return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_sp_offset();
  }
  static ByteSize last_Java_pc_offset()          {
    return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_pc_offset();
  }
  static ByteSize frame_anchor_offset()          {
    return byte_offset_of(JavaThread, _anchor);
  }
  static ByteSize callee_target_offset()         { return byte_offset_of(JavaThread, _callee_target       ); }
  static ByteSize vm_result_offset()             { return byte_offset_of(JavaThread, _vm_result           ); }
  static ByteSize vm_result_2_offset()           { return byte_offset_of(JavaThread, _vm_result_2         ); }
  static ByteSize thread_state_offset()          { return byte_offset_of(JavaThread, _thread_state        ); }
  static ByteSize saved_exception_pc_offset()    { return byte_offset_of(JavaThread, _saved_exception_pc  ); }
  static ByteSize osthread_offset()              { return byte_offset_of(JavaThread, _osthread            ); }
  static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
  static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
  static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }
  static ByteSize stack_overflow_limit_offset()  { return byte_offset_of(JavaThread, _stack_overflow_limit); }
  static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
  static ByteSize stack_guard_state_offset()     { return byte_offset_of(JavaThread, _stack_guard_state   ); }
  static ByteSize suspend_flags_offset()         { return byte_offset_of(JavaThread, _suspend_flags       ); }
  static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); }
  static ByteSize should_post_on_exceptions_flag_offset() {
    return byte_offset_of(JavaThread, _should_post_on_exceptions_flag);
  }
#if INCLUDE_ALL_GCS
  static ByteSize satb_mark_queue_offset()       { return byte_offset_of(JavaThread, _satb_mark_queue); }
  static ByteSize dirty_card_queue_offset()      { return byte_offset_of(JavaThread, _dirty_card_queue); }
#endif // INCLUDE_ALL_GCS
  JNIEnv* jni_environment()                      { return &_jni_environment; }
  static JavaThread* thread_from_jni_environment(JNIEnv* env) {
    JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
    if (thread_from_jni_env->is_terminated()) {
       thread_from_jni_env->block_if_vm_exited();
       return NULL;
    } else {
       return thread_from_jni_env;
    }
  }
  bool in_critical()    { return _jni_active_critical > 0; }
  bool in_last_critical()  { return _jni_active_critical == 1; }
  void enter_critical() { assert(Thread::current() == this ||
                                 Thread::current()->is_VM_thread() && SafepointSynchronize::is_synchronizing(),
                                 "this must be current thread or synchronizing");
                          _jni_active_critical++; }
  void exit_critical()  { assert(Thread::current() == this,
                                 "this must be current thread");
                          _jni_active_critical--;
                          assert(_jni_active_critical >= 0,
                                 "JNI critical nesting problem?"); }
  bool is_pending_jni_exception_check() const { return _pending_jni_exception_check_fn != NULL; }
  void clear_pending_jni_exception_check() { _pending_jni_exception_check_fn = NULL; }
  const char* get_pending_jni_exception_check() const { return _pending_jni_exception_check_fn; }
  void set_pending_jni_exception_check(const char* fn_name) { _pending_jni_exception_check_fn = (char*) fn_name; }
  int depth_first_number() { return _depth_first_number; }
  void set_depth_first_number(int dfn) { _depth_first_number = dfn; }
 private:
  void set_monitor_chunks(MonitorChunk* monitor_chunks) { _monitor_chunks = monitor_chunks; }
 public:
  MonitorChunk* monitor_chunks() const           { return _monitor_chunks; }
  void add_monitor_chunk(MonitorChunk* chunk);
  void remove_monitor_chunk(MonitorChunk* chunk);
  bool in_deopt_handler() const                  { return _in_deopt_handler > 0; }
  void inc_in_deopt_handler()                    { _in_deopt_handler++; }
  void dec_in_deopt_handler()                    {
    assert(_in_deopt_handler > 0, "mismatched deopt nesting");
    if (_in_deopt_handler > 0) { // robustness
      _in_deopt_handler--;
    }
  }
 private:
  void set_entry_point(ThreadFunction entry_point) { _entry_point = entry_point; }
 public:
  void frames_do(void f(frame*, const RegisterMap*));
  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
  void nmethods_do(CodeBlobClosure* cf);
  void metadata_do(void f(Metadata*));
  void gc_epilogue();
  void gc_prologue();
  char* name() const { return (char*)get_thread_name(); }
  void print_on(outputStream* st) const;
  void print() const { print_on(tty); }
  void print_value();
  void print_thread_state_on(outputStream* ) const      PRODUCT_RETURN;
  void print_thread_state() const                       PRODUCT_RETURN;
  void print_on_error(outputStream* st, char* buf, int buflen) const;
  void verify();
  const char* get_thread_name() const;
private:
  const char* get_thread_name_string(char* buf = NULL, int buflen = 0) const;
public:
  const char* get_threadgroup_name() const;
  const char* get_parent_name() const;
  frame last_frame() {
    _anchor.make_walkable(this);
    return pd_last_frame();
  }
  javaVFrame* last_java_vframe(RegisterMap* reg_map);
  Klass* security_get_caller_class(int depth);
  void print_stack_on(outputStream* st);
  void print_stack() { print_stack_on(tty); }
  void trace_stack()                             PRODUCT_RETURN;
  void trace_stack_from(vframe* start_vf)        PRODUCT_RETURN;
  void trace_frames()                            PRODUCT_RETURN;
  void trace_oops()                              PRODUCT_RETURN;
  void print_frame_layout(int depth = 0, bool validate_only = false) NOT_DEBUG_RETURN;
  void validate_frame_layout() {
    print_frame_layout(0, true);
  }
  int depth() const;
  void deoptimize();
  void make_zombies();
  void deoptimized_wrt_marked_nmethods();
 public:
   bool profile_last_Java_frame(frame* fr);
 private:
   ThreadProfiler* _thread_profiler;
 private:
   friend class FlatProfiler;                    // uses both [gs]et_thread_profiler.
   friend class FlatProfilerTask;                // uses get_thread_profiler.
   friend class ThreadProfilerMark;              // uses get_thread_profiler.
   ThreadProfiler* get_thread_profiler()         { return _thread_profiler; }
   ThreadProfiler* set_thread_profiler(ThreadProfiler* tp) {
     ThreadProfiler* result = _thread_profiler;
     _thread_profiler = tp;
     return result;
   }
 public:
  static inline JavaThread* current();
  static JavaThread* active();
  inline CompilerThread* as_CompilerThread();
 public:
  virtual void run();
  void thread_main_inner();
 private:
  PrivilegedElement*  _privileged_stack_top;
  GrowableArray<oop>* _array_for_gc;
 public:
  PrivilegedElement* privileged_stack_top() const       { return _privileged_stack_top; }
  void set_privileged_stack_top(PrivilegedElement *e)   { _privileged_stack_top = e; }
  void register_array_for_gc(GrowableArray<oop>* array) { _array_for_gc = array; }
 public:
  void set_jvmti_thread_state(JvmtiThreadState *value)                           { _jvmti_thread_state = value; }
  JvmtiThreadState *jvmti_thread_state() const                                   { return _jvmti_thread_state; }
  static ByteSize jvmti_thread_state_offset()                                    { return byte_offset_of(JavaThread, _jvmti_thread_state); }
  void set_jvmti_get_loaded_classes_closure(JvmtiGetLoadedClassesClosure* value) { _jvmti_get_loaded_classes_closure = value; }
  JvmtiGetLoadedClassesClosure* get_jvmti_get_loaded_classes_closure() const     { return _jvmti_get_loaded_classes_closure; }
  enum PopCondition {
    popframe_inactive                      = 0x00,
    popframe_pending_bit                   = 0x01,
    popframe_processing_bit                = 0x02,
    popframe_force_deopt_reexecution_bit   = 0x04
  };
  PopCondition popframe_condition()                   { return (PopCondition) _popframe_condition; }
  void set_popframe_condition(PopCondition c)         { _popframe_condition = c; }
  void set_popframe_condition_bit(PopCondition c)     { _popframe_condition |= c; }
  void clear_popframe_condition()                     { _popframe_condition = popframe_inactive; }
  static ByteSize popframe_condition_offset()         { return byte_offset_of(JavaThread, _popframe_condition); }
  bool has_pending_popframe()                         { return (popframe_condition() & popframe_pending_bit) != 0; }
  bool popframe_forcing_deopt_reexecution()           { return (popframe_condition() & popframe_force_deopt_reexecution_bit) != 0; }
  void clear_popframe_forcing_deopt_reexecution()     { _popframe_condition &= ~popframe_force_deopt_reexecution_bit; }
#ifdef CC_INTERP
  bool pop_frame_pending(void)                        { return ((_popframe_condition & popframe_pending_bit) != 0); }
  void clr_pop_frame_pending(void)                    { _popframe_condition = popframe_inactive; }
  bool pop_frame_in_process(void)                     { return ((_popframe_condition & popframe_processing_bit) != 0); }
  void set_pop_frame_in_process(void)                 { _popframe_condition |= popframe_processing_bit; }
  void clr_pop_frame_in_process(void)                 { _popframe_condition &= ~popframe_processing_bit; }
#endif
  int frames_to_pop_failed_realloc() const            { return _frames_to_pop_failed_realloc; }
  void set_frames_to_pop_failed_realloc(int nb)       { _frames_to_pop_failed_realloc = nb; }
  void dec_frames_to_pop_failed_realloc()             { _frames_to_pop_failed_realloc--; }
 private:
  void*    _popframe_preserved_args;
  int      _popframe_preserved_args_size;
 public:
  void  popframe_preserve_args(ByteSize size_in_bytes, void* start);
  void* popframe_preserved_args();
  ByteSize popframe_preserved_args_size();
  WordSize popframe_preserved_args_size_in_words();
  void  popframe_free_preserved_args();
 private:
  JvmtiThreadState *_jvmti_thread_state;
  JvmtiGetLoadedClassesClosure* _jvmti_get_loaded_classes_closure;
  int               _interp_only_mode;
 public:
  static ByteSize interp_only_mode_offset() { return byte_offset_of(JavaThread, _interp_only_mode); }
  bool is_interp_only_mode()                { return (_interp_only_mode != 0); }
  int get_interp_only_mode()                { return _interp_only_mode; }
  void increment_interp_only_mode()         { ++_interp_only_mode; }
  void decrement_interp_only_mode()         { --_interp_only_mode; }
 private:
  int    _should_post_on_exceptions_flag;
 public:
  int   should_post_on_exceptions_flag()  { return _should_post_on_exceptions_flag; }
  void  set_should_post_on_exceptions_flag(int val)  { _should_post_on_exceptions_flag = val; }
 private:
  ThreadStatistics *_thread_stat;
 public:
  ThreadStatistics* get_thread_stat() const    { return _thread_stat; }
  oop current_park_blocker();
 private:
  static size_t _stack_size_at_create;
 public:
  static inline size_t stack_size_at_create(void) {
    return _stack_size_at_create;
  }
  static inline void set_stack_size_at_create(size_t value) {
    _stack_size_at_create = value;
  }
#if INCLUDE_ALL_GCS
  ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; }
  static SATBMarkQueueSet& satb_mark_queue_set() {
    return _satb_mark_queue_set;
  }
  DirtyCardQueue& dirty_card_queue() { return _dirty_card_queue; }
  static DirtyCardQueueSet& dirty_card_queue_set() {
    return _dirty_card_queue_set;
  }
#endif // INCLUDE_ALL_GCS
#if INCLUDE_ALL_GCS
  void initialize_queues();
#else  // INCLUDE_ALL_GCS
  void initialize_queues() { }
#endif // INCLUDE_ALL_GCS
#ifdef TARGET_OS_ARCH_linux_x86
# include "thread_linux_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_aarch64
# include "thread_linux_aarch64.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "thread_linux_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "thread_linux_zero.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_x86
# include "thread_solaris_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "thread_solaris_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_windows_x86
# include "thread_windows_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_arm
# include "thread_linux_arm.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_ppc
# include "thread_linux_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_aix_ppc
# include "thread_aix_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_x86
# include "thread_bsd_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_zero
# include "thread_bsd_zero.hpp"
#endif
 public:
  void set_blocked_on_compilation(bool value) {
    _blocked_on_compilation = value;
  }
  bool blocked_on_compilation() {
    return _blocked_on_compilation;
  }
 protected:
  bool         _blocked_on_compilation;
private:
  Parker*    _parker;
public:
  Parker*     parker() { return _parker; }
private:
  GrowableArray<MonitorInfo*>* _cached_monitor_info;
public:
  GrowableArray<MonitorInfo*>* cached_monitor_info() { return _cached_monitor_info; }
  void set_cached_monitor_info(GrowableArray<MonitorInfo*>* info) { _cached_monitor_info = info; }
  bool is_attaching_via_jni() const { return _jni_attach_state == _attaching_via_jni; }
  bool has_attached_via_jni() const { return is_attaching_via_jni() || _jni_attach_state == _attached_via_jni; }
  inline void set_done_attaching_via_jni();
private:
  uint _claimed_par_id;
public:
  uint get_claimed_par_id() { return _claimed_par_id; }
  void set_claimed_par_id(uint id) { _claimed_par_id = id;}
};
inline JavaThread* JavaThread::current() {
  Thread* thread = Thread::current();
  assert(thread->is_Java_thread(), "just checking");
  return (JavaThread*)thread;
}
inline CompilerThread* JavaThread::as_CompilerThread() {
  assert(is_Compiler_thread(), "just checking");
  return (CompilerThread*)this;
}
inline bool JavaThread::stack_guard_zone_unused() {
  return _stack_guard_state == stack_guard_unused;
}
inline bool JavaThread::stack_yellow_zone_disabled() {
  return _stack_guard_state == stack_guard_yellow_disabled;
}
inline bool JavaThread::stack_yellow_zone_enabled() {
#ifdef ASSERT
  if (os::uses_stack_guard_pages() &&
      !(DisablePrimordialThreadGuardPages && os::is_primordial_thread())) {
    assert(_stack_guard_state != stack_guard_unused, "guard pages must be in use");
  }
#endif
    return _stack_guard_state == stack_guard_enabled;
}
inline size_t JavaThread::stack_available(address cur_sp) {
  address low_addr; // Limit on the address for deepest stack depth
  if ( _stack_guard_state == stack_guard_unused) {
    low_addr =  stack_base() - stack_size();
  } else {
    low_addr = stack_yellow_zone_base();
  }
  return cur_sp > low_addr ? cur_sp - low_addr : 0;
}
class CompilerThread : public JavaThread {
  friend class VMStructs;
 private:
  CompilerCounters* _counters;
  ciEnv*            _env;
  CompileLog*       _log;
  CompileTask*      _task;
  CompileQueue*     _queue;
  BufferBlob*       _buffer_blob;
  nmethod*          _scanned_nmethod;  // nmethod being scanned by the sweeper
  AbstractCompiler* _compiler;
 public:
  static CompilerThread* current();
  CompilerThread(CompileQueue* queue, CompilerCounters* counters);
  bool is_Compiler_thread() const                { return true; }
  bool is_hidden_from_external_view() const      { return true; }
  void set_compiler(AbstractCompiler* c)         { _compiler = c; }
  AbstractCompiler* compiler() const             { return _compiler; }
  CompileQueue* queue()        const             { return _queue; }
  CompilerCounters* counters() const             { return _counters; }
  ciEnv*        env()                            { return _env; }
  void          set_env(ciEnv* env)              { _env = env; }
  BufferBlob*   get_buffer_blob() const          { return _buffer_blob; }
  void          set_buffer_blob(BufferBlob* b)   { _buffer_blob = b; };
  CompileLog*   log()                            { return _log; }
  void          init_log(CompileLog* log) {
    assert(_log == NULL, "set only once");
    _log = log;
  }
  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
#ifndef PRODUCT
private:
  IdealGraphPrinter *_ideal_graph_printer;
public:
  IdealGraphPrinter *ideal_graph_printer()                       { return _ideal_graph_printer; }
  void set_ideal_graph_printer(IdealGraphPrinter *n)             { _ideal_graph_printer = n; }
#endif
  CompileTask*  task()                           { return _task; }
  void          set_task(CompileTask* task)      { _task = task; }
  void          set_scanned_nmethod(nmethod* nm) {
    assert(_scanned_nmethod == NULL || nm == NULL, "should reset to NULL before writing a new value");
    _scanned_nmethod = nm;
  }
};
inline CompilerThread* CompilerThread::current() {
  return JavaThread::current()->as_CompilerThread();
}
class Threads: AllStatic {
  friend class VMStructs;
 private:
  static JavaThread* _thread_list;
  static int         _number_of_threads;
  static int         _number_of_non_daemon_threads;
  static int         _return_code;
#ifdef ASSERT
  static bool        _vm_complete;
#endif
 public:
  static void add(JavaThread* p, bool force_daemon = false);
  static void remove(JavaThread* p);
  static bool includes(JavaThread* p);
  static JavaThread* first()                     { return _thread_list; }
  static void threads_do(ThreadClosure* tc);
  static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain);
  static void convert_vm_init_libraries_to_agents();
  static void create_vm_init_libraries();
  static void create_vm_init_agents();
  static void shutdown_vm_agents();
  static bool destroy_vm();
  static jboolean is_supported_jni_version_including_1_1(jint version);
  static jboolean is_supported_jni_version(jint version);
  static void follow_other_roots(void f(oop*));
  static void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
  static void possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
  static void create_thread_roots_tasks(GCTaskQueue* q);
  static void create_thread_roots_marking_tasks(GCTaskQueue* q);
  static void compiled_frame_oops_do(OopClosure* f, CodeBlobClosure* cf);
  static void convert_hcode_pointers();
  static void restore_hcode_pointers();
  static void nmethods_do(CodeBlobClosure* cf);
  static void metadata_do(void f(Metadata*));
  static void gc_epilogue();
  static void gc_prologue();
#ifdef ASSERT
  static bool is_vm_complete() { return _vm_complete; }
#endif
  static void verify();
  static void print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks);
  static void print(bool print_stacks, bool internal_format) {
    print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */);
  }
  static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen);
  static GrowableArray<JavaThread*>* get_pending_threads(int count,
    address monitor, bool doLock);
  static JavaThread *owning_thread_from_monitor_owner(address owner,
    bool doLock);
  static int number_of_threads()                 { return _number_of_threads; }
  static int number_of_non_daemon_threads()      { return _number_of_non_daemon_threads; }
  static void deoptimized_wrt_marked_nmethods();
  static JavaThread* find_java_thread_from_java_tid(jlong java_tid);
};
class ThreadClosure: public StackObj {
 public:
  virtual void do_thread(Thread* thread) = 0;
};
class SignalHandlerMark: public StackObj {
private:
  Thread* _thread;
public:
  SignalHandlerMark(Thread* t) {
    _thread = t;
    if (_thread) _thread->enter_signal_handler();
  }
  ~SignalHandlerMark() {
    if (_thread) _thread->leave_signal_handler();
    _thread = NULL;
  }
};
#endif // SHARE_VM_RUNTIME_THREAD_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/thread.inline.hpp
#ifndef SHARE_VM_RUNTIME_THREAD_INLINE_HPP
#define SHARE_VM_RUNTIME_THREAD_INLINE_HPP
#define SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE
#include "runtime/thread.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "thread_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "thread_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "thread_bsd.inline.hpp"
#endif
#undef SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE
inline jlong Thread::cooked_allocated_bytes() {
  jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes);
  if (UseTLAB) {
    size_t used_bytes = tlab().used_bytes();
    if ((ssize_t)used_bytes > 0) {
      return allocated_bytes + used_bytes;
    }
  }
  return allocated_bytes;
}
#if defined(PPC64) || defined (AARCH64)
inline JavaThreadState JavaThread::thread_state() const    {
  return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state);
}
inline void JavaThread::set_thread_state(JavaThreadState s) {
  OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s);
}
#endif
inline void JavaThread::set_done_attaching_via_jni() {
  _jni_attach_state = _attached_via_jni;
  OrderAccess::fence();
}
#endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/threadCritical.hpp
#ifndef SHARE_VM_RUNTIME_THREADCRITICAL_HPP
#define SHARE_VM_RUNTIME_THREADCRITICAL_HPP
#include "memory/allocation.hpp"
class ThreadCritical : public StackObj {
 friend class os;
 private:
  static void initialize();
  static void release();
 public:
  ThreadCritical();
  ~ThreadCritical();
};
#endif // SHARE_VM_RUNTIME_THREADCRITICAL_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/threadLocalStorage.cpp
#include "precompiled.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadLocalStorage.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
#ifndef SOLARIS
int ThreadLocalStorage::_thread_index = -1;
Thread* ThreadLocalStorage::get_thread_slow() {
  return (Thread*) os::thread_local_storage_at(ThreadLocalStorage::thread_index());
}
void ThreadLocalStorage::set_thread(Thread* thread) {
  pd_set_thread(thread);
  guarantee(get_thread()      == thread, "must be the same thread, quickly");
  guarantee(get_thread_slow() == thread, "must be the same thread, slowly");
}
void ThreadLocalStorage::init() {
  assert(!is_initialized(),
         "More than one attempt to initialize threadLocalStorage");
  pd_init();
  set_thread_index(os::allocate_thread_local_storage());
  generate_code_for_get_thread();
}
bool ThreadLocalStorage::is_initialized() {
    return (thread_index() != -1);
}
#endif // SOLARIS
C:\hotspot-69087d08d473\src\share\vm/runtime/threadLocalStorage.hpp
#ifndef SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP
#define SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP
#include "gc_implementation/shared/gcUtil.hpp"
#include "runtime/os.hpp"
#include "utilities/top.hpp"
extern "C" Thread*   get_thread();
extern "C" uintptr_t _raw_thread_id();
class ThreadLocalStorage : AllStatic {
 public:
  static void    set_thread(Thread* thread);
  static Thread* get_thread_slow();
  static void    invalidate_all() { pd_invalidate_all(); }
  static void    init();
  static bool    is_initialized();
#ifdef TARGET_OS_ARCH_linux_x86
# include "threadLS_linux_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_aarch64
# include "threadLS_linux_aarch64.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "threadLS_linux_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "threadLS_linux_zero.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_x86
# include "threadLS_solaris_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "threadLS_solaris_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_windows_x86
# include "threadLS_windows_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_arm
# include "threadLS_linux_arm.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_ppc
# include "threadLS_linux_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_aix_ppc
# include "threadLS_aix_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_x86
# include "threadLS_bsd_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_zero
# include "threadLS_bsd_zero.hpp"
#endif
#ifndef SOLARIS
 public:
  static inline int  thread_index()              { return _thread_index; }
  static inline void set_thread_index(int index) { _thread_index = index; }
 private:
  static int     _thread_index;
  static void    generate_code_for_get_thread();
  static void pd_set_thread(Thread* thread);
  static void pd_init();
#endif // SOLARIS
  static void pd_invalidate_all();
};
#endif // SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/thread_ext.cpp
#include "precompiled.hpp"
#include "runtime/thread.hpp"
#include "runtime/thread_ext.hpp"
void JavaThread::prepare_ext() {
}
C:\hotspot-69087d08d473\src\share\vm/runtime/thread_ext.hpp
#ifndef SHARE_VM_RUNTIME_THREAD_EXT_HPP
#define SHARE_VM_RUNTIME_THREAD_EXT_HPP
#include "memory/allocation.hpp"
class ThreadExt VALUE_OBJ_CLASS_SPEC {
public:
  void print_on(outputStream* st) const {};
};
#endif // SHARE_VM_RUNTIME_THREAD_EXT_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/timer.cpp
#include "precompiled.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/timer.hpp"
#include "utilities/ostream.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
double TimeHelper::counter_to_seconds(jlong counter) {
  double count = (double) counter;
  double freq  = (double) os::elapsed_frequency();
  return counter/freq;
}
void elapsedTimer::add(elapsedTimer t) {
  _counter += t._counter;
}
void elapsedTimer::start() {
  if (!_active) {
    _active = true;
    _start_counter = os::elapsed_counter();
  }
}
void elapsedTimer::stop() {
  if (_active) {
    _counter += os::elapsed_counter() - _start_counter;
    _active = false;
  }
}
double elapsedTimer::seconds() const {
 return TimeHelper::counter_to_seconds(_counter);
}
jlong elapsedTimer::milliseconds() const {
  jlong ticks_per_ms = os::elapsed_frequency() / 1000;
  return _counter / ticks_per_ms;
}
jlong elapsedTimer::active_ticks() const {
  if (!_active) {
    return ticks();
  }
  jlong counter = _counter + os::elapsed_counter() - _start_counter;
  return counter;
}
void TimeStamp::update_to(jlong ticks) {
  _counter = ticks;
  if (_counter == 0)  _counter = 1;
  assert(is_updated(), "must not look clear");
}
void TimeStamp::update() {
  update_to(os::elapsed_counter());
}
double TimeStamp::seconds() const {
  assert(is_updated(), "must not be clear");
  jlong new_count = os::elapsed_counter();
  return TimeHelper::counter_to_seconds(new_count - _counter);
}
jlong TimeStamp::milliseconds() const {
  assert(is_updated(), "must not be clear");
  jlong new_count = os::elapsed_counter();
  jlong count = new_count - _counter;
  jlong ticks_per_ms = os::elapsed_frequency() / 1000;
  return count / ticks_per_ms;
}
jlong TimeStamp::ticks_since_update() const {
  assert(is_updated(), "must not be clear");
  return os::elapsed_counter() - _counter;
}
TraceTime::TraceTime(const char* title,
                     bool doit) {
  _active   = doit;
  _verbose  = true;
  if (_active) {
    _accum = NULL;
    tty->stamp(PrintGCTimeStamps);
    tty->print("[%s", title);
    tty->flush();
    _t.start();
  }
}
TraceTime::TraceTime(const char* title,
                     elapsedTimer* accumulator,
                     bool doit,
                     bool verbose) {
  _active = doit;
  _verbose = verbose;
  if (_active) {
    if (_verbose) {
      tty->stamp(PrintGCTimeStamps);
      tty->print("[%s", title);
      tty->flush();
    }
    _accum = accumulator;
    _t.start();
  }
}
TraceTime::~TraceTime() {
  if (_active) {
    _t.stop();
    if (_accum!=NULL) _accum->add(_t);
    if (_verbose) {
      tty->print_cr(", %3.7f secs]", _t.seconds());
      tty->flush();
    }
  }
}
TraceCPUTime::TraceCPUTime(bool doit,
               bool print_cr,
               outputStream *logfile) :
  _active(doit),
  _print_cr(print_cr),
  _starting_user_time(0.0),
  _starting_system_time(0.0),
  _starting_real_time(0.0),
  _logfile(logfile),
  _error(false) {
  if (_active) {
    if (logfile != NULL) {
      _logfile = logfile;
    } else {
      _logfile = tty;
    }
    _error = !os::getTimesSecs(&_starting_real_time,
                               &_starting_user_time,
                               &_starting_system_time);
  }
}
TraceCPUTime::~TraceCPUTime() {
  if (_active) {
    bool valid = false;
    if (!_error) {
      double real_secs;                 // walk clock time
      double system_secs;               // system time
      double user_secs;                 // user time for all threads
      double real_time, user_time, system_time;
      valid = os::getTimesSecs(&real_time, &user_time, &system_time);
      if (valid) {
        user_secs = user_time - _starting_user_time;
        system_secs = system_time - _starting_system_time;
        real_secs = real_time - _starting_real_time;
        _logfile->print(" [Times: user=%3.2f sys=%3.2f, real=%3.2f secs] ",
          user_secs, system_secs, real_secs);
      } else {
        _logfile->print("[Invalid result in TraceCPUTime]");
      }
    } else {
      _logfile->print("[Error in TraceCPUTime]");
    }
    if (_print_cr) {
      _logfile->cr();
    }
    _logfile->flush();
  }
}
C:\hotspot-69087d08d473\src\share\vm/runtime/timer.hpp
#ifndef SHARE_VM_RUNTIME_TIMER_HPP
#define SHARE_VM_RUNTIME_TIMER_HPP
#include "utilities/globalDefinitions.hpp"
class elapsedTimer VALUE_OBJ_CLASS_SPEC {
  friend class VMStructs;
 private:
  jlong _counter;
  jlong _start_counter;
  bool  _active;
 public:
  elapsedTimer()             { _active = false; reset(); }
  void add(elapsedTimer t);
  void start();
  void stop();
  void reset()               { _counter = 0; }
  double seconds() const;
  jlong milliseconds() const;
  jlong ticks() const        { return _counter; }
  jlong active_ticks() const;
  bool  is_active() const { return _active; }
};
class TimeStamp VALUE_OBJ_CLASS_SPEC {
 private:
  jlong _counter;
 public:
  TimeStamp()  { _counter = 0; }
  void clear() { _counter = 0; }
  bool is_updated() const { return _counter != 0; }
  void update();
  void update_to(jlong ticks);
  double seconds() const;
  jlong milliseconds() const;
  jlong ticks() const { return _counter; }
  jlong ticks_since_update() const;
};
class TraceTime: public StackObj {
 private:
  bool          _active;    // do timing
  bool          _verbose;   // report every timing
  elapsedTimer  _t;         // timer
  elapsedTimer* _accum;     // accumulator
 public:
  TraceTime(const char* title,
            bool doit = true);
  TraceTime(const char* title,
            elapsedTimer* accumulator,
            bool doit = true,
            bool verbose = false);
  ~TraceTime();
  void set_verbose(bool verbose)  { _verbose = verbose; }
  bool verbose() const            { return _verbose;    }
  void suspend()  { if (_active) _t.stop();  }
  void resume()   { if (_active) _t.start(); }
};
class TraceCPUTime: public StackObj {
 private:
  bool _active;                 // true if times will be measured and printed
  bool _print_cr;               // if true print carriage return at end
  double _starting_user_time;   // user time at start of measurement
  double _starting_system_time; // system time at start of measurement
  double _starting_real_time;   // real time at start of measurement
  outputStream* _logfile;       // output is printed to this stream
  bool _error;                  // true if an error occurred, turns off output
 public:
  TraceCPUTime(bool doit = true,
               bool print_cr = true,
               outputStream *logfile = NULL);
  ~TraceCPUTime();
};
class TimeHelper {
 public:
  static double counter_to_seconds(jlong counter);
};
#endif // SHARE_VM_RUNTIME_TIMER_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/unhandledOops.cpp
#include "precompiled.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "memory/gcLocker.inline.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/thread.hpp"
#include "runtime/unhandledOops.hpp"
#include "utilities/globalDefinitions.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#ifdef CHECK_UNHANDLED_OOPS
const int free_list_size = 256;
UnhandledOops::UnhandledOops(Thread* thread) {
  _thread = thread;
  _oop_list = new (ResourceObj::C_HEAP, mtInternal)
                    GrowableArray<UnhandledOopEntry>(free_list_size, true);
  _level = 0;
}
UnhandledOops::~UnhandledOops() {
  delete _oop_list;
}
void UnhandledOops::dump_oops(UnhandledOops *list) {
  for (int k = 0; k < list->_oop_list->length(); k++) {
    UnhandledOopEntry entry = list->_oop_list->at(k);
    tty->print(" " INTPTR_FORMAT, entry._oop_ptr);
  }
  tty->cr();
}
static bool unhandled_oop_print=0;
void UnhandledOops::register_unhandled_oop(oop* op, address pc) {
  if (!_thread->is_in_stack((address)op))
    return;
  _level ++;
  if (unhandled_oop_print) {
    for (int i=0; i<_level; i++) tty->print(" ");
    tty->print_cr("r " INTPTR_FORMAT, op);
  }
  UnhandledOopEntry entry(op, pc);
  _oop_list->push(entry);
}
bool match_oop_entry(void *op, UnhandledOopEntry e) {
  return (e.oop_ptr() == op);
}
void UnhandledOops::allow_unhandled_oop(oop* op) {
  assert (CheckUnhandledOops, "should only be called with checking option");
  int i = _oop_list->find_from_end(op, match_oop_entry);
  assert(i!=-1, "safe for gc oop not in unhandled_oop_list");
  UnhandledOopEntry entry = _oop_list->at(i);
  assert(!entry._ok_for_gc, "duplicate entry");
  entry._ok_for_gc = true;
  _oop_list->at_put(i, entry);
}
void UnhandledOops::unregister_unhandled_oop(oop* op) {
  if (!_thread->is_in_stack((address)op)) return;
  _level --;
  if (unhandled_oop_print) {
    for (int i=0; i<_level; i++) tty->print(" ");
    tty->print_cr("u " INTPTR_FORMAT, op);
  }
  int i = _oop_list->find_from_end(op, match_oop_entry);
  assert(i!=-1, "oop not in unhandled_oop_list");
  _oop_list->remove_at(i);
}
void UnhandledOops::clear_unhandled_oops() {
  assert (CheckUnhandledOops, "should only be called with checking option");
  for (int k = 0; k < _oop_list->length(); k++) {
    UnhandledOopEntry entry = _oop_list->at(k);
    if(!_thread->is_in_stack((address)entry._oop_ptr)) {
      tty->print_cr("oop_ptr is " INTPTR_FORMAT, (address)entry._oop_ptr);
      tty->print_cr("thread is " INTPTR_FORMAT " from pc " INTPTR_FORMAT,
                     (address)_thread, (address)entry._pc);
      assert(false, "heap is corrupted by the unhandled oop detector");
    }
    if (!entry._ok_for_gc) *(intptr_t*)(entry._oop_ptr) = BAD_OOP_ADDR;
  }
}
#endif // CHECK_UNHANDLED_OOPS
C:\hotspot-69087d08d473\src\share\vm/runtime/unhandledOops.hpp
#ifndef SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP
#define SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP
#ifdef CHECK_UNHANDLED_OOPS
class oop;
class Thread;
class UnhandledOopEntry : public CHeapObj<mtThread> {
 friend class UnhandledOops;
 private:
  oop* _oop_ptr;
  bool _ok_for_gc;
  address _pc;
 public:
  oop* oop_ptr() { return _oop_ptr; }
  UnhandledOopEntry() : _oop_ptr(NULL), _ok_for_gc(false), _pc(NULL) {}
  UnhandledOopEntry(oop* op, address pc) :
                        _oop_ptr(op),   _ok_for_gc(false), _pc(pc) {}
};
class UnhandledOops : public CHeapObj<mtThread> {
 friend class Thread;
 private:
  Thread* _thread;
  int _level;
  GrowableArray<UnhandledOopEntry> *_oop_list;
  void allow_unhandled_oop(oop* op);
  void clear_unhandled_oops();
  UnhandledOops(Thread* thread);
  ~UnhandledOops();
 public:
  static void dump_oops(UnhandledOops* list);
  void register_unhandled_oop(oop* op, address pc);
  void unregister_unhandled_oop(oop* op);
};
#ifdef _LP64
const intptr_t BAD_OOP_ADDR =  0xfffffffffffffff1;
#else
const intptr_t BAD_OOP_ADDR =  0xfffffff1;
#endif // _LP64
#endif // CHECK_UNHANDLED_OOPS
#endif // SHARE_VM_RUNTIME_UNHANDLEDOOPS_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/vframe.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/debugInfoRec.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/objectMonitor.inline.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vframe_hp.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
: _reg_map(reg_map), _thread(thread) {
  assert(fr != NULL, "must have frame");
  _fr = *fr;
}
vframe::vframe(const frame* fr, JavaThread* thread)
: _reg_map(thread), _thread(thread) {
  assert(fr != NULL, "must have frame");
  _fr = *fr;
}
vframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) {
  if (f->is_interpreted_frame()) {
    return new interpretedVFrame(f, reg_map, thread);
  }
  CodeBlob* cb = f->cb();
  if (cb != NULL) {
    if (cb->is_nmethod()) {
      nmethod* nm = (nmethod*)cb;
      return new compiledVFrame(f, reg_map, thread, nm);
    }
    if (f->is_runtime_frame()) {
      RegisterMap temp_map = *reg_map;
      frame s = f->sender(&temp_map);
      return new_vframe(&s, &temp_map, thread);
    }
  }
  return new externalVFrame(f, reg_map, thread);
}
vframe* vframe::sender() const {
  RegisterMap temp_map = *register_map();
  assert(is_top(), "just checking");
  if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL;
  frame s = _fr.real_sender(&temp_map);
  if (s.is_first_frame()) return NULL;
  return vframe::new_vframe(&s, &temp_map, thread());
}
vframe* vframe::top() const {
  vframe* vf = (vframe*) this;
  while (!vf->is_top()) vf = vf->sender();
  return vf;
}
javaVFrame* vframe::java_sender() const {
  vframe* f = sender();
  while (f != NULL) {
    if (f->is_java_frame()) return javaVFrame::cast(f);
    f = f->sender();
  }
  return NULL;
}
GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
  assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(),
         "must be at safepoint or it's a java frame of the current thread");
  GrowableArray<MonitorInfo*>* mons = monitors();
  GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(mons->length());
  if (mons->is_empty()) return result;
  bool found_first_monitor = false;
  ObjectMonitor *pending_monitor = thread()->current_pending_monitor();
  ObjectMonitor *waiting_monitor = thread()->current_waiting_monitor();
  oop pending_obj = (pending_monitor != NULL ? (oop) pending_monitor->object() : (oop) NULL);
  oop waiting_obj = (waiting_monitor != NULL ? (oop) waiting_monitor->object() : (oop) NULL);
  for (int index = (mons->length()-1); index >= 0; index--) {
    MonitorInfo* monitor = mons->at(index);
    if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor
    oop obj = monitor->owner();
    if (obj == NULL) continue; // skip unowned monitor
    if (!found_first_monitor && (obj == pending_obj || obj == waiting_obj)) {
      continue;
    }
    found_first_monitor = true;
    result->append(monitor);
  }
  return result;
}
static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
  if (obj.not_null()) {
    st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
    if (obj->klass() == SystemDictionary::Class_klass()) {
      st->print_cr("(a java.lang.Class for %s)", java_lang_Class::as_external_name(obj()));
    } else {
      Klass* k = obj->klass();
      st->print_cr("(a %s)", k->external_name());
    }
  }
}
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
  ResourceMark rm;
  if (frame_count == 0) {
    if (method()->name() == vmSymbols::wait_name() &&
        method()->method_holder()->name() == vmSymbols::java_lang_Object()) {
      StackValueCollection* locs = locals();
      if (!locs->is_empty()) {
        StackValue* sv = locs->at(0);
        if (sv->type() == T_OBJECT) {
          Handle o = locs->at(0)->get_obj();
          print_locked_object_class_name(st, o, "waiting on");
        }
      }
    } else if (thread()->current_park_blocker() != NULL) {
      oop obj = thread()->current_park_blocker();
      Klass* k = obj->klass();
      st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name());
    }
  }
  GrowableArray<MonitorInfo*>* mons = monitors();
  if (!mons->is_empty()) {
    bool found_first_monitor = false;
    for (int index = (mons->length()-1); index >= 0; index--) {
      MonitorInfo* monitor = mons->at(index);
      if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
        if (monitor->owner_is_scalar_replaced()) {
          Klass* k = java_lang_Class::as_Klass(monitor->owner_klass());
          st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
        } else {
          oop obj = monitor->owner();
          if (obj != NULL) {
            print_locked_object_class_name(st, obj, "eliminated");
          }
        }
        continue;
      }
      if (monitor->owner() != NULL) {
        markOop mark = NULL;
        const char *lock_state = "locked"; // assume we have the monitor locked
        if (!found_first_monitor && frame_count == 0) {
          mark = monitor->owner()->mark();
          if (mark->has_monitor() &&
              ( // we have marked ourself as pending on this monitor
                mark->monitor() == thread()->current_pending_monitor() ||
                !mark->monitor()->is_entered(thread())
              )) {
            lock_state = "waiting to lock";
          } else {
            mark = NULL; // Disable printing below
          }
        }
        print_locked_object_class_name(st, monitor->owner(), lock_state);
        if (Verbose && mark != NULL) {
          st->print("\t  lockbits=");
          mark->print_on(st);
          st->cr();
        }
        found_first_monitor = true;
      }
    }
  }
}
u_char* interpretedVFrame::bcp() const {
  return fr().interpreter_frame_bcp();
}
void interpretedVFrame::set_bcp(u_char* bcp) {
  fr().interpreter_frame_set_bcp(bcp);
}
intptr_t* interpretedVFrame::locals_addr_at(int offset) const {
  assert(fr().is_interpreted_frame(), "frame should be an interpreted frame");
  return fr().interpreter_frame_local_at(offset);
}
GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const {
  GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5);
  for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
       current >= fr().interpreter_frame_monitor_end();
       current = fr().previous_monitor_in_interpreter_frame(current)) {
    result->push(new MonitorInfo(current->obj(), current->lock(), false, false));
  }
  return result;
}
int interpretedVFrame::bci() const {
  return method()->bci_from(bcp());
}
Method* interpretedVFrame::method() const {
  return fr().interpreter_frame_method();
}
static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
                                                   int index,
                                                   const intptr_t* const addr) {
  assert(index >= 0 &&
         index < oop_mask.number_of_entries(), "invariant");
  if (oop_mask.is_oop(index)) {
    Handle h(addr != NULL ? (*(oop*)addr) : (oop)NULL);
    return new StackValue(h);
  }
  return new StackValue(addr != NULL ? *addr : 0);
}
static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) {
  assert(addr != NULL, "invariant");
  if (frame::interpreter_frame_expression_stack_direction() > 0) {
    return addr <= fr.interpreter_frame_tos_address();
  }
  return addr >= fr.interpreter_frame_tos_address();
}
static void stack_locals(StackValueCollection* result,
                         int length,
                         const InterpreterOopMap& oop_mask,
                         const frame& fr) {
  assert(result != NULL, "invariant");
  for (int i = 0; i < length; ++i) {
    const intptr_t* const addr = fr.interpreter_frame_local_at(i);
    assert(addr != NULL, "invariant");
    assert(addr >= fr.sp(), "must be inside the frame");
    StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
    assert(sv != NULL, "sanity check");
    result->add(sv);
  }
}
static void stack_expressions(StackValueCollection* result,
                              int length,
                              int max_locals,
                              const InterpreterOopMap& oop_mask,
                              const frame& fr) {
  assert(result != NULL, "invariant");
  for (int i = 0; i < length; ++i) {
    const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i);
    assert(addr != NULL, "invariant");
    if (!is_in_expression_stack(fr, addr)) {
      addr = NULL;
    }
    StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
                                                           i + max_locals,
                                                           addr);
    assert(sv != NULL, "sanity check");
    result->add(sv);
  }
}
StackValueCollection* interpretedVFrame::locals() const {
  return stack_data(false);
}
StackValueCollection* interpretedVFrame::expressions() const {
  return stack_data(true);
}
                       (false == locals / true == expressions)
StackValueCollection* interpretedVFrame::stack_data(bool expressions) const {
  InterpreterOopMap oop_mask;
  if (TraceDeoptimization && Verbose) {
    methodHandle m_h(Thread::current(), method());
    OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
  } else {
    method()->mask_for(bci(), &oop_mask);
  }
  const int mask_len = oop_mask.number_of_entries();
  const int max_locals = method()->is_native() ?
    method()->size_of_parameters() : method()->max_locals();
  assert(mask_len >= max_locals, "invariant");
  const int length = expressions ? mask_len - max_locals : max_locals;
  assert(length >= 0, "invariant");
  StackValueCollection* const result = new StackValueCollection(length);
  if (0 == length) {
    return result;
  }
  if (expressions) {
    stack_expressions(result, length, max_locals, oop_mask, fr());
  } else {
    stack_locals(result, length, oop_mask, fr());
  }
  assert(length == result->size(), "invariant");
  return result;
}
void interpretedVFrame::set_locals(StackValueCollection* values) const {
  if (values == NULL || values->size() == 0) return;
  const int max_locals = method()->is_native() ?
    method()->size_of_parameters() : method()->max_locals();
  assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data");
  for (int i = 0; i < max_locals; i++) {
    intptr_t *addr = locals_addr_at(i);
    const StackValue* const sv = values->at(i);
    assert(sv != NULL, "sanity check");
    if (sv->type() == T_OBJECT) {
    } else {                   // integer
    }
  }
}
entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
: externalVFrame(fr, reg_map, thread) {}
void vframeStreamCommon::found_bad_method_frame() {
  assert(false, "invalid bci or invalid scope desc");
}
vframeStream::vframeStream(JavaThread* thread, frame top_frame,
  bool stop_at_java_call_stub) : vframeStreamCommon(thread) {
  _stop_at_java_call_stub = stop_at_java_call_stub;
  _frame  = top_frame.sender(&_reg_map);
  while (!fill_from_frame()) {
    _frame = _frame.sender(&_reg_map);
  }
}
void vframeStreamCommon::security_get_caller_frame(int depth) {
  assert(depth >= 0, err_msg("invalid depth: %d", depth));
  for (int n = 0; !at_end(); security_next()) {
    if (!method()->is_ignored_by_security_stack_walk()) {
      if (n == depth) {
        return;
      }
      n++;  // this is a non-skipped frame; count it against the depth
    }
  }
}
void vframeStreamCommon::security_next() {
  if (method()->is_prefixed_native()) {
    skip_prefixed_method_and_wrappers();  // calls next()
  } else {
    next();
  }
}
void vframeStreamCommon::skip_prefixed_method_and_wrappers() {
  ResourceMark rm;
  HandleMark hm;
  int    method_prefix_count = 0;
  char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count);
  KlassHandle prefixed_klass(method()->method_holder());
  const char* prefixed_name = method()->name()->as_C_string();
  size_t prefixed_name_len = strlen(prefixed_name);
  int prefix_index = method_prefix_count-1;
  while (!at_end()) {
    next();
    if (method()->method_holder() != prefixed_klass()) {
      break; // classes don't match, can't be a wrapper
    }
    const char* name = method()->name()->as_C_string();
    size_t name_len = strlen(name);
    size_t prefix_len = prefixed_name_len - name_len;
    if (prefix_len <= 0 || strcmp(name, prefixed_name + prefix_len) != 0) {
      break; // prefixed name isn't prefixed version of method name, can't be a wrapper
    }
    for (; prefix_index >= 0; --prefix_index) {
      const char* possible_prefix = method_prefixes[prefix_index];
      size_t possible_prefix_len = strlen(possible_prefix);
      if (possible_prefix_len == prefix_len &&
          strncmp(possible_prefix, prefixed_name, prefix_len) == 0) {
        break; // matching prefix found
      }
    }
    if (prefix_index < 0) {
      break; // didn't find the prefix, can't be a wrapper
    }
    prefixed_name = name;
    prefixed_name_len = name_len;
  }
}
void vframeStreamCommon::skip_reflection_related_frames() {
  while (!at_end() &&
         (JDK_Version::is_gte_jdk14x_version() && UseNewReflection &&
          (method()->method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) ||
           method()->method_holder()->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) {
    next();
  }
}
#ifndef PRODUCT
void vframe::print() {
  if (WizardMode) _fr.print_value_on(tty,NULL);
}
void vframe::print_value() const {
  ((vframe*)this)->print();
}
void entryVFrame::print_value() const {
  ((entryVFrame*)this)->print();
}
void entryVFrame::print() {
  vframe::print();
  tty->print_cr("C Chunk inbetween Java");
  tty->print_cr("C     link " INTPTR_FORMAT, _fr.link());
}
static void print_stack_values(const char* title, StackValueCollection* values) {
  if (values->is_empty()) return;
  tty->print_cr("\t%s:", title);
  values->print();
}
void javaVFrame::print() {
  ResourceMark rm;
  vframe::print();
  tty->print("\t");
  method()->print_value();
  tty->cr();
  tty->print_cr("\tbci:    %d", bci());
  print_stack_values("locals",      locals());
  print_stack_values("expressions", expressions());
  GrowableArray<MonitorInfo*>* list = monitors();
  if (list->is_empty()) return;
  tty->print_cr("\tmonitor list:");
  for (int index = (list->length()-1); index >= 0; index--) {
    MonitorInfo* monitor = list->at(index);
    tty->print("\t  obj\t");
    if (monitor->owner_is_scalar_replaced()) {
      Klass* k = java_lang_Class::as_Klass(monitor->owner_klass());
      tty->print("( is scalar replaced %s)", k->external_name());
    } else if (monitor->owner() == NULL) {
      tty->print("( null )");
    } else {
      monitor->owner()->print_value();
      tty->print("(owner=" INTPTR_FORMAT ")", (address)monitor->owner());
    }
    if (monitor->eliminated()) {
      if(is_compiled_frame()) {
        tty->print(" ( lock is eliminated in compiled frame )");
      } else {
        tty->print(" ( lock is eliminated, frame not compiled )");
      }
    }
    tty->cr();
    tty->print("\t  ");
    monitor->lock()->print_on(tty);
    tty->cr();
  }
}
void javaVFrame::print_value() const {
  Method*    m = method();
  InstanceKlass*     k = m->method_holder();
  tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")",
                _fr.sp(),  _fr.unextended_sp(), _fr.fp(), _fr.pc());
  tty->print("%s.%s", k->internal_name(), m->name()->as_C_string());
  if (!m->is_native()) {
    Symbol*  source_name = k->source_file_name();
    int        line_number = m->line_number_from_bci(bci());
    if (source_name != NULL && (line_number != -1)) {
      tty->print("(%s:%d)", source_name->as_C_string(), line_number);
    }
  } else {
    tty->print("(Native Method)");
  }
  if (fr().sp() != NULL) {
    RegisterMap map = *register_map();
    uint size = fr().frame_size(&map);
#ifdef _LP64
    if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
#else
    if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
#endif
  }
}
bool javaVFrame::structural_compare(javaVFrame* other) {
  if (method() != other->method()) return false;
  if (bci()    != other->bci())    return false;
  StackValueCollection *locs = locals();
  StackValueCollection *other_locs = other->locals();
  assert(locs->size() == other_locs->size(), "sanity check");
  int i;
  for(i = 0; i < locs->size(); i++) {
    if (       is_compiled_frame() &&       locs->at(i)->type() == T_CONFLICT) continue;
    if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue;
    if (!locs->at(i)->equal(other_locs->at(i)))
      return false;
  }
  StackValueCollection* exprs = expressions();
  StackValueCollection* other_exprs = other->expressions();
  assert(exprs->size() == other_exprs->size(), "sanity check");
  for(i = 0; i < exprs->size(); i++) {
    if (!exprs->at(i)->equal(other_exprs->at(i)))
      return false;
  }
  return true;
}
void javaVFrame::print_activation(int index) const {
  tty->print("%2d - ", index);
  ((vframe*)this)->print_value();
  tty->cr();
  if (WizardMode) {
    ((vframe*)this)->print();
    tty->cr();
  }
}
void javaVFrame::verify() const {
}
void interpretedVFrame::verify() const {
}
void externalVFrame::print() {
  _fr.print_value_on(tty,NULL);
}
void externalVFrame::print_value() const {
  ((vframe*)this)->print();
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/runtime/vframe.hpp
#ifndef SHARE_VM_RUNTIME_VFRAME_HPP
#define SHARE_VM_RUNTIME_VFRAME_HPP
#include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp"
#include "code/location.hpp"
#include "oops/oop.hpp"
#include "runtime/frame.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/stackValue.hpp"
#include "runtime/stackValueCollection.hpp"
#include "utilities/growableArray.hpp"
class vframe: public ResourceObj {
 protected:
  frame        _fr;      // Raw frame behind the virtual frame.
  RegisterMap  _reg_map; // Register map for the raw frame (used to handle callee-saved registers).
  JavaThread*  _thread;  // The thread owning the raw frame.
  vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
  vframe(const frame* fr, JavaThread* thread);
 public:
  static vframe* new_vframe(const frame* f, const RegisterMap *reg_map, JavaThread* thread);
  frame              fr()           const { return _fr;       }
  CodeBlob*          cb()         const { return _fr.cb();  }
  nmethod*           nm()         const {
      assert( cb() != NULL && cb()->is_nmethod(), "usage");
      return (nmethod*) cb();
  }
  frame*             frame_pointer() { return &_fr;       }
  const RegisterMap* register_map() const { return &_reg_map; }
  JavaThread*        thread()       const { return _thread;   }
  virtual vframe* sender() const;
  javaVFrame *java_sender() const;
  virtual bool is_top() const { return true; }
  virtual vframe* top() const;
  virtual bool is_entry_frame()       const { return false; }
  virtual bool is_java_frame()        const { return false; }
  virtual bool is_interpreted_frame() const { return false; }
  virtual bool is_compiled_frame()    const { return false; }
#ifndef PRODUCT
  virtual void print_value() const;
  virtual void print();
#endif
};
class javaVFrame: public vframe {
 public:
  virtual Method*                      method()         const = 0;
  virtual int                          bci()            const = 0;
  virtual StackValueCollection*        locals()         const = 0;
  virtual StackValueCollection*        expressions()    const = 0;
  virtual GrowableArray<MonitorInfo*>* monitors()       const = 0;
  virtual void set_locals(StackValueCollection* values) const = 0;
  bool is_java_frame() const { return true; }
 protected:
  javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
  javaVFrame(const frame* fr, JavaThread* thread) : vframe(fr, thread) {}
 public:
  static javaVFrame* cast(vframe* vf) {
    assert(vf == NULL || vf->is_java_frame(), "must be java frame");
    return (javaVFrame*) vf;
  }
  GrowableArray<MonitorInfo*>* locked_monitors();
  void print_lock_info_on(outputStream* st, int frame_count);
  void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); }
#ifndef PRODUCT
 public:
  void print();
  void print_value() const;
  void print_activation(int index) const;
  virtual void verify() const;
  bool structural_compare(javaVFrame* other);
#endif
  friend class vframe;
};
class interpretedVFrame: public javaVFrame {
 public:
  Method*                      method()         const;
  int                          bci()            const;
  StackValueCollection*        locals()         const;
  StackValueCollection*        expressions()    const;
  GrowableArray<MonitorInfo*>* monitors()       const;
  void set_locals(StackValueCollection* values) const;
  bool is_interpreted_frame() const { return true; }
 protected:
  interpretedVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : javaVFrame(fr, reg_map, thread) {};
 public:
  u_char* bcp() const;
  void set_bcp(u_char* bcp);
  static interpretedVFrame* cast(vframe* vf) {
    assert(vf == NULL || vf->is_interpreted_frame(), "must be interpreted frame");
    return (interpretedVFrame*) vf;
  }
 private:
  static const int bcp_offset;
  intptr_t* locals_addr_at(int offset) const;
  StackValueCollection* stack_data(bool expressions) const;
  int start_of_parameters() const;
#ifndef PRODUCT
 public:
  void verify() const;
#endif
  friend class vframe;
};
class externalVFrame: public vframe {
 protected:
  externalVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {}
#ifndef PRODUCT
 public:
  void print_value() const;
  void print();
#endif
  friend class vframe;
};
class entryVFrame: public externalVFrame {
 public:
  bool is_entry_frame() const { return true; }
 protected:
  entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread);
 public:
  static entryVFrame* cast(vframe* vf) {
    assert(vf == NULL || vf->is_entry_frame(), "must be entry frame");
    return (entryVFrame*) vf;
  }
#ifndef PRODUCT
 public:
  void print_value() const;
  void print();
#endif
  friend class vframe;
};
class MonitorInfo : public ResourceObj {
 private:
  oop        _owner; // the object owning the monitor
  BasicLock* _lock;
  oop        _owner_klass; // klass (mirror) if owner was scalar replaced
  bool       _eliminated;
  bool       _owner_is_scalar_replaced;
 public:
  MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) {
    if (!owner_is_scalar_replaced) {
      _owner = owner;
      _owner_klass = NULL;
    } else {
      assert(eliminated, "monitor should be eliminated for scalar replaced object");
      _owner = NULL;
      _owner_klass = owner;
    }
    _lock  = lock;
    _eliminated = eliminated;
    _owner_is_scalar_replaced = owner_is_scalar_replaced;
  }
  oop        owner() const {
    assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
    return _owner;
  }
  oop   owner_klass() const {
    assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
    return _owner_klass;
  }
  BasicLock* lock()  const { return _lock;  }
  bool eliminated()  const { return _eliminated; }
  bool owner_is_scalar_replaced()  const { return _owner_is_scalar_replaced; }
};
class vframeStreamCommon : StackObj {
 protected:
  frame        _frame;
  JavaThread*  _thread;
  RegisterMap  _reg_map;
  enum { interpreted_mode, compiled_mode, at_end_mode } _mode;
  int _sender_decode_offset;
  Method* _method;
  int       _bci;
  bool _stop_at_java_call_stub;
  bool fill_in_compiled_inlined_sender();
  void fill_from_compiled_frame(int decode_offset);
  void fill_from_compiled_native_frame();
  void found_bad_method_frame();
  void fill_from_interpreter_frame();
  bool fill_from_frame();
  void skip_prefixed_method_and_wrappers();
 public:
  vframeStreamCommon(JavaThread* thread) : _reg_map(thread, false) {
    _thread = thread;
  }
  Method* method() const { return _method; }
  int bci() const { return _bci; }
  intptr_t* frame_id() const { return _frame.id(); }
  address frame_pc() const { return _frame.pc(); }
  CodeBlob*          cb()         const { return _frame.cb();  }
  nmethod*           nm()         const {
      assert( cb() != NULL && cb()->is_nmethod(), "usage");
      return (nmethod*) cb();
  }
  bool is_interpreted_frame() const { return _frame.is_interpreted_frame(); }
  bool is_entry_frame() const       { return _frame.is_entry_frame(); }
  void next() {
    if (_mode == compiled_mode    && fill_in_compiled_inlined_sender()) return;
    do {
      _frame = _frame.sender(&_reg_map);
    } while (!fill_from_frame());
  }
  void security_next();
  bool at_end() const { return _mode == at_end_mode; }
  void security_get_caller_frame(int depth);
  void skip_reflection_related_frames();
};
class vframeStream : public vframeStreamCommon {
 public:
  vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false)
    : vframeStreamCommon(thread) {
    _stop_at_java_call_stub = stop_at_java_call_stub;
    if (!thread->has_last_Java_frame()) {
      _mode = at_end_mode;
      return;
    }
    _frame = _thread->last_frame();
    while (!fill_from_frame()) {
      _frame = _frame.sender(&_reg_map);
    }
  }
  vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false);
};
inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() {
  if (_sender_decode_offset == DebugInformationRecorder::serialized_null) {
    return false;
  }
  fill_from_compiled_frame(_sender_decode_offset);
  return true;
}
inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
  _mode = compiled_mode;
  if (decode_offset == DebugInformationRecorder::serialized_null ||
      decode_offset < 0 ||
      decode_offset >= nm()->scopes_data_size()) {
#ifdef ASSERT
    if (WizardMode) {
      ttyLocker ttyl;
      tty->print_cr("Error in fill_from_frame: pc_desc for "
                    INTPTR_FORMAT " not found or invalid at %d",
                    p2i(_frame.pc()), decode_offset);
      nm()->print();
      nm()->method()->print_codes();
      nm()->print_code();
      nm()->print_pcs();
    }
#endif
    found_bad_method_frame();
    fill_from_compiled_native_frame();
    return;
  }
  DebugInfoReadStream buffer(nm(), decode_offset);
  _sender_decode_offset = buffer.read_int();
  _method               = buffer.read_method();
  _bci                  = buffer.read_bci();
  assert(_method->is_method(), "checking type of decoded method");
}
inline void vframeStreamCommon::fill_from_compiled_native_frame() {
  _mode = compiled_mode;
  _sender_decode_offset = DebugInformationRecorder::serialized_null;
  _method = nm()->method();
  _bci = 0;
}
inline bool vframeStreamCommon::fill_from_frame() {
  if (_frame.is_interpreted_frame()) {
    fill_from_interpreter_frame();
    return true;
  }
  if (cb() != NULL && cb()->is_nmethod()) {
    if (nm()->is_native_method()) {
      fill_from_compiled_native_frame();
    } else {
      PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc());
      int decode_offset;
      if (pc_desc == NULL) {
        JavaThreadState state = _thread->thread_state();
        if (state == _thread_in_Java ) {
          fill_from_compiled_native_frame();
          return true;
        }
        decode_offset = DebugInformationRecorder::serialized_null;
      } else {
        decode_offset = pc_desc->scope_decode_offset();
      }
      fill_from_compiled_frame(decode_offset);
    }
    return true;
  }
  if (_frame.is_first_frame() || (_stop_at_java_call_stub && _frame.is_entry_frame())) {
    _mode = at_end_mode;
    return true;
  }
  return false;
}
inline void vframeStreamCommon::fill_from_interpreter_frame() {
  Method* method = _frame.interpreter_frame_method();
  intptr_t  bcx    = _frame.interpreter_frame_bcx();
  int       bci    = method->validate_bci_from_bcx(bcx);
  if (bci < 0) {
    found_bad_method_frame();
    bci = 0;
  }
  _mode   = interpreted_mode;
  _method = method;
  _bci    = bci;
}
#endif // SHARE_VM_RUNTIME_VFRAME_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/vframeArray.cpp
#include "precompiled.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/monitorChunk.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vframe_hp.hpp"
#include "utilities/events.hpp"
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
int vframeArrayElement:: bci(void) const { return (_bci == SynchronizationEntryBCI ? 0 : _bci); }
void vframeArrayElement::free_monitors(JavaThread* jt) {
  if (_monitors != NULL) {
     MonitorChunk* chunk = _monitors;
     _monitors = NULL;
     jt->remove_monitor_chunk(chunk);
     delete chunk;
  }
}
void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
  _method = vf->method();
  _bci    = vf->raw_bci();
  _reexecute = vf->should_reexecute();
#ifdef ASSERT
  _removed_monitors = false;
#endif
  int index;
  GrowableArray<MonitorInfo*>* list = vf->monitors();
  if (list->is_empty()) {
    _monitors = NULL;
  } else {
    _monitors = new MonitorChunk(list->length());
    vf->thread()->add_monitor_chunk(_monitors);
    for (index = 0; index < list->length(); index++) {
      MonitorInfo* monitor = list->at(index);
      assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
      BasicObjectLock* dest = _monitors->at(index);
      if (monitor->owner_is_scalar_replaced()) {
        dest->set_obj(NULL);
      } else {
        assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
        dest->set_obj(monitor->owner());
        monitor->lock()->move_to(monitor->owner(), dest->lock());
      }
    }
  }
  StackValueCollection *locs = vf->locals();
  _locals = new StackValueCollection(locs->size());
  for(index = 0; index < locs->size(); index++) {
    StackValue* value = locs->at(index);
    switch(value->type()) {
      case T_OBJECT:
        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
        _locals->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
        break;
      case T_CONFLICT:
        _locals->add( new StackValue());
        break;
      case T_INT:
        _locals->add( new StackValue(value->get_int()));
        break;
      default:
        ShouldNotReachHere();
    }
  }
  StackValueCollection *exprs = vf->expressions();
  _expressions = new StackValueCollection(exprs->size());
  for(index = 0; index < exprs->size(); index++) {
    StackValue* value = exprs->at(index);
    switch(value->type()) {
      case T_OBJECT:
        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
        _expressions->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
        break;
      case T_CONFLICT:
        _expressions->add( new StackValue());
        break;
      case T_INT:
        _expressions->add( new StackValue(value->get_int()));
        break;
      default:
        ShouldNotReachHere();
    }
  }
}
int unpack_counter = 0;
void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
                                         int callee_parameters,
                                         int callee_locals,
                                         frame* caller,
                                         bool is_top_frame,
                                         bool is_bottom_frame,
                                         int exec_mode) {
  JavaThread* thread = (JavaThread*) Thread::current();
  address bcp;
  address pc;
  bool use_next_mdp = false; // true if we should use the mdp associated with the next bci
  if (raw_bci() == SynchronizationEntryBCI) {
    bcp = method()->bcp_from(0); // first byte code
    pc  = Interpreter::deopt_entry(vtos, 0); // step = 0 since we don't skip current bytecode
  } else if (should_reexecute()) { //reexecute this bytecode
    assert(is_top_frame, "reexecute allowed only for the top frame");
    bcp = method()->bcp_from(bci());
    pc  = Interpreter::deopt_reexecute_entry(method(), bcp);
  } else {
    bcp = method()->bcp_from(bci());
    pc  = Interpreter::deopt_continue_after_entry(method(), bcp, callee_parameters, is_top_frame);
    use_next_mdp = true;
  }
  assert(Bytecodes::is_defined(*bcp), "must be a valid bytecode");
  assert(*bcp != Bytecodes::_monitorenter || is_top_frame, "a _monitorenter must be a top frame");
  assert(thread->deopt_nmethod() != NULL, "nmethod should be known");
  guarantee(!(thread->deopt_nmethod()->is_compiled_by_c2() &&
              exec_mode == Deoptimization::Unpack_exception),
            "shouldn't get exception during monitorenter");
  int popframe_preserved_args_size_in_bytes = 0;
  int popframe_preserved_args_size_in_words = 0;
  if (is_top_frame) {
    JvmtiThreadState *state = thread->jvmti_thread_state();
    if (JvmtiExport::can_pop_frame() &&
        (thread->has_pending_popframe() || thread->popframe_forcing_deopt_reexecution())) {
      if (thread->has_pending_popframe()) {
#ifndef CC_INTERP
        pc = Interpreter::remove_activation_preserving_args_entry();
#else
        pc = Interpreter::deopt_entry(vtos, 0);
        use_next_mdp = false;
#endif
      } else {
        pc = Interpreter::deopt_entry(vtos, 0);
        use_next_mdp = false;
        popframe_preserved_args_size_in_bytes = in_bytes(thread->popframe_preserved_args_size());
        popframe_preserved_args_size_in_words = in_words(thread->popframe_preserved_args_size_in_words());
      }
    } else if (JvmtiExport::can_force_early_return() && state != NULL && state->is_earlyret_pending()) {
#ifndef CC_INTERP
      pc = Interpreter::remove_activation_early_entry(state->earlyret_tos());
#endif
    } else {
      switch (exec_mode) {
      case Deoptimization::Unpack_deopt:
        break;
      case Deoptimization::Unpack_exception:
        pc = SharedRuntime::raw_exception_handler_for_return_address(thread, pc);
        break;
      case Deoptimization::Unpack_uncommon_trap:
      case Deoptimization::Unpack_reexecute:
        pc  = Interpreter::deopt_entry(vtos, 0);
        use_next_mdp = false;
        break;
      default:
        ShouldNotReachHere();
      }
    }
  }
  assert(method() != NULL, "method must exist");
  int temps = expressions()->size();
  int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors();
  Interpreter::layout_activation(method(),
                                 temps + callee_parameters,
                                 popframe_preserved_args_size_in_words,
                                 locks,
                                 caller_actual_parameters,
                                 callee_parameters,
                                 callee_locals,
                                 caller,
                                 iframe(),
                                 is_top_frame,
                                 is_bottom_frame);
  _frame.patch_pc(thread, pc);
  assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
  BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
  for (int index = 0; index < locks; index++) {
    top = iframe()->previous_monitor_in_interpreter_frame(top);
    BasicObjectLock* src = _monitors->at(index);
    top->set_obj(src->obj());
    src->lock()->move_to(src->obj(), top->lock());
  }
  if (ProfileInterpreter) {
    iframe()->interpreter_frame_set_mdx(0); // clear out the mdp.
  }
  iframe()->interpreter_frame_set_bcx((intptr_t)bcp); // cannot use bcp because frame is not initialized yet
  if (ProfileInterpreter) {
    MethodData* mdo = method()->method_data();
    if (mdo != NULL) {
      int bci = iframe()->interpreter_frame_bci();
      if (use_next_mdp) ++bci;
      address mdp = mdo->bci_to_dp(bci);
      iframe()->interpreter_frame_set_mdp(mdp);
    }
  }
  int i;
  for(i = 0; i < expressions()->size(); i++) {
    StackValue *value = expressions()->at(i);
    intptr_t*   addr  = iframe()->interpreter_frame_expression_stack_at(i);
    switch(value->type()) {
      case T_INT:
        break;
      case T_OBJECT:
        break;
      case T_CONFLICT:
        break;
      default:
        ShouldNotReachHere();
    }
  }
  for(i = 0; i < locals()->size(); i++) {
    StackValue *value = locals()->at(i);
    intptr_t* addr  = iframe()->interpreter_frame_local_at(i);
    switch(value->type()) {
      case T_INT:
        break;
      case T_OBJECT:
        break;
      case T_CONFLICT:
        break;
      default:
        ShouldNotReachHere();
    }
  }
  if (is_top_frame && JvmtiExport::can_pop_frame() && thread->popframe_forcing_deopt_reexecution()) {
    if (popframe_preserved_args_size_in_words != 0) {
      void* saved_args = thread->popframe_preserved_args();
      assert(saved_args != NULL, "must have been saved by interpreter");
#ifdef ASSERT
      assert(popframe_preserved_args_size_in_words <=
             iframe()->interpreter_frame_expression_stack_size()*Interpreter::stackElementWords,
             "expression stack size should have been extended");
#endif // ASSERT
      int top_element = iframe()->interpreter_frame_expression_stack_size()-1;
      intptr_t* base;
      if (frame::interpreter_frame_expression_stack_direction() < 0) {
        base = iframe()->interpreter_frame_expression_stack_at(top_element);
      } else {
        base = iframe()->interpreter_frame_expression_stack();
      }
      Copy::conjoint_jbytes(saved_args,
                            base,
                            popframe_preserved_args_size_in_bytes);
      thread->popframe_free_preserved_args();
    }
  }
#ifndef PRODUCT
  if (TraceDeoptimization && Verbose) {
    ttyLocker ttyl;
    tty->print_cr("[%d Interpreted Frame]", ++unpack_counter);
    iframe()->print_on(tty);
    RegisterMap map(thread);
    vframe* f = vframe::new_vframe(iframe(), &map, thread);
    f->print();
    tty->print_cr("locals size     %d", locals()->size());
    tty->print_cr("expression size %d", expressions()->size());
    method()->print_value();
    tty->cr();
  } else if (TraceDeoptimization) {
    tty->print("     ");
    method()->print_value();
    Bytecodes::Code code = Bytecodes::java_code_at(method(), bcp);
    int bci = method()->bci_from(bcp);
    tty->print(" - %s", Bytecodes::name(code));
    tty->print(" @ bci %d ", bci);
    tty->print_cr("sp = " PTR_FORMAT, iframe()->sp());
  }
#endif // PRODUCT
  _locals = _expressions = NULL;
}
int vframeArrayElement::on_stack_size(int callee_parameters,
                                      int callee_locals,
                                      bool is_top_frame,
                                      int popframe_extra_stack_expression_els) const {
  assert(method()->max_locals() == locals()->size(), "just checking");
  int locks = monitors() == NULL ? 0 : monitors()->number_of_monitors();
  int temps = expressions()->size();
  return Interpreter::size_activation(method()->max_stack(),
                                      temps + callee_parameters,
                                      popframe_extra_stack_expression_els,
                                      locks,
                                      callee_parameters,
                                      callee_locals,
                                      is_top_frame);
}
vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
                                   RegisterMap *reg_map, frame sender, frame caller, frame self,
                                   bool realloc_failures) {
  vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
                                                     sizeof(vframeArrayElement) * (chunk->length() - 1), // variable part
                                                     mtCompiler);
  result->_frames = chunk->length();
  result->_owner_thread = thread;
  result->_sender = sender;
  result->_caller = caller;
  result->_original = self;
  result->set_unroll_block(NULL); // initialize it
  result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures);
  return result;
}
void vframeArray::fill_in(JavaThread* thread,
                          int frame_size,
                          GrowableArray<compiledVFrame*>* chunk,
                          const RegisterMap *reg_map,
                          bool realloc_failures) {
  _frame_size = frame_size;
  for(int i = 0; i < chunk->length(); i++) {
    element(i)->fill_in(chunk->at(i), realloc_failures);
  }
  if (reg_map != NULL) {
    for(int i = 0; i < RegisterMap::reg_count; i++) {
#if defined(AMD64) || defined(AARCH64)
        intptr_t* src = (intptr_t*) reg_map->location(VMRegImpl::as_VMReg(i));
        _callee_registers[i] = src != NULL ? *src : NULL_WORD;
#else
      jint* src = (jint*) reg_map->location(VMRegImpl::as_VMReg(i));
      _callee_registers[i] = src != NULL ? *src : NULL_WORD;
#endif
      if (src == NULL) {
        set_location_valid(i, false);
      } else {
        set_location_valid(i, true);
        jint* dst = (jint*) register_location(i);
      }
    }
  }
}
void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller_actual_parameters) {
  JavaThread* THREAD = JavaThread::current();
  RegisterMap map(THREAD, false);
  frame me = unpack_frame.sender(&map);
  int index;
  for (index = 0; index < frames(); index++ ) {
    me = me.sender(&map);
  }
  frame* caller_frame = &me;
  for (index = frames() - 1; index >= 0 ; index--) {
    vframeArrayElement* elem = element(index);  // caller
    int callee_parameters, callee_locals;
    if (index == 0) {
      callee_parameters = callee_locals = 0;
    } else {
      methodHandle caller = elem->method();
      methodHandle callee = element(index - 1)->method();
      Bytecode_invoke inv(caller, elem->bci());
      const bool has_member_arg =
          !inv.is_invokedynamic() && MethodHandles::has_member_arg(inv.klass(), inv.name());
      callee_parameters = callee->size_of_parameters() + (has_member_arg ? 1 : 0);
      callee_locals     = callee->max_locals();
    }
    elem->unpack_on_stack(caller_actual_parameters,
                          callee_parameters,
                          callee_locals,
                          caller_frame,
                          index == 0,
                          index == frames() - 1,
                          exec_mode);
    if (index == frames() - 1) {
      Deoptimization::unwind_callee_save_values(elem->iframe(), this);
    }
    caller_frame = elem->iframe();
    caller_actual_parameters = callee_parameters;
  }
  deallocate_monitor_chunks();
}
void vframeArray::deallocate_monitor_chunks() {
  JavaThread* jt = JavaThread::current();
  for (int index = 0; index < frames(); index++ ) {
     element(index)->free_monitors(jt);
  }
}
#ifndef PRODUCT
bool vframeArray::structural_compare(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk) {
  if (owner_thread() != thread) return false;
  int index = 0;
#if 0 // FIXME can't do this comparison
  for (deoptimizedVFrame* vf = deoptimizedVFrame::cast(vframe_at(first_index())); vf; vf = vf->deoptimized_sender_or_null()) {
    if (index >= chunk->length() || !vf->structural_compare(chunk->at(index))) return false;
    index++;
  }
  if (index != chunk->length()) return false;
#endif
  return true;
}
#endif
address vframeArray::register_location(int i) const {
  assert(0 <= i && i < RegisterMap::reg_count, "index out of bounds");
  return (address) & _callee_registers[i];
}
#ifndef PRODUCT
void vframeArray::print_on_2(outputStream* st)  {
  st->print_cr(" - sp: " INTPTR_FORMAT, sp());
  st->print(" - thread: ");
  Thread::current()->print();
  st->print_cr(" - frame size: %d", frame_size());
  for (int index = 0; index < frames() ; index++ ) {
    element(index)->print(st);
  }
}
void vframeArrayElement::print(outputStream* st) {
  st->print_cr(" - interpreter_frame -> sp: " INTPTR_FORMAT, iframe()->sp());
}
void vframeArray::print_value_on(outputStream* st) const {
  st->print_cr("vframeArray [%d] ", frames());
}
#endif
C:\hotspot-69087d08d473\src\share\vm/runtime/vframeArray.hpp
#ifndef SHARE_VM_RUNTIME_VFRAMEARRAY_HPP
#define SHARE_VM_RUNTIME_VFRAMEARRAY_HPP
#include "oops/arrayOop.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/monitorChunk.hpp"
#include "utilities/growableArray.hpp"
class LocalsClosure;
class ExpressionStackClosure;
class MonitorStackClosure;
class MonitorArrayElement;
class StackValueCollection;
class vframeArrayElement : public _ValueObj {
  friend class VMStructs;
  private:
    frame _frame;                                                // the interpreter frame we will unpack into
    int  _bci;                                                   // raw bci for this vframe
    bool _reexecute;                                             // whether sould we reexecute this bytecode
    Method*    _method;                                          // the method for this vframe
    MonitorChunk* _monitors;                                     // active monitors for this vframe
    StackValueCollection* _locals;
    StackValueCollection* _expressions;
#ifdef ASSERT
    bool _removed_monitors;
#endif
  public:
  frame* iframe(void)                { return &_frame; }
  int bci(void) const;
  int raw_bci(void) const            { return _bci; }
  bool should_reexecute(void) const  { return _reexecute; }
  Method* method(void) const       { return _method; }
  MonitorChunk* monitors(void) const { return _monitors; }
  void free_monitors(JavaThread* jt);
  StackValueCollection* locals(void) const             { return _locals; }
  StackValueCollection* expressions(void) const        { return _expressions; }
  void fill_in(compiledVFrame* vf, bool realloc_failures);
  int on_stack_size(int callee_parameters,
                    int callee_locals,
                    bool is_top_frame,
                    int popframe_extra_stack_expression_els) const;
  void unpack_on_stack(int caller_actual_parameters,
                       int callee_parameters,
                       int callee_locals,
                       frame* caller,
                       bool is_top_frame,
                       bool is_bottom_frame,
                       int exec_mode);
#ifdef ASSERT
  void set_removed_monitors() {
    _removed_monitors = true;
  }
#endif
#ifndef PRODUCT
  void print(outputStream* st);
#endif /* PRODUCT */
};
class vframeArray: public CHeapObj<mtCompiler> {
  friend class VMStructs;
 private:
      fixed part
        description of the original frame
        _frames - number of vframes in this array
        adapter info
        callee register save area
      variable part
        vframeArrayElement   [ 0 ]
        ...
        vframeArrayElement   [_frames - 1]
  JavaThread*                  _owner_thread;
  vframeArray*                 _next;
  frame                        _original;          // the original frame of the deoptee
  frame                        _caller;            // caller of root frame in vframeArray
  frame                        _sender;
  Deoptimization::UnrollBlock* _unroll_block;
  int                          _frame_size;
  int                          _frames; // number of javavframes in the array (does not count any adapter)
  intptr_t                     _callee_registers[RegisterMap::reg_count];
  unsigned char                _valid[RegisterMap::reg_count];
  vframeArrayElement           _elements[1];   // First variable section.
  void fill_in_element(int index, compiledVFrame* vf);
  bool is_location_valid(int i) const        { return _valid[i] != 0; }
  void set_location_valid(int i, bool valid) { _valid[i] = valid; }
 public:
  bool is_within_bounds(int index) const        { return 0 <= index && index < frames(); }
  int frames() const                            { return _frames;   }
  static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
                               RegisterMap* reg_map, frame sender, frame caller, frame self,
                               bool realloc_failures);
  vframeArrayElement* element(int index)        { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; }
  void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map, bool realloc_failures);
  JavaThread* owner_thread() const           { return _owner_thread; }
  vframeArray* next() const                  { return _next; }
  void set_next(vframeArray* value)          { _next = value; }
  intptr_t* sp() const                       { return _original.sp(); }
  intptr_t* unextended_sp() const            { return _original.unextended_sp(); }
  address original_pc() const                { return _original.pc(); }
  frame original() const                     { return _original; }
  frame caller() const                       { return _caller; }
  frame sender() const                       { return _sender; }
  Deoptimization::UnrollBlock* unroll_block() const         { return _unroll_block; }
  void set_unroll_block(Deoptimization::UnrollBlock* block) { _unroll_block = block; }
  int frame_size() const { return _frame_size; }
  void unpack_to_stack(frame &unpack_frame, int exec_mode, int caller_actual_parameters);
  void deallocate_monitor_chunks();
  address register_location(int i) const;
  void print_on_2(outputStream* st) PRODUCT_RETURN;
  void print_value_on(outputStream* st) const PRODUCT_RETURN;
#ifndef PRODUCT
  bool structural_compare(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk);
#endif
};
#endif // SHARE_VM_RUNTIME_VFRAMEARRAY_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/vframe_hp.cpp
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "code/debugInfoRec.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/basicLock.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/monitorChunk.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vframe_hp.hpp"
#ifdef COMPILER2
#include "opto/matcher.hpp"
#endif
StackValueCollection* compiledVFrame::locals() const {
  if (scope() == NULL) return new StackValueCollection(0);
  GrowableArray<ScopeValue*>*  scv_list = scope()->locals();
  if (scv_list == NULL) return new StackValueCollection(0);
  int length = scv_list->length();
  StackValueCollection* result = new StackValueCollection(length);
  GrowableArray<jvmtiDeferredLocalVariable*>* deferred = NULL;
  GrowableArray<jvmtiDeferredLocalVariableSet*>* list = thread()->deferred_locals();
  if (list != NULL ) {
    for (int i = 0; i < list->length(); i++) {
      if (list->at(i)->matches((vframe*)this)) {
        deferred = list->at(i)->locals();
        break;
      }
    }
  }
  for( int i = 0; i < length; i++ ) {
    result->add( create_stack_value(scv_list->at(i)) );
  }
  if (deferred != NULL) {
    for ( int l = 0;  l < deferred->length() ; l ++) {
      jvmtiDeferredLocalVariable* val = deferred->at(l);
      switch (val->type()) {
      case T_BOOLEAN:
        result->set_int_at(val->index(), val->value().z);
        break;
      case T_CHAR:
        result->set_int_at(val->index(), val->value().c);
        break;
      case T_FLOAT:
        result->set_float_at(val->index(), val->value().f);
        break;
      case T_DOUBLE:
        result->set_double_at(val->index(), val->value().d);
        break;
      case T_BYTE:
        result->set_int_at(val->index(), val->value().b);
        break;
      case T_SHORT:
        result->set_int_at(val->index(), val->value().s);
        break;
      case T_INT:
        result->set_int_at(val->index(), val->value().i);
        break;
      case T_LONG:
        result->set_long_at(val->index(), val->value().j);
        break;
      case T_OBJECT:
        {
          Handle obj((oop)val->value().l);
          result->set_obj_at(val->index(), obj);
        }
        break;
      default:
        ShouldNotReachHere();
      }
    }
  }
  return result;
}
void compiledVFrame::set_locals(StackValueCollection* values) const {
  fatal("Should use update_local for each local update");
}
void compiledVFrame::update_local(BasicType type, int index, jvalue value) {
#ifdef ASSERT
  assert(fr().is_deoptimized_frame(), "frame must be scheduled for deoptimization");
#endif /* ASSERT */
  GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = thread()->deferred_locals();
  if (deferred != NULL ) {
    int f;
    for ( f = 0 ; f < deferred->length() ; f++ ) {
      if (deferred->at(f)->matches(this)) {
        GrowableArray<jvmtiDeferredLocalVariable*>* locals = deferred->at(f)->locals();
        int l;
        for (l = 0 ; l < locals->length() ; l++ ) {
          if (locals->at(l)->index() == index) {
            locals->at(l)->set_value(value);
            return;
          }
        }
        locals->push(new jvmtiDeferredLocalVariable(index, type, value));
        return;
      }
    }
  } else {
    deferred =  new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
    thread()->set_deferred_locals(deferred);
  }
  deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
  assert(deferred->top()->id() == fr().id(), "Huh? Must match");
  deferred->top()->set_local_at(index, type, value);
}
StackValueCollection* compiledVFrame::expressions() const {
  if (scope() == NULL) return new StackValueCollection(0);
  GrowableArray<ScopeValue*>*  scv_list = scope()->expressions();
  if (scv_list == NULL) return new StackValueCollection(0);
  int length = scv_list->length();
  StackValueCollection* result = new StackValueCollection(length);
  for( int i = 0; i < length; i++ )
    result->add( create_stack_value(scv_list->at(i)) );
  return result;
}
StackValue *compiledVFrame::create_stack_value(ScopeValue *sv) const {
  return StackValue::create_stack_value(&_fr, register_map(), sv);
}
BasicLock* compiledVFrame::resolve_monitor_lock(Location location) const {
  return StackValue::resolve_monitor_lock(&_fr, location);
}
GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const {
  if (scope() == NULL) {
    nmethod* nm = code();
    Method* method = nm->method();
    assert(method->is_native(), "");
    if (!method->is_synchronized()) {
      return new GrowableArray<MonitorInfo*>(0);
    }
    GrowableArray<MonitorInfo*> *monitors = new GrowableArray<MonitorInfo*>(1);
    frame& fr = (frame&) _fr;
    MonitorInfo* info = new MonitorInfo(
        fr.get_native_receiver(), fr.get_native_monitor(), false, false);
    monitors->push(info);
    return monitors;
  }
  GrowableArray<MonitorValue*>* monitors = scope()->monitors();
  if (monitors == NULL) {
    return new GrowableArray<MonitorInfo*>(0);
  }
  GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(monitors->length());
  for (int index = 0; index < monitors->length(); index++) {
    MonitorValue* mv = monitors->at(index);
    ScopeValue*   ov = mv->owner();
    StackValue *owner_sv = create_stack_value(ov); // it is an oop
    if (ov->is_object() && owner_sv->obj_is_scalar_replaced()) { // The owner object was scalar replaced
      assert(mv->eliminated(), "monitor should be eliminated for scalar replaced object");
      ScopeValue* kv = ((ObjectValue *)ov)->klass();
      assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object");
      Handle k(((ConstantOopReadValue*)kv)->value()());
      assert(java_lang_Class::is_instance(k()), "must be");
      result->push(new MonitorInfo(k(), resolve_monitor_lock(mv->basic_lock()),
                                   mv->eliminated(), true));
    } else {
      result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()),
                                   mv->eliminated(), false));
    }
  }
  return result;
}
compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm)
: javaVFrame(fr, reg_map, thread) {
  _scope  = NULL;
  if (!nm->is_native_method()) {
    _scope  = nm->scope_desc_at(_fr.pc());
  }
}
compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope)
: javaVFrame(fr, reg_map, thread) {
  _scope  = scope;
  guarantee(_scope != NULL, "scope must be present");
}
bool compiledVFrame::is_top() const {
  if (scope() == NULL) return true;
  return scope()->is_top();
}
nmethod* compiledVFrame::code() const {
  return CodeCache::find_nmethod(_fr.pc());
}
Method* compiledVFrame::method() const {
  if (scope() == NULL) {
    nmethod* nm = code();
    assert(nm->is_native_method(), "must be native");
    return nm->method();
  }
  return scope()->method();
}
int compiledVFrame::bci() const {
  int raw = raw_bci();
  return raw == SynchronizationEntryBCI ? 0 : raw;
}
int compiledVFrame::raw_bci() const {
  if (scope() == NULL) {
    nmethod* nm = code();
    assert(nm->is_native_method(), "must be native");
    return 0;
  }
  return scope()->bci();
}
bool compiledVFrame::should_reexecute() const {
  if (scope() == NULL) {
    nmethod* nm = code();
    assert(nm->is_native_method(), "must be native");
    return false;
  }
  return scope()->should_reexecute();
}
vframe* compiledVFrame::sender() const {
  const frame f = fr();
  if (scope() == NULL) {
    nmethod* nm = code();
    assert(nm->is_native_method(), "must be native");
    return vframe::sender();
  } else {
    return scope()->is_top()
      ? vframe::sender()
      : new compiledVFrame(&f, register_map(), thread(), scope()->sender());
  }
}
jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id) {
  _method = method;
  _bci = bci;
  _id = id;
  _locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
}
jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() {
  for (int i = 0; i < _locals->length() ; i++ ) {
    delete _locals->at(i);
  }
  delete _locals;
}
bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) {
  if (!vf->is_compiled_frame()) return false;
  compiledVFrame* cvf = (compiledVFrame*)vf;
  return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci();
}
void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) {
  int i;
  for ( i = 0 ; i < locals()->length() ; i++ ) {
    if ( locals()->at(i)->index() == idx) {
      assert(locals()->at(i)->type() == type, "Wrong type");
      locals()->at(i)->set_value(val);
      return;
    }
  }
  locals()->push(new jvmtiDeferredLocalVariable(idx, type, val));
}
void jvmtiDeferredLocalVariableSet::oops_do(OopClosure* f) {
  for ( int i = 0; i < locals()->length(); i++ ) {
    if ( locals()->at(i)->type() == T_OBJECT) {
      f->do_oop(locals()->at(i)->oop_addr());
    }
  }
}
jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value) {
  _index = index;
  _type = type;
  _value = value;
}
#ifndef PRODUCT
void compiledVFrame::verify() const {
  Unimplemented();
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/runtime/vframe_hp.hpp
#ifndef SHARE_VM_RUNTIME_VFRAME_HP_HPP
#define SHARE_VM_RUNTIME_VFRAME_HP_HPP
#include "runtime/vframe.hpp"
class compiledVFrame: public javaVFrame {
 public:
  Method*                      method()             const;
  int                          bci()                const;
  bool                         should_reexecute()   const;
  StackValueCollection*        locals()             const;
  StackValueCollection*        expressions()        const;
  GrowableArray<MonitorInfo*>* monitors()           const;
  void set_locals(StackValueCollection* values) const;
  bool is_compiled_frame() const { return true; }
  vframe* sender() const;
  bool is_top() const;
  static compiledVFrame* cast(vframe* vf) {
    assert(vf == NULL || vf->is_compiled_frame(), "must be compiled frame");
    return (compiledVFrame*) vf;
  }
 public:
  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, nmethod* nm);
  void update_local(BasicType type, int index, jvalue value);
  nmethod*  code() const;
  ScopeDesc* scope() const { return _scope; }
  int raw_bci() const;
 protected:
  ScopeDesc* _scope;
  BasicLock* resolve_monitor_lock(Location location) const;
  StackValue *create_stack_value(ScopeValue *sv) const;
 private:
  compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope);
#ifndef PRODUCT
 public:
  void verify() const;
#endif
};
class jvmtiDeferredLocalVariable;
class jvmtiDeferredLocalVariableSet : public CHeapObj<mtCompiler> {
private:
  Method* _method;
  int       _bci;
  intptr_t* _id;
  GrowableArray<jvmtiDeferredLocalVariable*>* _locals;
 public:
  Method*                           method()         const  { return _method; }
  int                               bci()            const  { return _bci; }
  intptr_t*                         id()             const  { return _id; }
  GrowableArray<jvmtiDeferredLocalVariable*>* locals()         const  { return _locals; }
  void                              set_local_at(int idx, BasicType typ, jvalue val);
  bool                              matches(vframe* vf);
  void                              oops_do(OopClosure* f);
  jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id);
  ~jvmtiDeferredLocalVariableSet();
};
class jvmtiDeferredLocalVariable : public CHeapObj<mtCompiler> {
  public:
    jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value);
    BasicType type(void)                   { return _type; }
    int index(void)                        { return _index; }
    jvalue value(void)                     { return _value; }
    void set_value(jvalue value)           { _value = value; }
    oop* oop_addr(void)                    { return (oop*) &_value.l; }
  private:
    BasicType         _type;
    jvalue            _value;
    int               _index;
};
#endif // SHARE_VM_RUNTIME_VFRAME_HP_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/virtualspace.cpp
#include "precompiled.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/virtualspace.hpp"
#include "services/memTracker.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
    _alignment(0), _special(false), _executable(false) {
}
ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) {
  bool has_preferred_page_size = preferred_page_size != 0;
  size_t page_size = has_preferred_page_size ? preferred_page_size : os::page_size_for_region_unaligned(size, 1);
  bool large_pages = page_size != (size_t)os::vm_page_size();
  size_t alignment;
  if (large_pages && has_preferred_page_size) {
    alignment = MAX2(page_size, (size_t)os::vm_allocation_granularity());
    size = align_size_up(size, alignment);
  } else {
    alignment = os::vm_allocation_granularity();
  }
  initialize(size, alignment, large_pages, NULL, 0, false);
}
ReservedSpace::ReservedSpace(size_t size, size_t alignment,
                             bool large,
                             char* requested_address,
                             const size_t noaccess_prefix) {
  initialize(size+noaccess_prefix, alignment, large, requested_address,
             noaccess_prefix, false);
}
ReservedSpace::ReservedSpace(size_t size, size_t alignment,
                             bool large,
                             bool executable) {
  initialize(size, alignment, large, NULL, 0, executable);
}
static bool failed_to_reserve_as_requested(char* base, char* requested_address,
                                           const size_t size, bool special)
{
  if (base == requested_address || requested_address == NULL)
    return false; // did not fail
  if (base != NULL) {
    assert(UseCompressedOops, "currently requested address used only for compressed oops");
    if (PrintCompressedOopsMode) {
      tty->cr();
      tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
    }
    if (special) {
      if (!os::release_memory_special(base, size)) {
        fatal("os::release_memory_special failed");
      }
    } else {
      if (!os::release_memory(base, size)) {
        fatal("os::release_memory failed");
      }
    }
  }
  return true;
}
void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
                               char* requested_address,
                               const size_t noaccess_prefix,
                               bool executable) {
  const size_t granularity = os::vm_allocation_granularity();
  assert((size & (granularity - 1)) == 0,
         "size not aligned to os::vm_allocation_granularity()");
  assert((alignment & (granularity - 1)) == 0,
         "alignment not aligned to os::vm_allocation_granularity()");
  assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
         "not a power of 2");
  alignment = MAX2(alignment, (size_t)os::vm_page_size());
  assert(noaccess_prefix == 0 ||
         noaccess_prefix == alignment, "noaccess prefix wrong");
  _base = NULL;
  _size = 0;
  _special = false;
  _executable = executable;
  _alignment = 0;
  _noaccess_prefix = 0;
  if (size == 0) {
    return;
  }
  bool special = large && !os::can_commit_large_page_memory();
  char* base = NULL;
  if (requested_address != 0) {
    requested_address -= noaccess_prefix; // adjust requested address
    assert(requested_address != NULL, "huge noaccess prefix?");
  }
  if (special) {
    base = os::reserve_memory_special(size, alignment, requested_address, executable);
    if (base != NULL) {
      if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
        return;
      }
      assert((uintptr_t) base % alignment == 0,
             err_msg("Large pages returned a non-aligned address, base: "
                 PTR_FORMAT " alignment: " PTR_FORMAT,
                 base, (void*)(uintptr_t)alignment));
      _special = true;
    } else {
      if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
                            !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
        if (PrintCompressedOopsMode) {
          tty->cr();
          tty->print_cr("Reserve regular memory without large pages.");
        }
      }
    }
  }
  if (base == NULL) {
    if (requested_address != 0) {
      base = os::attempt_reserve_memory_at(size, requested_address);
      if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
        base = NULL;
      }
    } else {
      base = os::reserve_memory(size, NULL, alignment);
    }
    if (base == NULL) return;
    if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
      if (!os::release_memory(base, size)) fatal("os::release_memory failed");
      size = align_size_up(size, alignment);
      base = os::reserve_memory_aligned(size, alignment);
      if (requested_address != 0 &&
          failed_to_reserve_as_requested(base, requested_address, size, false)) {
        assert(_base == NULL, "should be");
        return;
      }
    }
  }
  _base = base;
  _size = size;
  _alignment = alignment;
  _noaccess_prefix = noaccess_prefix;
  assert(noaccess_prefix == 0 ||
         noaccess_prefix == _alignment, "noaccess prefix wrong");
  assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base,
         "area must be distinguisable from marks for mark-sweep");
  assert(markOopDesc::encode_pointer_as_mark(&_base[size])->decode_pointer() == &_base[size],
         "area must be distinguisable from marks for mark-sweep");
}
ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
                             bool special, bool executable) {
  assert((size % os::vm_allocation_granularity()) == 0,
         "size not allocation aligned");
  _base = base;
  _size = size;
  _alignment = alignment;
  _noaccess_prefix = 0;
  _special = special;
  _executable = executable;
}
ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment,
                                        bool split, bool realloc) {
  assert(partition_size <= size(), "partition failed");
  if (split) {
    os::split_reserved_memory(base(), size(), partition_size, realloc);
  }
  ReservedSpace result(base(), partition_size, alignment, special(),
                       executable());
  return result;
}
ReservedSpace
ReservedSpace::last_part(size_t partition_size, size_t alignment) {
  assert(partition_size <= size(), "partition failed");
  ReservedSpace result(base() + partition_size, size() - partition_size,
                       alignment, special(), executable());
  return result;
}
size_t ReservedSpace::page_align_size_up(size_t size) {
  return align_size_up(size, os::vm_page_size());
}
size_t ReservedSpace::page_align_size_down(size_t size) {
  return align_size_down(size, os::vm_page_size());
}
size_t ReservedSpace::allocation_align_size_up(size_t size) {
  return align_size_up(size, os::vm_allocation_granularity());
}
size_t ReservedSpace::allocation_align_size_down(size_t size) {
  return align_size_down(size, os::vm_allocation_granularity());
}
void ReservedSpace::release() {
  if (is_reserved()) {
    char *real_base = _base - _noaccess_prefix;
    const size_t real_size = _size + _noaccess_prefix;
    if (special()) {
      os::release_memory_special(real_base, real_size);
    } else{
      os::release_memory(real_base, real_size);
    }
    _base = NULL;
    _size = 0;
    _noaccess_prefix = 0;
    _special = false;
    _executable = false;
  }
}
void ReservedSpace::protect_noaccess_prefix(const size_t size) {
  assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL &&
                                      (Universe::narrow_oop_base() != NULL) &&
                                      Universe::narrow_oop_use_implicit_null_checks()),
         "noaccess_prefix should be used only with non zero based compressed oops");
  if (_noaccess_prefix == 0) return;
  assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
         "must be at least page size big");
  if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE,
                          _special)) {
    fatal("cannot protect protection page");
  }
  if (PrintCompressedOopsMode) {
    tty->cr();
    tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix);
  }
  _base += _noaccess_prefix;
  _size -= _noaccess_prefix;
  assert((size == _size) && ((uintptr_t)_base % _alignment == 0),
         "must be exactly of required size and alignment");
}
ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment,
                                     bool large, char* requested_address) :
  ReservedSpace(size, alignment, large,
                requested_address,
                (UseCompressedOops && (Universe::narrow_oop_base() != NULL) &&
                 Universe::narrow_oop_use_implicit_null_checks()) ?
                  lcm(os::vm_page_size(), alignment) : 0) {
  if (base() != NULL) {
    MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
  }
  protect_noaccess_prefix(size);
}
ReservedCodeSpace::ReservedCodeSpace(size_t r_size,
                                     size_t rs_align,
                                     bool large) :
  ReservedSpace(r_size, rs_align, large, /*executable*/ true) {
  MemTracker::record_virtual_memory_type((address)base(), mtCode);
}
VirtualSpace::VirtualSpace() {
  _low_boundary           = NULL;
  _high_boundary          = NULL;
  _low                    = NULL;
  _high                   = NULL;
  _lower_high             = NULL;
  _middle_high            = NULL;
  _upper_high             = NULL;
  _lower_high_boundary    = NULL;
  _middle_high_boundary   = NULL;
  _upper_high_boundary    = NULL;
  _lower_alignment        = 0;
  _middle_alignment       = 0;
  _upper_alignment        = 0;
  _special                = false;
  _executable             = false;
}
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
  const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1);
  return initialize_with_granularity(rs, committed_size, max_commit_granularity);
}
bool VirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t committed_size, size_t max_commit_granularity) {
  if(!rs.is_reserved()) return false;  // allocation failed.
  assert(_low_boundary == NULL, "VirtualSpace already initialized");
  assert(max_commit_granularity > 0, "Granularity must be non-zero.");
  _low_boundary  = rs.base();
  _high_boundary = low_boundary() + rs.size();
  _low = low_boundary();
  _high = low();
  _special = rs.special();
  _executable = rs.executable();
  _lower_alignment  = os::vm_page_size();
  _middle_alignment = max_commit_granularity;
  _upper_alignment  = os::vm_page_size();
  _lower_high_boundary = (char*) round_to((intptr_t) low_boundary(), middle_alignment());
  _middle_high_boundary = (char*) round_down((intptr_t) high_boundary(), middle_alignment());
  _upper_high_boundary = high_boundary();
  _lower_high = low_boundary();
  _middle_high = lower_high_boundary();
  _upper_high = middle_high_boundary();
  if (committed_size > 0) {
    if (!expand_by(committed_size)) {
      return false;
    }
  }
  return true;
}
VirtualSpace::~VirtualSpace() {
  release();
}
void VirtualSpace::release() {
  _low_boundary           = NULL;
  _high_boundary          = NULL;
  _low                    = NULL;
  _high                   = NULL;
  _lower_high             = NULL;
  _middle_high            = NULL;
  _upper_high             = NULL;
  _lower_high_boundary    = NULL;
  _middle_high_boundary   = NULL;
  _upper_high_boundary    = NULL;
  _lower_alignment        = 0;
  _middle_alignment       = 0;
  _upper_alignment        = 0;
  _special                = false;
  _executable             = false;
}
size_t VirtualSpace::committed_size() const {
  return pointer_delta(high(), low(), sizeof(char));
}
size_t VirtualSpace::reserved_size() const {
  return pointer_delta(high_boundary(), low_boundary(), sizeof(char));
}
size_t VirtualSpace::uncommitted_size()  const {
  return reserved_size() - committed_size();
}
size_t VirtualSpace::actual_committed_size() const {
  if (special()) {
    return reserved_size();
  }
  size_t committed_low    = pointer_delta(_lower_high,  _low_boundary,         sizeof(char));
  size_t committed_middle = pointer_delta(_middle_high, _lower_high_boundary,  sizeof(char));
  size_t committed_high   = pointer_delta(_upper_high,  _middle_high_boundary, sizeof(char));
#ifdef ASSERT
  size_t lower  = pointer_delta(_lower_high_boundary,  _low_boundary,         sizeof(char));
  size_t middle = pointer_delta(_middle_high_boundary, _lower_high_boundary,  sizeof(char));
  size_t upper  = pointer_delta(_upper_high_boundary,  _middle_high_boundary, sizeof(char));
  if (committed_high > 0) {
    assert(committed_low == lower, "Must be");
    assert(committed_middle == middle, "Must be");
  }
  if (committed_middle > 0) {
    assert(committed_low == lower, "Must be");
  }
  if (committed_middle < middle) {
    assert(committed_high == 0, "Must be");
  }
  if (committed_low < lower) {
    assert(committed_high == 0, "Must be");
    assert(committed_middle == 0, "Must be");
  }
#endif
  return committed_low + committed_middle + committed_high;
}
bool VirtualSpace::contains(const void* p) const {
  return low() <= (const char*) p && (const char*) p < high();
}
   First we need to determine if a particular virtual space is using large
   pages.  This is done at the initialize function and only virtual spaces
   that are larger than LargePageSizeInBytes use large pages.  Once we
   have determined this, all expand_by and shrink_by calls must grow and
   shrink by large page size chunks.  If a particular request
   is within the current large page, the call to commit and uncommit memory
   can be ignored.  In the case that the low and high boundaries of this
   space is not large page aligned, the pages leading to the first large
   page address and the pages after the last large page address must be
   allocated with default pages.
bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) {
  if (uncommitted_size() < bytes) return false;
  if (special()) {
    _high += bytes;
    return true;
  }
  char* previous_high = high();
  char* unaligned_new_high = high() + bytes;
  assert(unaligned_new_high <= high_boundary(),
         "cannot expand by more than upper boundary");
  char* unaligned_lower_new_high =
    MIN2(unaligned_new_high, lower_high_boundary());
  char* unaligned_middle_new_high =
    MIN2(unaligned_new_high, middle_high_boundary());
  char* unaligned_upper_new_high =
    MIN2(unaligned_new_high, upper_high_boundary());
  char* aligned_lower_new_high =
    (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
  char* aligned_middle_new_high =
    (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
  char* aligned_upper_new_high =
    (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
  size_t lower_needs = 0;
  if (aligned_lower_new_high > lower_high()) {
    lower_needs =
      pointer_delta(aligned_lower_new_high, lower_high(), sizeof(char));
  }
  size_t middle_needs = 0;
  if (aligned_middle_new_high > middle_high()) {
    middle_needs =
      pointer_delta(aligned_middle_new_high, middle_high(), sizeof(char));
  }
  size_t upper_needs = 0;
  if (aligned_upper_new_high > upper_high()) {
    upper_needs =
      pointer_delta(aligned_upper_new_high, upper_high(), sizeof(char));
  }
  assert(low_boundary() <= lower_high() &&
         lower_high() <= lower_high_boundary(),
         "high address must be contained within the region");
  assert(lower_high_boundary() <= middle_high() &&
         middle_high() <= middle_high_boundary(),
         "high address must be contained within the region");
  assert(middle_high_boundary() <= upper_high() &&
         upper_high() <= upper_high_boundary(),
         "high address must be contained within the region");
  if (lower_needs > 0) {
    assert(low_boundary() <= lower_high() &&
           lower_high() + lower_needs <= lower_high_boundary(),
           "must not expand beyond region");
    if (!os::commit_memory(lower_high(), lower_needs, _executable)) {
      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
                         ", lower_needs=" SIZE_FORMAT ", %d) failed",
                         lower_high(), lower_needs, _executable);)
      return false;
    } else {
      _lower_high += lower_needs;
    }
  }
  if (middle_needs > 0) {
    assert(lower_high_boundary() <= middle_high() &&
           middle_high() + middle_needs <= middle_high_boundary(),
           "must not expand beyond region");
    if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(),
                           _executable)) {
      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
                         ", middle_needs=" SIZE_FORMAT ", " SIZE_FORMAT
                         ", %d) failed", middle_high(), middle_needs,
                         middle_alignment(), _executable);)
      return false;
    }
    _middle_high += middle_needs;
  }
  if (upper_needs > 0) {
    assert(middle_high_boundary() <= upper_high() &&
           upper_high() + upper_needs <= upper_high_boundary(),
           "must not expand beyond region");
    if (!os::commit_memory(upper_high(), upper_needs, _executable)) {
      debug_only(warning("INFO: os::commit_memory(" PTR_FORMAT
                         ", upper_needs=" SIZE_FORMAT ", %d) failed",
                         upper_high(), upper_needs, _executable);)
      return false;
    } else {
      _upper_high += upper_needs;
    }
  }
  if (pre_touch || AlwaysPreTouch) {
    os::pretouch_memory(previous_high, unaligned_new_high);
  }
  _high += bytes;
  return true;
}
void VirtualSpace::shrink_by(size_t size) {
  if (committed_size() < size)
    fatal("Cannot shrink virtual space to negative size");
  if (special()) {
    _high -= size;
    return;
  }
  char* unaligned_new_high = high() - size;
  assert(unaligned_new_high >= low_boundary(), "cannot shrink past lower boundary");
  char* unaligned_upper_new_high =
    MAX2(unaligned_new_high, middle_high_boundary());
  char* unaligned_middle_new_high =
    MAX2(unaligned_new_high, lower_high_boundary());
  char* unaligned_lower_new_high =
    MAX2(unaligned_new_high, low_boundary());
  char* aligned_upper_new_high =
    (char*) round_to((intptr_t) unaligned_upper_new_high, upper_alignment());
  char* aligned_middle_new_high =
    (char*) round_to((intptr_t) unaligned_middle_new_high, middle_alignment());
  char* aligned_lower_new_high =
    (char*) round_to((intptr_t) unaligned_lower_new_high, lower_alignment());
  size_t upper_needs = 0;
  if (aligned_upper_new_high < upper_high()) {
    upper_needs =
      pointer_delta(upper_high(), aligned_upper_new_high, sizeof(char));
  }
  size_t middle_needs = 0;
  if (aligned_middle_new_high < middle_high()) {
    middle_needs =
      pointer_delta(middle_high(), aligned_middle_new_high, sizeof(char));
  }
  size_t lower_needs = 0;
  if (aligned_lower_new_high < lower_high()) {
    lower_needs =
      pointer_delta(lower_high(), aligned_lower_new_high, sizeof(char));
  }
  assert(middle_high_boundary() <= upper_high() &&
         upper_high() <= upper_high_boundary(),
         "high address must be contained within the region");
  assert(lower_high_boundary() <= middle_high() &&
         middle_high() <= middle_high_boundary(),
         "high address must be contained within the region");
  assert(low_boundary() <= lower_high() &&
         lower_high() <= lower_high_boundary(),
         "high address must be contained within the region");
  if (upper_needs > 0) {
    assert(middle_high_boundary() <= aligned_upper_new_high &&
           aligned_upper_new_high + upper_needs <= upper_high_boundary(),
           "must not shrink beyond region");
    if (!os::uncommit_memory(aligned_upper_new_high, upper_needs)) {
      debug_only(warning("os::uncommit_memory failed"));
      return;
    } else {
      _upper_high -= upper_needs;
    }
  }
  if (middle_needs > 0) {
    assert(lower_high_boundary() <= aligned_middle_new_high &&
           aligned_middle_new_high + middle_needs <= middle_high_boundary(),
           "must not shrink beyond region");
    if (!os::uncommit_memory(aligned_middle_new_high, middle_needs)) {
      debug_only(warning("os::uncommit_memory failed"));
      return;
    } else {
      _middle_high -= middle_needs;
    }
  }
  if (lower_needs > 0) {
    assert(low_boundary() <= aligned_lower_new_high &&
           aligned_lower_new_high + lower_needs <= lower_high_boundary(),
           "must not shrink beyond region");
    if (!os::uncommit_memory(aligned_lower_new_high, lower_needs)) {
      debug_only(warning("os::uncommit_memory failed"));
      return;
    } else {
      _lower_high -= lower_needs;
    }
  }
  _high -= size;
}
#ifndef PRODUCT
void VirtualSpace::check_for_contiguity() {
  assert(low_boundary() <= lower_high() &&
         lower_high() <= lower_high_boundary(),
         "high address must be contained within the region");
  assert(lower_high_boundary() <= middle_high() &&
         middle_high() <= middle_high_boundary(),
         "high address must be contained within the region");
  assert(middle_high_boundary() <= upper_high() &&
         upper_high() <= upper_high_boundary(),
         "high address must be contained within the region");
  assert(low() >= low_boundary(), "low");
  assert(low_boundary() <= lower_high_boundary(), "lower high boundary");
  assert(upper_high_boundary() <= high_boundary(), "upper high boundary");
  assert(high() <= upper_high(), "upper high");
}
void VirtualSpace::print_on(outputStream* out) {
  out->print   ("Virtual space:");
  if (special()) out->print(" (pinned in memory)");
  out->cr();
  out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
  out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
  out->print_cr(" - [low, high]:     [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  low(), high());
  out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  low_boundary(), high_boundary());
}
void VirtualSpace::print() {
  print_on(tty);
}
#ifndef PRODUCT
#define test_log(...) \
  do {\
    if (VerboseInternalVMTests) { \
      tty->print_cr(__VA_ARGS__); \
      tty->flush(); \
    }\
  } while (false)
class TestReservedSpace : AllStatic {
 public:
  static void small_page_write(void* addr, size_t size) {
    size_t page_size = os::vm_page_size();
    char* end = (char*)addr + size;
    for (char* p = (char*)addr; p < end; p += page_size) {
    }
  }
  static void release_memory_for_test(ReservedSpace rs) {
    if (rs.special()) {
      guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
    } else {
      guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
    }
  }
  static void test_reserved_space1(size_t size, size_t alignment) {
    test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
    assert(is_size_aligned(size, alignment), "Incorrect input parameters");
    ReservedSpace rs(size,          // size
                     alignment,     // alignment
                     UseLargePages, // large
                     NULL,          // requested_address
                     0);            // noacces_prefix
    test_log(" rs.special() == %d", rs.special());
    assert(rs.base() != NULL, "Must be");
    assert(rs.size() == size, "Must be");
    assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
    assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
    if (rs.special()) {
      small_page_write(rs.base(), size);
    }
    release_memory_for_test(rs);
  }
  static void test_reserved_space2(size_t size) {
    test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
    assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
    ReservedSpace rs(size);
    test_log(" rs.special() == %d", rs.special());
    assert(rs.base() != NULL, "Must be");
    assert(rs.size() == size, "Must be");
    if (rs.special()) {
      small_page_write(rs.base(), size);
    }
    release_memory_for_test(rs);
  }
  static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
    test_log("test_reserved_space3(%p, %p, %d)",
        (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
    assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
    assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
    bool large = maybe_large && UseLargePages && size >= os::large_page_size();
    ReservedSpace rs(size, alignment, large, false);
    test_log(" rs.special() == %d", rs.special());
    assert(rs.base() != NULL, "Must be");
    assert(rs.size() == size, "Must be");
    if (rs.special()) {
      small_page_write(rs.base(), size);
    }
    release_memory_for_test(rs);
  }
  static void test_reserved_space1() {
    size_t size = 2 * 1024 * 1024;
    size_t ag   = os::vm_allocation_granularity();
    test_reserved_space1(size,      ag);
    test_reserved_space1(size * 2,  ag);
    test_reserved_space1(size * 10, ag);
  }
  static void test_reserved_space2() {
    size_t size = 2 * 1024 * 1024;
    size_t ag = os::vm_allocation_granularity();
    test_reserved_space2(size * 1);
    test_reserved_space2(size * 2);
    test_reserved_space2(size * 10);
    test_reserved_space2(ag);
    test_reserved_space2(size - ag);
    test_reserved_space2(size);
    test_reserved_space2(size + ag);
    test_reserved_space2(size * 2);
    test_reserved_space2(size * 2 - ag);
    test_reserved_space2(size * 2 + ag);
    test_reserved_space2(size * 3);
    test_reserved_space2(size * 3 - ag);
    test_reserved_space2(size * 3 + ag);
    test_reserved_space2(size * 10);
    test_reserved_space2(size * 10 + size / 2);
  }
  static void test_reserved_space3() {
    size_t ag = os::vm_allocation_granularity();
    test_reserved_space3(ag,      ag    , false);
    test_reserved_space3(ag * 2,  ag    , false);
    test_reserved_space3(ag * 3,  ag    , false);
    test_reserved_space3(ag * 2,  ag * 2, false);
    test_reserved_space3(ag * 4,  ag * 2, false);
    test_reserved_space3(ag * 8,  ag * 2, false);
    test_reserved_space3(ag * 4,  ag * 4, false);
    test_reserved_space3(ag * 8,  ag * 4, false);
    test_reserved_space3(ag * 16, ag * 4, false);
    if (UseLargePages) {
      size_t lp = os::large_page_size();
      test_reserved_space3(lp,     ag * 4, false);
      test_reserved_space3(lp * 2, ag * 4, false);
      test_reserved_space3(lp * 4, ag * 4, false);
      test_reserved_space3(lp,     lp    , false);
      test_reserved_space3(lp * 2, lp    , false);
      test_reserved_space3(lp * 3, lp    , false);
      test_reserved_space3(lp * 2, lp * 2, false);
      test_reserved_space3(lp * 4, lp * 2, false);
      test_reserved_space3(lp * 8, lp * 2, false);
      test_reserved_space3(lp, ag * 4    , true);
      test_reserved_space3(lp * 2, ag * 4, true);
      test_reserved_space3(lp * 4, ag * 4, true);
      test_reserved_space3(lp, lp        , true);
      test_reserved_space3(lp * 2, lp    , true);
      test_reserved_space3(lp * 3, lp    , true);
      test_reserved_space3(lp * 2, lp * 2, true);
      test_reserved_space3(lp * 4, lp * 2, true);
      test_reserved_space3(lp * 8, lp * 2, true);
    }
  }
  static void test_reserved_space() {
    test_reserved_space1();
    test_reserved_space2();
    test_reserved_space3();
  }
};
void TestReservedSpace_test() {
  TestReservedSpace::test_reserved_space();
}
#define assert_equals(actual, expected)     \
  assert(actual == expected,                \
    err_msg("Got " SIZE_FORMAT " expected " \
      SIZE_FORMAT, actual, expected));
#define assert_ge(value1, value2)                  \
  assert(value1 >= value2,                         \
    err_msg("'" #value1 "': " SIZE_FORMAT " '"     \
      #value2 "': " SIZE_FORMAT, value1, value2));
#define assert_lt(value1, value2)                  \
  assert(value1 < value2,                          \
    err_msg("'" #value1 "': " SIZE_FORMAT " '"     \
      #value2 "': " SIZE_FORMAT, value1, value2));
class TestVirtualSpace : AllStatic {
  enum TestLargePages {
    Default,
    Disable,
    Reserve,
    Commit
  };
  static ReservedSpace reserve_memory(size_t reserve_size_aligned, TestLargePages mode) {
    switch(mode) {
    default:
    case Default:
    case Reserve:
      return ReservedSpace(reserve_size_aligned);
    case Disable:
    case Commit:
      return ReservedSpace(reserve_size_aligned,
                           os::vm_allocation_granularity(),
    }
  }
  static bool initialize_virtual_space(VirtualSpace& vs, ReservedSpace rs, TestLargePages mode) {
    switch(mode) {
    default:
    case Default:
    case Reserve:
      return vs.initialize(rs, 0);
    case Disable:
      return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
    case Commit:
      return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1));
    }
  }
 public:
  static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size,
                                                        TestLargePages mode = Default) {
    size_t granularity = os::vm_allocation_granularity();
    size_t reserve_size_aligned = align_size_up(reserve_size, granularity);
    ReservedSpace reserved = reserve_memory(reserve_size_aligned, mode);
    assert(reserved.is_reserved(), "Must be");
    VirtualSpace vs;
    bool initialized = initialize_virtual_space(vs, reserved, mode);
    assert(initialized, "Failed to initialize VirtualSpace");
    vs.expand_by(commit_size, false);
    if (vs.special()) {
      assert_equals(vs.actual_committed_size(), reserve_size_aligned);
    } else {
      assert_ge(vs.actual_committed_size(), commit_size);
      size_t commit_granularity = (mode == Disable || !UseLargePages) ?
                                   os::vm_page_size() : os::large_page_size();
      assert_lt(vs.actual_committed_size(), commit_size + commit_granularity);
    }
    reserved.release();
  }
  static void test_virtual_space_actual_committed_space_one_large_page() {
    if (!UseLargePages) {
      return;
    }
    size_t large_page_size = os::large_page_size();
    ReservedSpace reserved(large_page_size, large_page_size, true, false);
    assert(reserved.is_reserved(), "Must be");
    VirtualSpace vs;
    bool initialized = vs.initialize(reserved, 0);
    assert(initialized, "Failed to initialize VirtualSpace");
    vs.expand_by(large_page_size, false);
    assert_equals(vs.actual_committed_size(), large_page_size);
    reserved.release();
  }
  static void test_virtual_space_actual_committed_space() {
    test_virtual_space_actual_committed_space(4 * K, 0);
    test_virtual_space_actual_committed_space(4 * K, 4 * K);
    test_virtual_space_actual_committed_space(8 * K, 0);
    test_virtual_space_actual_committed_space(8 * K, 4 * K);
    test_virtual_space_actual_committed_space(8 * K, 8 * K);
    test_virtual_space_actual_committed_space(12 * K, 0);
    test_virtual_space_actual_committed_space(12 * K, 4 * K);
    test_virtual_space_actual_committed_space(12 * K, 8 * K);
    test_virtual_space_actual_committed_space(12 * K, 12 * K);
    test_virtual_space_actual_committed_space(64 * K, 0);
    test_virtual_space_actual_committed_space(64 * K, 32 * K);
    test_virtual_space_actual_committed_space(64 * K, 64 * K);
    test_virtual_space_actual_committed_space(2 * M, 0);
    test_virtual_space_actual_committed_space(2 * M, 4 * K);
    test_virtual_space_actual_committed_space(2 * M, 64 * K);
    test_virtual_space_actual_committed_space(2 * M, 1 * M);
    test_virtual_space_actual_committed_space(2 * M, 2 * M);
    test_virtual_space_actual_committed_space(10 * M, 0);
    test_virtual_space_actual_committed_space(10 * M, 4 * K);
    test_virtual_space_actual_committed_space(10 * M, 8 * K);
    test_virtual_space_actual_committed_space(10 * M, 1 * M);
    test_virtual_space_actual_committed_space(10 * M, 2 * M);
    test_virtual_space_actual_committed_space(10 * M, 5 * M);
    test_virtual_space_actual_committed_space(10 * M, 10 * M);
  }
  static void test_virtual_space_disable_large_pages() {
    if (!UseLargePages) {
      return;
    }
    test_virtual_space_actual_committed_space(10 * M, 0, Disable);
    test_virtual_space_actual_committed_space(10 * M, 4 * K, Disable);
    test_virtual_space_actual_committed_space(10 * M, 8 * K, Disable);
    test_virtual_space_actual_committed_space(10 * M, 1 * M, Disable);
    test_virtual_space_actual_committed_space(10 * M, 2 * M, Disable);
    test_virtual_space_actual_committed_space(10 * M, 5 * M, Disable);
    test_virtual_space_actual_committed_space(10 * M, 10 * M, Disable);
    test_virtual_space_actual_committed_space(10 * M, 0, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 4 * K, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 8 * K, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 1 * M, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 2 * M, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 5 * M, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 10 * M, Reserve);
    test_virtual_space_actual_committed_space(10 * M, 0, Commit);
    test_virtual_space_actual_committed_space(10 * M, 4 * K, Commit);
    test_virtual_space_actual_committed_space(10 * M, 8 * K, Commit);
    test_virtual_space_actual_committed_space(10 * M, 1 * M, Commit);
    test_virtual_space_actual_committed_space(10 * M, 2 * M, Commit);
    test_virtual_space_actual_committed_space(10 * M, 5 * M, Commit);
    test_virtual_space_actual_committed_space(10 * M, 10 * M, Commit);
  }
  static void test_virtual_space() {
    test_virtual_space_actual_committed_space();
    test_virtual_space_actual_committed_space_one_large_page();
    test_virtual_space_disable_large_pages();
  }
};
void TestVirtualSpace_test() {
  TestVirtualSpace::test_virtual_space();
}
#endif // PRODUCT
#endif
C:\hotspot-69087d08d473\src\share\vm/runtime/virtualspace.hpp
#ifndef SHARE_VM_RUNTIME_VIRTUALSPACE_HPP
#define SHARE_VM_RUNTIME_VIRTUALSPACE_HPP
#include "memory/allocation.hpp"
class ReservedSpace VALUE_OBJ_CLASS_SPEC {
  friend class VMStructs;
 private:
  char*  _base;
  size_t _size;
  size_t _noaccess_prefix;
  size_t _alignment;
  bool   _special;
  bool   _executable;
  ReservedSpace(char* base, size_t size, size_t alignment, bool special,
                bool executable);
  void initialize(size_t size, size_t alignment, bool large,
                  char* requested_address,
                  const size_t noaccess_prefix,
                  bool executable);
 protected:
  void protect_noaccess_prefix(const size_t size);
 public:
  ReservedSpace();
  ReservedSpace(size_t size, size_t preferred_page_size = 0);
  ReservedSpace(size_t size, size_t alignment, bool large,
                char* requested_address = NULL,
                const size_t noaccess_prefix = 0);
  ReservedSpace(size_t size, size_t alignment, bool large, bool executable);
  char*  base()            const { return _base;      }
  size_t size()            const { return _size;      }
  size_t alignment()       const { return _alignment; }
  bool   special()         const { return _special;   }
  bool   executable()      const { return _executable;   }
  size_t noaccess_prefix() const { return _noaccess_prefix;   }
  bool is_reserved()       const { return _base != NULL; }
  void release();
  ReservedSpace first_part(size_t partition_size, size_t alignment,
                           bool split = false, bool realloc = true);
  ReservedSpace last_part (size_t partition_size, size_t alignment);
  inline ReservedSpace first_part(size_t partition_size,
                                  bool split = false, bool realloc = true);
  inline ReservedSpace last_part (size_t partition_size);
  static size_t page_align_size_up(size_t size);
  static size_t page_align_size_down(size_t size);
  static size_t allocation_align_size_up(size_t size);
  static size_t allocation_align_size_down(size_t size);
};
ReservedSpace
ReservedSpace::first_part(size_t partition_size, bool split, bool realloc)
{
  return first_part(partition_size, alignment(), split, realloc);
}
ReservedSpace ReservedSpace::last_part(size_t partition_size)
{
  return last_part(partition_size, alignment());
}
class ReservedHeapSpace : public ReservedSpace {
public:
  ReservedHeapSpace(size_t size, size_t forced_base_alignment,
                    bool large, char* requested_address);
};
class ReservedCodeSpace : public ReservedSpace {
 public:
  ReservedCodeSpace(size_t r_size, size_t rs_align, bool large);
};
class VirtualSpace VALUE_OBJ_CLASS_SPEC {
  friend class VMStructs;
 private:
  char* _low_boundary;
  char* _high_boundary;
  char* _low;
  char* _high;
  bool _special;
  bool   _executable;
  char* _lower_high;
  char* _middle_high;
  char* _upper_high;
  char* _lower_high_boundary;
  char* _middle_high_boundary;
  char* _upper_high_boundary;
  size_t _lower_alignment;
  size_t _middle_alignment;
  size_t _upper_alignment;
  char* lower_high() const { return _lower_high; }
  char* middle_high() const { return _middle_high; }
  char* upper_high() const { return _upper_high; }
  char* lower_high_boundary() const { return _lower_high_boundary; }
  char* middle_high_boundary() const { return _middle_high_boundary; }
  char* upper_high_boundary() const { return _upper_high_boundary; }
  size_t lower_alignment() const { return _lower_alignment; }
  size_t middle_alignment() const { return _middle_alignment; }
  size_t upper_alignment() const { return _upper_alignment; }
 public:
  char* low()  const { return _low; }
  char* high() const { return _high; }
  char* low_boundary()  const { return _low_boundary; }
  char* high_boundary() const { return _high_boundary; }
  bool special() const { return _special; }
 public:
  VirtualSpace();
  bool initialize_with_granularity(ReservedSpace rs, size_t committed_byte_size, size_t max_commit_ganularity);
  bool initialize(ReservedSpace rs, size_t committed_byte_size);
  ~VirtualSpace();
  size_t reserved_size() const;
  size_t actual_committed_size() const;
  size_t committed_size() const;
  size_t uncommitted_size() const;
  bool   contains(const void* p) const;
  bool expand_by(size_t bytes, bool pre_touch = false);
  void shrink_by(size_t bytes);
  void release();
  void check_for_contiguity() PRODUCT_RETURN;
  void print_on(outputStream* out) PRODUCT_RETURN;
  void print();
};
#endif // SHARE_VM_RUNTIME_VIRTUALSPACE_HPP
C:\hotspot-69087d08d473\src\share\vm/runtime/vmStructs.cpp
#include "precompiled.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/systemDictionary.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciSymbol.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/compressedStream.hpp"
#include "code/location.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/stubs.hpp"
#include "code/vmreg.hpp"
#include "compiler/oopMap.hpp"
#include "compiler/compileBroker.hpp"
#include "gc_implementation/shared/immutableSpace.hpp"
#include "gc_implementation/shared/markSweep.hpp"
#include "gc_implementation/shared/mutableSpace.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "interpreter/bytecodeInterpreter.hpp"
#include "interpreter/bytecodes.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.hpp"
#include "memory/cardTableRS.hpp"
#include "memory/defNewGeneration.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/genCollectedHeap.hpp"
#include "memory/generation.hpp"
#include "memory/generationSpec.hpp"
#include "memory/heap.hpp"
#include "memory/metachunk.hpp"
#include "memory/referenceType.hpp"
#include "memory/space.hpp"
#include "memory/tenuredGeneration.hpp"
#include "memory/universe.hpp"
#include "memory/watermark.hpp"
#include "oops/arrayKlass.hpp"
#include "oops/arrayOop.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/constMethod.hpp"
#include "oops/constantPool.hpp"
#include "oops/cpCache.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/klass.hpp"
#include "oops/markOop.hpp"
#include "oops/methodData.hpp"
#include "oops/methodCounters.hpp"
#include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.hpp"
#include "prims/jvmtiAgentThread.hpp"
#include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/globals.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/serviceThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/virtualspace.hpp"
#include "runtime/vmStructs.hpp"
#include "utilities/array.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp"
#ifdef TARGET_ARCH_x86
# include "vmStructs_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "vmStructs_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "vmStructs_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "vmStructs_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "vmStructs_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "vmStructs_ppc.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_x86
# include "vmStructs_linux_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_aarch64
# include "vmStructs_linux_aarch64.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "vmStructs_linux_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "vmStructs_linux_zero.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_x86
# include "vmStructs_solaris_x86.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "vmStructs_solaris_sparc.hpp"
#endif
#ifdef TARGET_OS_ARCH_windows_x86
# include "vmStructs_windows_x86.hpp"
#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值