< prev index next >

src/hotspot/share/runtime/thread.cpp

Print this page
*** 37,10 ***
--- 37,11 ---
  #include "code/scopeDesc.hpp"
  #include "compiler/compileBroker.hpp"
  #include "compiler/compileTask.hpp"
  #include "compiler/compilerThread.hpp"
  #include "gc/shared/barrierSet.hpp"
+ #include "gc/shared/barrierSetNMethod.hpp"
  #include "gc/shared/collectedHeap.hpp"
  #include "gc/shared/gcId.hpp"
  #include "gc/shared/gcLocker.inline.hpp"
  #include "gc/shared/gcVMOperations.hpp"
  #include "gc/shared/oopStorage.hpp"

*** 71,11 ***
  #include "oops/typeArrayOop.inline.hpp"
  #include "oops/verifyOopClosure.hpp"
  #include "prims/jvm_misc.hpp"
  #include "prims/jvmtiDeferredUpdates.hpp"
  #include "prims/jvmtiExport.hpp"
! #include "prims/jvmtiThreadState.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/fieldDescriptor.inline.hpp"
  #include "runtime/flags/jvmFlagLimit.hpp"
  #include "runtime/deoptimization.hpp"
--- 72,11 ---
  #include "oops/typeArrayOop.inline.hpp"
  #include "oops/verifyOopClosure.hpp"
  #include "prims/jvm_misc.hpp"
  #include "prims/jvmtiDeferredUpdates.hpp"
  #include "prims/jvmtiExport.hpp"
! #include "prims/jvmtiThreadState.inline.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/fieldDescriptor.inline.hpp"
  #include "runtime/flags/jvmFlagLimit.hpp"
  #include "runtime/deoptimization.hpp"

*** 268,10 ***
--- 269,12 ---
    // BarrierSet::on_thread_create() for this thread is therefore deferred
    // to BarrierSet::set_barrier_set().
    BarrierSet* const barrier_set = BarrierSet::barrier_set();
    if (barrier_set != NULL) {
      barrier_set->on_thread_create(this);
+     BarrierSetNMethod* bs_nm = barrier_set->barrier_set_nmethod();
+     _nmethod_disarm_value = bs_nm->disarmed_value();
    } else {
      // Only the main thread should be created before the barrier set
      // and that happens just before Thread::current is set. No other thread
      // can attach as the VM is not created yet, so they can't execute this code.
      // If the main thread creates other threads before the barrier set that is an error.

*** 704,12 ***
  
    // Cannot use JavaCalls::construct_new_instance because the java.lang.Thread
    // constructor calls Thread.current(), which must be set here for the
    // initial thread.
    java_lang_Thread::set_thread(thread_oop(), thread);
!   java_lang_Thread::set_priority(thread_oop(), NormPriority);
-   thread->set_threadObj(thread_oop());
  
    Handle string = java_lang_String::create_from_str("main", CHECK);
  
    JavaValue result(T_VOID);
    JavaCalls::call_special(&result, thread_oop,
--- 707,11 ---
  
    // Cannot use JavaCalls::construct_new_instance because the java.lang.Thread
    // constructor calls Thread.current(), which must be set here for the
    // initial thread.
    java_lang_Thread::set_thread(thread_oop(), thread);
!   thread->set_threadOopHandles(thread_oop());
  
    Handle string = java_lang_String::create_from_str("main", CHECK);
  
    JavaValue result(T_VOID);
    JavaCalls::call_special(&result, thread_oop,

*** 761,17 ***
  }
  
  // Initialized by VMThread at vm_global_init
  static OopStorage* _thread_oop_storage = NULL;
  
! oop  JavaThread::threadObj() const    {
    return _threadObj.resolve();
  }
  
! void JavaThread::set_threadObj(oop p) {
    assert(_thread_oop_storage != NULL, "not yet initialized");
!   _threadObj = OopHandle(_thread_oop_storage, p);
  }
  
  OopStorage* JavaThread::thread_oop_storage() {
    assert(_thread_oop_storage != NULL, "not yet initialized");
    return _thread_oop_storage;
--- 763,37 ---
  }
  
  // Initialized by VMThread at vm_global_init
  static OopStorage* _thread_oop_storage = NULL;
  
! oop JavaThread::threadObj() const    {
    return _threadObj.resolve();
  }
  
! void JavaThread::set_threadOopHandles(oop p) {
    assert(_thread_oop_storage != NULL, "not yet initialized");
!   _threadObj   = OopHandle(_thread_oop_storage, p);
+   _vthread     = OopHandle(_thread_oop_storage, p);
+   _scopeLocalCache = OopHandle(_thread_oop_storage, NULL);
+ }
+ 
+ oop JavaThread::scopeLocalCache() const {
+   return _scopeLocalCache.resolve();
+ }
+ 
+ oop JavaThread::vthread() const {
+   return _vthread.resolve();
+ }
+ 
+ void JavaThread::set_vthread(oop p) {
+   assert(_thread_oop_storage != NULL, "not yet initialized");
+   _vthread.replace(p);
+ }
+ 
+ void JavaThread::set_scopeLocalCache(oop p) {
+   assert(_thread_oop_storage != NULL, "not yet initialized");
+   _scopeLocalCache.replace(p);
  }
  
  OopStorage* JavaThread::thread_oop_storage() {
    assert(_thread_oop_storage != NULL, "not yet initialized");
    return _thread_oop_storage;

*** 788,12 ***
  
    // We are called from jni_AttachCurrentThread/jni_AttachCurrentThreadAsDaemon.
    // We cannot use JavaCalls::construct_new_instance because the java.lang.Thread
    // constructor calls Thread.current(), which must be set here.
    java_lang_Thread::set_thread(thread_oop(), this);
!   java_lang_Thread::set_priority(thread_oop(), NormPriority);
-   set_threadObj(thread_oop());
  
    JavaValue result(T_VOID);
    if (thread_name != NULL) {
      Handle name = java_lang_String::create_from_str(thread_name, CHECK);
      // Thread gets assigned specified name and null target
--- 810,11 ---
  
    // We are called from jni_AttachCurrentThread/jni_AttachCurrentThreadAsDaemon.
    // We cannot use JavaCalls::construct_new_instance because the java.lang.Thread
    // constructor calls Thread.current(), which must be set here.
    java_lang_Thread::set_thread(thread_oop(), this);
!   set_threadOopHandles(thread_oop());
  
    JavaValue result(T_VOID);
    if (thread_name != NULL) {
      Handle name = java_lang_String::create_from_str(thread_name, CHECK);
      // Thread gets assigned specified name and null target

*** 815,30 ***
                              vmSymbols::threadgroup_runnable_void_signature(),
                              thread_group,
                              Handle(),
                              THREAD);
    }
! 
  
    if (daemon) {
      java_lang_Thread::set_daemon(thread_oop());
    }
- 
-   if (HAS_PENDING_EXCEPTION) {
-     return;
-   }
- 
-   Klass* group = vmClasses::ThreadGroup_klass();
-   Handle threadObj(THREAD, this->threadObj());
- 
-   JavaCalls::call_special(&result,
-                           thread_group,
-                           group,
-                           vmSymbols::add_method_name(),
-                           vmSymbols::thread_void_signature(),
-                           threadObj,          // Arg 1
-                           THREAD);
  }
  
  // ======= JavaThread ========
  
  #if INCLUDE_JVMCI
--- 836,15 ---
                              vmSymbols::threadgroup_runnable_void_signature(),
                              thread_group,
                              Handle(),
                              THREAD);
    }
!   os::set_priority(this, NormPriority);
  
    if (daemon) {
      java_lang_Thread::set_daemon(thread_oop());
    }
  }
  
  // ======= JavaThread ========
  
  #if INCLUDE_JVMCI

*** 987,10 ***
--- 993,11 ---
    _deopt_mark(nullptr),
    _deopt_nmethod(nullptr),
    _vframe_array_head(nullptr),
    _vframe_array_last(nullptr),
    _jvmti_deferred_updates(nullptr),
+   _keepalive_cleanup(new (ResourceObj::C_HEAP, mtInternal) GrowableArray<WeakHandle>(16, mtInternal)),
    _callee_target(nullptr),
    _vm_result(nullptr),
    _vm_result_2(nullptr),
  
    _current_pending_monitor(NULL),

*** 1015,10 ***
--- 1022,14 ---
  
    _terminated(_not_terminated),
    _in_deopt_handler(0),
    _doing_unsafe_access(false),
    _do_not_unlock_if_synchronized(false),
+ #if INCLUDE_JVMTI
+   _is_in_VTMT(false),
+   _is_VTMT_disabler(false),
+ #endif
    _jni_attach_state(_not_attaching_via_jni),
  #if INCLUDE_JVMCI
    _pending_deoptimization(-1),
    _pending_monitorenter(false),
    _pending_transfer_to_interpreter(false),

*** 1042,10 ***
--- 1053,18 ---
  
    // JVMTI PopFrame support
    _popframe_condition(popframe_inactive),
    _frames_to_pop_failed_realloc(0),
  
+   _cont_entry(nullptr),
+   _cont_yield(false),
+   _cont_preempt(false),
+   _cont_fastpath_thread_state(1),
+   _cont_fastpath(0),
+   _held_monitor_count(0),
+   _mounted_vthread(oop()),
+ 
    _handshake(this),
  
    _popframe_preserved_args(nullptr),
    _popframe_preserved_args_size(0),
  

*** 1059,18 ***
    _class_to_be_initialized(nullptr),
  
    _SleepEvent(ParkEvent::Allocate(this))
  {
    set_jni_functions(jni_functions());
- 
  #if INCLUDE_JVMCI
    assert(_jvmci._implicit_exception_pc == nullptr, "must be");
    if (JVMCICounterSize > 0) {
      resize_counters(0, (int) JVMCICounterSize);
    }
  #endif // INCLUDE_JVMCI
- 
    // Setup safepoint state info for this thread
    ThreadSafepointState::create(this);
  
    SafepointMechanism::initialize_header(this);
  
--- 1078,16 ---

*** 1182,10 ***
--- 1199,11 ---
  
  JavaThread::~JavaThread() {
  
    // Ask ServiceThread to release the threadObj OopHandle
    ServiceThread::add_oop_handle_release(_threadObj);
+   ServiceThread::add_oop_handle_release(_vthread);
  
    // Return the sleep event to the free list
    ParkEvent::Release(_SleepEvent);
    _SleepEvent = NULL;
  

*** 1358,26 ***
                      name());
          CLEAR_PENDING_EXCEPTION;
        }
      }
  
!     // Call Thread.exit(). We try 3 times in case we got another Thread.stop during
-     // the execution of the method. If that is not enough, then we don't really care. Thread.stop
-     // is deprecated anyhow.
      if (!is_Compiler_thread()) {
!       int count = 3;
!       while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) {
!         EXCEPTION_MARK;
!         JavaValue result(T_VOID);
!         Klass* thread_klass = vmClasses::Thread_klass();
!         JavaCalls::call_virtual(&result,
!                                 threadObj, thread_klass,
!                                 vmSymbols::exit_method_name(),
!                                 vmSymbols::void_method_signature(),
-                                 THREAD);
-         CLEAR_PENDING_EXCEPTION;
-       }
      }
      // notify JVMTI
      if (JvmtiExport::should_post_thread_life()) {
        JvmtiExport::post_thread_end(this);
      }
--- 1376,21 ---
                      name());
          CLEAR_PENDING_EXCEPTION;
        }
      }
  
!     // Call Thread.exit()
      if (!is_Compiler_thread()) {
!       EXCEPTION_MARK;
!       JavaValue result(T_VOID);
!       Klass* thread_klass = vmClasses::Thread_klass();
!       JavaCalls::call_virtual(&result,
!                               threadObj, thread_klass,
!                               vmSymbols::exit_method_name(),
!                               vmSymbols::void_method_signature(),
!                               THREAD);
!       CLEAR_PENDING_EXCEPTION;
      }
      // notify JVMTI
      if (JvmtiExport::should_post_thread_life()) {
        JvmtiExport::post_thread_end(this);
      }

*** 1426,10 ***
--- 1439,12 ---
             "should not have a Java frame when detaching or exiting");
      ObjectSynchronizer::release_monitors_owned_by_thread(this);
      assert(!this->has_pending_exception(), "release_monitors should have cleared");
    }
  
+   assert(this->held_monitor_count() == 0, "held monitor count should be zero");
+ 
    // These things needs to be done while we are still a Java Thread. Make sure that thread
    // is in a consistent state, in case GC happens
    JFR_ONLY(Jfr::on_thread_exit(this);)
  
    if (active_handles() != NULL) {

*** 1608,10 ***
--- 1623,16 ---
      if (!has_pending_exception() || !pending_exception()->is_a(vmClasses::ThreadDeath_klass())) {
  
        // We cannot call Exceptions::_throw(...) here because we cannot block
        set_pending_exception(_pending_async_exception, __FILE__, __LINE__);
  
+       // Clear any scope-local bindings on ThreadDeath
+       set_scopeLocalCache(NULL);
+       oop threadOop = threadObj();
+       assert(threadOop != NULL, "must be");
+       java_lang_Thread::clear_scopeLocalBindings(threadOop);
+ 
        LogTarget(Info, exceptions) lt;
        if (lt.is_enabled()) {
          ResourceMark rm;
          LogStream ls(lt);
          ls.print("Async. exception installed at runtime exit (" INTPTR_FORMAT ")", p2i(this));

*** 1664,10 ***
--- 1685,15 ---
    if (check_asyncs) {
      check_and_handle_async_exceptions();
    }
  
    JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
+ 
+   if (is_cont_force_yield()) {
+     Continuation::jump_from_safepoint(this); // does not return
+     ShouldNotReachHere();
+   }
  }
  
  class InstallAsyncExceptionClosure : public HandshakeClosure {
    Handle _throwable; // The Throwable thrown at the target Thread
  public:

*** 1733,18 ***
--- 1759,43 ---
    // Interrupt thread so it will wake up from a potential wait()/sleep()/park()
    java_lang_Thread::set_interrupted(threadObj(), true);
    this->interrupt();
  }
  
+ #if INCLUDE_JVMTI
+ void JavaThread::set_is_in_VTMT(bool val) {
+   _is_in_VTMT = val;
+   if (val) {
+     assert(JvmtiVTMTDisabler::VTMT_disable_count() == 0, "must be 0");
+   }
+ }
+ 
+ void JavaThread::set_is_VTMT_disabler(bool val) {
+   _is_VTMT_disabler = val;
+   assert(JvmtiVTMTDisabler::VTMT_count() == 0, "must be 0");
+ }
+ #endif
  
  // External suspension mechanism.
  //
  // Guarantees on return (for a valid target thread):
  //   - Target thread will not execute any new bytecode.
  //   - Target thread will not enter any new monitors.
  //
  bool JavaThread::java_suspend() {
+ #if INCLUDE_JVMTI
+   // Suspending a JavaThread in VTMT or disabling VTMT can cause deadlocks.
+   assert(!is_in_VTMT(), "no suspend allowed in VTMT transition");
+ #ifdef ASSERT
+   if (is_VTMT_disabler()) { // TMP debugging code, should be removed after this assert is observed
+     printf("DBG: JavaThread::java_suspend: suspended jt: %p current jt: %p\n", (void*)this, (void*)JavaThread::current());
+     printf("DBG: JavaThread::java_suspend: VTMT_disable_count: %d\n", JvmtiVTMTDisabler::VTMT_disable_count());
+   }
+ #endif
+   assert(!is_VTMT_disabler(), "no suspend allowed for VTMT disablers");
+ #endif
+ 
    ThreadsListHandle tlh;
    if (!tlh.includes(this)) {
      log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " not on ThreadsList, no suspension", p2i(this));
      return false;
    }

*** 1758,10 ***
--- 1809,29 ---
      return false;
    }
    return this->handshake_state()->resume();
  }
  
+ bool JavaThread::block_suspend(JavaThread* caller) {
+   ThreadsListHandle tlh;
+   if (!tlh.includes(this)) {
+     log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " not on ThreadsList, no suspension", p2i(this));
+     return false;
+   }
+   return this->handshake_state()->block_suspend(caller);
+ }
+ 
+ bool JavaThread::continue_resume(JavaThread* caller) {
+   ThreadsListHandle tlh;
+   if (!tlh.includes(this)) {
+     log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " not on ThreadsList, nothing to resume", p2i(this));
+     return false;
+   }
+   return this->handshake_state()->continue_resume(caller);
+ }
+ 
+ 
  // Wait for another thread to perform object reallocation and relocking on behalf of
  // this thread.
  // Raw thread state transition to _thread_blocked and back again to the original
  // state before returning are performed. The current thread is required to
  // change to _thread_blocked in order to be seen to be safepoint/handshake safe

*** 1918,10 ***
--- 1988,28 ---
        Deoptimization::deoptimize(this, *fst.current());
      }
    }
  }
  
+ void JavaThread::deoptimize_marked_methods_only_anchors() {
+   if (!has_last_Java_frame()) return;
+   bool java_callee = false;
+   StackFrameStream fst(this, false /* update */, true /* process_frames */);
+   for (; !fst.is_done(); fst.next()) {
+     if (fst.current()->should_be_deoptimized()) {
+       if (!java_callee) {
+         //tty->print_cr("Patching RA");
+         Deoptimization::deoptimize(this, *fst.current());
+       } else {
+         //tty->print_cr("Not patching RA");
+       }
+     }
+     java_callee = fst.current()->is_compiled_frame();
+   }
+ }
+ 
+ 
  #ifdef ASSERT
  void JavaThread::verify_frame_info() {
    assert((!has_last_Java_frame() && java_call_counter() == 0) ||
           (has_last_Java_frame() && java_call_counter() > 0),
           "unexpected frame info: has_last_frame=%s, java_call_counter=%d",

*** 1965,10 ***
--- 2053,12 ---
  #endif
  
    if (jvmti_thread_state() != NULL) {
      jvmti_thread_state()->oops_do(f, cf);
    }
+ 
+   f->do_oop(&_mounted_vthread);
  }
  
  void JavaThread::oops_do_frames(OopClosure* f, CodeBlobClosure* cf) {
    if (!has_last_Java_frame()) {
      return;

*** 2038,24 ***
    case _thread_blocked_trans:     return "_thread_blocked_trans";
    default:                        return "unknown thread state";
    }
  }
  
- #ifndef PRODUCT
  void JavaThread::print_thread_state_on(outputStream *st) const {
    st->print_cr("   JavaThread state: %s", _get_thread_state_name(_thread_state));
  };
! #endif // PRODUCT
  
  // Called by Threads::print() for VM_PrintThreads operation
  void JavaThread::print_on(outputStream *st, bool print_extended_info) const {
    st->print_raw("\"");
    st->print_raw(name());
    st->print_raw("\" ");
    oop thread_oop = threadObj();
    if (thread_oop != NULL) {
!     st->print("#" INT64_FORMAT " ", (int64_t)java_lang_Thread::thread_id(thread_oop));
      if (java_lang_Thread::is_daemon(thread_oop))  st->print("daemon ");
      st->print("prio=%d ", java_lang_Thread::priority(thread_oop));
    }
    Thread::print_on(st, print_extended_info);
    // print guess for valid stack memory region (assume 4K pages); helps lock debugging
--- 2128,25 ---
    case _thread_blocked_trans:     return "_thread_blocked_trans";
    default:                        return "unknown thread state";
    }
  }
  
  void JavaThread::print_thread_state_on(outputStream *st) const {
    st->print_cr("   JavaThread state: %s", _get_thread_state_name(_thread_state));
  };
! const char* JavaThread::thread_state_name() const {
+   return _get_thread_state_name(_thread_state);
+ }
  
  // Called by Threads::print() for VM_PrintThreads operation
  void JavaThread::print_on(outputStream *st, bool print_extended_info) const {
    st->print_raw("\"");
    st->print_raw(name());
    st->print_raw("\" ");
    oop thread_oop = threadObj();
    if (thread_oop != NULL) {
!     st->print("#" INT64_FORMAT " [%ld] ", (int64_t)java_lang_Thread::thread_id(thread_oop), (long) osthread()->thread_id());
      if (java_lang_Thread::is_daemon(thread_oop))  st->print("daemon ");
      st->print("prio=%d ", java_lang_Thread::priority(thread_oop));
    }
    Thread::print_on(st, print_extended_info);
    // print guess for valid stack memory region (assume 4K pages); helps lock debugging

*** 2098,10 ***
--- 2189,11 ---
      st->print(", id=%d", osthread()->thread_id());
    }
    st->print(", stack(" PTR_FORMAT "," PTR_FORMAT ")",
              p2i(stack_end()), p2i(stack_base()));
    st->print("]");
+   DEBUG_ONLY(print_owned_locks_on(st);)
  
    ThreadsSMRSupport::print_info_on(this, st);
    return;
  }
  

*** 2202,11 ***
  
    Handle thread_oop(Thread::current(),
                      JNIHandles::resolve_non_null(jni_thread));
    assert(InstanceKlass::cast(thread_oop->klass())->is_linked(),
           "must be initialized");
!   set_threadObj(thread_oop());
    java_lang_Thread::set_thread(thread_oop(), this);
  
    if (prio == NoPriority) {
      prio = java_lang_Thread::priority(thread_oop());
      assert(prio != NoPriority, "A valid priority should be present");
--- 2294,11 ---
  
    Handle thread_oop(Thread::current(),
                      JNIHandles::resolve_non_null(jni_thread));
    assert(InstanceKlass::cast(thread_oop->klass())->is_linked(),
           "must be initialized");
!   set_threadOopHandles(thread_oop());
    java_lang_Thread::set_thread(thread_oop(), this);
  
    if (prio == NoPriority) {
      prio = java_lang_Thread::priority(thread_oop());
      assert(prio != NoPriority, "A valid priority should be present");

*** 2238,11 ***
  
    Thread* current_thread = Thread::current();
    ResourceMark rm(current_thread);
    HandleMark hm(current_thread);
  
!   RegisterMap reg_map(this);
    vframe* start_vf = last_java_vframe(&reg_map);
    int count = 0;
    for (vframe* f = start_vf; f != NULL; f = f->sender()) {
      if (f->is_java_frame()) {
        javaVFrame* jvf = javaVFrame::cast(f);
--- 2330,11 ---
  
    Thread* current_thread = Thread::current();
    ResourceMark rm(current_thread);
    HandleMark hm(current_thread);
  
!   RegisterMap reg_map(this, true, true);
    vframe* start_vf = last_java_vframe(&reg_map);
    int count = 0;
    for (vframe* f = start_vf; f != NULL; f = f->sender()) {
      if (f->is_java_frame()) {
        javaVFrame* jvf = javaVFrame::cast(f);

*** 2260,10 ***
--- 2352,24 ---
      count++;
      if (MaxJavaStackTraceDepth > 0 && MaxJavaStackTraceDepth == count) return;
    }
  }
  
+ #if INCLUDE_JVMTI
+ // Rebind JVMTI thread state from carrier to virtual or from virtual to carrier.
+ JvmtiThreadState* JavaThread::rebind_to_jvmti_thread_state_of(oop thread_oop) {
+   set_mounted_vthread(thread_oop);
+ 
+   // unbind current JvmtiThreadState from JavaThread
+   jvmti_thread_state()->unbind_from(this);
+ 
+   // bind new JvmtiThreadState to JavaThread
+   java_lang_Thread::jvmti_thread_state(thread_oop)->bind_to(this);
+ 
+   return jvmti_thread_state();
+ }
+ #endif
  
  // JVMTI PopFrame support
  void JavaThread::popframe_preserve_args(ByteSize size_in_bytes, void* start) {
    assert(_popframe_preserved_args == NULL, "should not wipe out old PopFrame preserved arguments");
    if (in_bytes(size_in_bytes) != 0) {

*** 2333,14 ***
  void JavaThread::print_frame_layout(int depth, bool validate_only) {
    ResourceMark rm;
    PreserveExceptionMark pm(this);
    FrameValues values;
    int frame_no = 0;
!   for (StackFrameStream fst(this, false /* update */, true /* process_frames */); !fst.is_done(); fst.next()) {
!     fst.current()->describe(values, ++frame_no);
      if (depth == frame_no) break;
    }
    if (validate_only) {
      values.validate();
    } else {
      tty->print_cr("[Describe stack layout]");
      values.print(this);
--- 2439,16 ---
  void JavaThread::print_frame_layout(int depth, bool validate_only) {
    ResourceMark rm;
    PreserveExceptionMark pm(this);
    FrameValues values;
    int frame_no = 0;
!   for (StackFrameStream fst(this, true, true, true); !fst.is_done(); fst.next()) {
!     if (frame_no == 0) fst.current()->describe_top(values);
+     fst.current()->describe(values, ++frame_no, fst.register_map());
      if (depth == frame_no) break;
    }
+   Continuation::describe(values);
    if (validate_only) {
      values.validate();
    } else {
      tty->print_cr("[Describe stack layout]");
      values.print(this);

*** 2368,29 ***
  void JavaThread::trace_stack() {
    if (!has_last_Java_frame()) return;
    Thread* current_thread = Thread::current();
    ResourceMark rm(current_thread);
    HandleMark hm(current_thread);
!   RegisterMap reg_map(this);
    trace_stack_from(last_java_vframe(&reg_map));
  }
  
  
  #endif // PRODUCT
  
  
! javaVFrame* JavaThread::last_java_vframe(RegisterMap *reg_map) {
    assert(reg_map != NULL, "a map must be given");
-   frame f = last_frame();
    for (vframe* vf = vframe::new_vframe(&f, reg_map, this); vf; vf = vf->sender()) {
      if (vf->is_java_frame()) return javaVFrame::cast(vf);
    }
    return NULL;
  }
  
- 
  Klass* JavaThread::security_get_caller_class(int depth) {
    vframeStream vfst(this);
    vfst.security_get_caller_frame(depth);
    if (!vfst.at_end()) {
      return vfst.method()->method_holder();
    }
--- 2476,38 ---
  void JavaThread::trace_stack() {
    if (!has_last_Java_frame()) return;
    Thread* current_thread = Thread::current();
    ResourceMark rm(current_thread);
    HandleMark hm(current_thread);
!   RegisterMap reg_map(this, true, true);
    trace_stack_from(last_java_vframe(&reg_map));
  }
  
  
  #endif // PRODUCT
  
  
! frame JavaThread::vthread_carrier_last_frame(RegisterMap* reg_map) {
+   ContinuationEntry* cont = last_continuation(java_lang_VirtualThread::vthread_scope());
+   guarantee (cont != NULL, "Not a carrier thread");
+   frame f = cont->to_frame();
+   cont->update_register_map(reg_map);
+   return f.sender(reg_map);
+ }
+ 
+ javaVFrame* JavaThread::last_java_vframe(const frame f, RegisterMap *reg_map) {
    assert(reg_map != NULL, "a map must be given");
    for (vframe* vf = vframe::new_vframe(&f, reg_map, this); vf; vf = vf->sender()) {
      if (vf->is_java_frame()) return javaVFrame::cast(vf);
    }
    return NULL;
  }
  
  Klass* JavaThread::security_get_caller_class(int depth) {
+   ResetNoHandleMark rnhm;
+   HandleMark hm(Thread::current());
+ 
    vframeStream vfst(this);
    vfst.security_get_caller_frame(depth);
    if (!vfst.at_end()) {
      return vfst.method()->method_holder();
    }

*** 3708,10 ***
--- 3825,16 ---
  
    ALL_JAVA_THREADS(p) {
      ResourceMark rm;
      p->print_on(st, print_extended_info);
      if (print_stacks) {
+       // if (p->has_last_Java_frame()) {
+       //   static char buf[O_BUFLEN];
+       //   frame fr = p->last_frame();
+       //   VMError::print_native_stack(tty, fr, p, buf, sizeof(buf));
+       // }
+ 
        if (internal_format) {
          p->trace_stack();
        } else {
          p->print_stack_on(st);
        }

*** 3826,11 ***
        }
      }
    }
  }
  
- 
  // Ad-hoc mutual exclusion primitives: SpinLock
  //
  // We employ SpinLocks _only for low-contention, fixed-length
  // short-duration critical sections where we're concerned
  // about native mutex_t or HotSpot Mutex:: latency.
--- 3949,10 ---

*** 3900,43 ***
     report_vm_error(__FILE__, __LINE__, "Cross modify fence failure", "%p", thread);
  }
  #endif
  
  // Helper function to create the java.lang.Thread object for a
! // VM-internal thread. The thread will have the given name, be
! // part of the System ThreadGroup and if is_visible is true will be
- // discoverable via the system ThreadGroup.
  Handle JavaThread::create_system_thread_object(const char* name,
                                                 bool is_visible, TRAPS) {
    Handle string = java_lang_String::create_from_str(name, CHECK_NH);
  
    // Initialize thread_oop to put it into the system threadGroup.
!   // This is done by calling the Thread(ThreadGroup tg, String name)
-   // constructor, which adds the new thread to the group as an unstarted
-   // thread.
    Handle thread_group(THREAD, Universe::system_thread_group());
    Handle thread_oop =
      JavaCalls::construct_new_instance(vmClasses::Thread_klass(),
                                        vmSymbols::threadgroup_string_void_signature(),
                                        thread_group,
                                        string,
                                        CHECK_NH);
  
-   // If the Thread is intended to be visible then we have to mimic what
-   // Thread.start() would do, by adding it to its ThreadGroup: tg.add(t).
-   if (is_visible) {
-     Klass* group = vmClasses::ThreadGroup_klass();
-     JavaValue result(T_VOID);
-     JavaCalls::call_special(&result,
-                             thread_group,
-                             group,
-                             vmSymbols::add_method_name(),
-                             vmSymbols::thread_void_signature(),
-                             thread_oop,
-                             CHECK_NH);
-   }
- 
    return thread_oop;
  }
  
  // Starts the target JavaThread as a daemon of the given priority, and
  // bound to the given java.lang.Thread instance.
--- 4022,26 ---
     report_vm_error(__FILE__, __LINE__, "Cross modify fence failure", "%p", thread);
  }
  #endif
  
  // Helper function to create the java.lang.Thread object for a
! // VM-internal thread. The thread will have the given name, and be
! // a member of the "system" ThreadGroup.
  Handle JavaThread::create_system_thread_object(const char* name,
                                                 bool is_visible, TRAPS) {
    Handle string = java_lang_String::create_from_str(name, CHECK_NH);
  
    // Initialize thread_oop to put it into the system threadGroup.
!   // This is done by calling the Thread(ThreadGroup group, String name) constructor.
    Handle thread_group(THREAD, Universe::system_thread_group());
    Handle thread_oop =
      JavaCalls::construct_new_instance(vmClasses::Thread_klass(),
                                        vmSymbols::threadgroup_string_void_signature(),
                                        thread_group,
                                        string,
                                        CHECK_NH);
  
    return thread_oop;
  }
  
  // Starts the target JavaThread as a daemon of the given priority, and
  // bound to the given java.lang.Thread instance.

*** 3959,11 ***
    }
  
    java_lang_Thread::set_daemon(thread_oop());
  
    // Now bind the thread_oop to the target JavaThread.
!   target->set_threadObj(thread_oop());
  
    Threads::add(target); // target is now visible for safepoint/handshake
    Thread::start(target);
  }
  
--- 4064,11 ---
    }
  
    java_lang_Thread::set_daemon(thread_oop());
  
    // Now bind the thread_oop to the target JavaThread.
!   target->set_threadOopHandles(thread_oop());
  
    Threads::add(target); // target is now visible for safepoint/handshake
    Thread::start(target);
  }
  
< prev index next >