< prev index next >

src/hotspot/share/prims/jvmtiImpl.cpp

Print this page

  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/symbolTable.hpp"
  28 #include "code/nmethod.hpp"
  29 #include "interpreter/interpreter.hpp"
  30 #include "interpreter/oopMapCache.hpp"
  31 #include "jvmtifiles/jvmtiEnv.hpp"
  32 #include "logging/log.hpp"
  33 #include "logging/logStream.hpp"
  34 #include "memory/allocation.inline.hpp"
  35 #include "memory/resourceArea.hpp"
  36 #include "oops/instanceKlass.hpp"
  37 #include "oops/klass.inline.hpp"
  38 #include "oops/oop.inline.hpp"
  39 #include "oops/oopHandle.inline.hpp"
  40 #include "prims/jvmtiAgentThread.hpp"
  41 #include "prims/jvmtiEventController.inline.hpp"
  42 #include "prims/jvmtiImpl.hpp"
  43 #include "prims/jvmtiRedefineClasses.hpp"

  44 #include "runtime/deoptimization.hpp"
  45 #include "runtime/frame.inline.hpp"
  46 #include "runtime/handles.inline.hpp"
  47 #include "runtime/interfaceSupport.inline.hpp"
  48 #include "runtime/javaCalls.hpp"
  49 #include "runtime/jniHandles.hpp"
  50 #include "runtime/os.hpp"
  51 #include "runtime/serviceThread.hpp"
  52 #include "runtime/signature.hpp"
  53 #include "runtime/thread.inline.hpp"
  54 #include "runtime/threadSMR.hpp"
  55 #include "runtime/vframe.hpp"
  56 #include "runtime/vframe_hp.hpp"
  57 #include "runtime/vmOperations.hpp"
  58 #include "utilities/exceptions.hpp"
  59 
  60 //
  61 // class JvmtiAgentThread
  62 //
  63 // JavaThread used to wrap a thread started by an agent

 407 
 408 JvmtiBreakpoints& JvmtiCurrentBreakpoints::get_jvmti_breakpoints() {
 409   if (_jvmti_breakpoints != NULL) return (*_jvmti_breakpoints);
 410   _jvmti_breakpoints = new JvmtiBreakpoints(listener_fun);
 411   assert(_jvmti_breakpoints != NULL, "_jvmti_breakpoints != NULL");
 412   return (*_jvmti_breakpoints);
 413 }
 414 
 415 void  JvmtiCurrentBreakpoints::listener_fun(void *this_obj, address *cache) {
 416   JvmtiBreakpoints *this_jvmti = (JvmtiBreakpoints *) this_obj;
 417   assert(this_jvmti != NULL, "this_jvmti != NULL");
 418 
 419   debug_only(int n = this_jvmti->length(););
 420   assert(cache[n] == NULL, "cache must be NULL terminated");
 421 
 422   set_breakpoint_list(cache);
 423 }
 424 
 425 ///////////////////////////////////////////////////////////////
 426 //
 427 // class VM_GetOrSetLocal
 428 //
 429 

 430 // Constructor for non-object getter
 431 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type)
 432   : _thread(thread)
 433   , _calling_thread(NULL)
 434   , _depth(depth)
 435   , _index(index)
 436   , _type(type)
 437   , _jvf(NULL)
 438   , _set(false)
 439   , _eb(false, NULL, NULL)
 440   , _result(JVMTI_ERROR_NONE)
 441 {
 442 }
 443 
 444 // Constructor for object or non-object setter
 445 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value)
 446   : _thread(thread)
 447   , _calling_thread(NULL)
 448   , _depth(depth)
 449   , _index(index)
 450   , _type(type)
 451   , _value(value)
 452   , _jvf(NULL)
 453   , _set(true)
 454   , _eb(type == T_OBJECT, JavaThread::current(), thread)
 455   , _result(JVMTI_ERROR_NONE)
 456 {
 457 }
 458 
 459 // Constructor for object getter
 460 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth, int index)
 461   : _thread(thread)
 462   , _calling_thread(calling_thread)
 463   , _depth(depth)
 464   , _index(index)
 465   , _type(T_OBJECT)
 466   , _jvf(NULL)
 467   , _set(false)
 468   , _eb(true, calling_thread, thread)
 469   , _result(JVMTI_ERROR_NONE)
 470 {
 471 }
 472 
 473 vframe *VM_GetOrSetLocal::get_vframe() {
 474   if (!_thread->has_last_Java_frame()) {
 475     return NULL;
 476   }
 477   RegisterMap reg_map(_thread);
 478   vframe *vf = _thread->last_java_vframe(&reg_map);
 479   int d = 0;
 480   while ((vf != NULL) && (d < _depth)) {
 481     vf = vf->java_sender();
 482     d++;
 483   }
 484   return vf;
 485 }
 486 
 487 javaVFrame *VM_GetOrSetLocal::get_java_vframe() {
 488   vframe* vf = get_vframe();
 489   if (vf == NULL) {
 490     _result = JVMTI_ERROR_NO_MORE_FRAMES;
 491     return NULL;
 492   }
 493   javaVFrame *jvf = (javaVFrame*)vf;
 494 
 495   if (!vf->is_java_frame()) {
 496     _result = JVMTI_ERROR_OPAQUE_FRAME;
 497     return NULL;
 498   }
 499   return jvf;
 500 }
 501 
 502 // Check that the klass is assignable to a type with the given signature.
 503 // Another solution could be to use the function Klass::is_subtype_of(type).
 504 // But the type class can be forced to load/initialize eagerly in such a case.
 505 // This may cause unexpected consequences like CFLH or class-init JVMTI events.
 506 // It is better to avoid such a behavior.
 507 bool VM_GetOrSetLocal::is_assignable(const char* ty_sign, Klass* klass, Thread* thread) {
 508   assert(ty_sign != NULL, "type signature must not be NULL");
 509   assert(thread != NULL, "thread must not be NULL");
 510   assert(klass != NULL, "klass must not be NULL");
 511 
 512   int len = (int) strlen(ty_sign);
 513   if (ty_sign[0] == JVM_SIGNATURE_CLASS &&
 514       ty_sign[len-1] == JVM_SIGNATURE_ENDCLASS) { // Need pure class/interface name
 515     ty_sign++;
 516     len -= 2;
 517   }
 518   TempNewSymbol ty_sym = SymbolTable::new_symbol(ty_sign, len);
 519   if (klass->name() == ty_sym) {
 520     return true;
 521   }
 522   // Compare primary supers
 523   int super_depth = klass->super_depth();
 524   int idx;
 525   for (idx = 0; idx < super_depth; idx++) {
 526     if (klass->primary_super_of_depth(idx)->name() == ty_sym) {
 527       return true;
 528     }
 529   }
 530   // Compare secondary supers
 531   const Array<Klass*>* sec_supers = klass->secondary_supers();
 532   for (idx = 0; idx < sec_supers->length(); idx++) {
 533     if (((Klass*) sec_supers->at(idx))->name() == ty_sym) {
 534       return true;
 535     }
 536   }
 537   return false;
 538 }
 539 
 540 // Checks error conditions:
 541 //   JVMTI_ERROR_INVALID_SLOT
 542 //   JVMTI_ERROR_TYPE_MISMATCH
 543 // Returns: 'true' - everything is Ok, 'false' - error code
 544 
 545 bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
 546   Method* method = jvf->method();










 547   jint num_entries = method->localvariable_table_length();
 548   if (num_entries == 0) {
 549     _result = JVMTI_ERROR_INVALID_SLOT;
 550     return false;       // There are no slots
 551   }
 552   int signature_idx = -1;
 553   int vf_bci = jvf->bci();
 554   LocalVariableTableElement* table = method->localvariable_table_start();
 555   for (int i = 0; i < num_entries; i++) {
 556     int start_bci = table[i].start_bci;
 557     int end_bci = start_bci + table[i].length;
 558 
 559     // Here we assume that locations of LVT entries
 560     // with the same slot number cannot be overlapped
 561     if (_index == (jint) table[i].slot && start_bci <= vf_bci && vf_bci <= end_bci) {
 562       signature_idx = (int) table[i].descriptor_cp_index;
 563       break;
 564     }
 565   }
 566   if (signature_idx == -1) {

 588     return false;
 589   }
 590 
 591   jobject jobj = _value.l;
 592   if (_set && slot_type == T_OBJECT && jobj != NULL) { // NULL reference is allowed
 593     // Check that the jobject class matches the return type signature.
 594     oop obj = JNIHandles::resolve_external_guard(jobj);
 595     NULL_CHECK(obj, (_result = JVMTI_ERROR_INVALID_OBJECT, false));
 596     Klass* ob_k = obj->klass();
 597     NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false));
 598 
 599     const char* signature = (const char *) sign_sym->as_utf8();
 600     if (!is_assignable(signature, ob_k, VMThread::vm_thread())) {
 601       _result = JVMTI_ERROR_TYPE_MISMATCH;
 602       return false;
 603     }
 604   }
 605   return true;
 606 }
 607 
 608 bool VM_GetOrSetLocal::check_slot_type_no_lvt(javaVFrame* jvf) {
 609   Method* method = jvf->method();
 610   jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
 611 
 612   if (_index < 0 || _index + extra_slot >= method->max_locals()) {
 613     _result = JVMTI_ERROR_INVALID_SLOT;
 614     return false;
 615   }
 616   StackValueCollection *locals = _jvf->locals();
 617   BasicType slot_type = locals->at(_index)->type();
 618 
 619   if (slot_type == T_CONFLICT) {
 620     _result = JVMTI_ERROR_INVALID_SLOT;
 621     return false;
 622   }
 623   if (extra_slot) {
 624     BasicType extra_slot_type = locals->at(_index + 1)->type();
 625     if (extra_slot_type != T_INT) {
 626       _result = JVMTI_ERROR_INVALID_SLOT;
 627       return false;
 628     }

 631     _result = JVMTI_ERROR_TYPE_MISMATCH;
 632     return false;
 633   }
 634   return true;
 635 }
 636 
 637 static bool can_be_deoptimized(vframe* vf) {
 638   return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
 639 }
 640 
 641 bool VM_GetOrSetLocal::doit_prologue() {
 642   if (!_eb.deoptimize_objects(_depth, _depth)) {
 643     // The target frame is affected by a reallocation failure.
 644     _result = JVMTI_ERROR_OUT_OF_MEMORY;
 645     return false;
 646   }
 647 
 648   return true;
 649 }
 650 
 651 void VM_GetOrSetLocal::doit() {
 652   _jvf = _jvf == NULL ? get_java_vframe() : _jvf;
 653   if (_jvf == NULL) {
 654     return;
 655   };
 656 





 657   Method* method = _jvf->method();
 658   if (getting_receiver()) {
 659     if (method->is_static()) {
 660       _result = JVMTI_ERROR_INVALID_SLOT;
 661       return;
 662     }
 663   } else {
 664     if (method->is_native()) {
 665       _result = JVMTI_ERROR_OPAQUE_FRAME;
 666       return;
 667     }
 668 
 669     if (!check_slot_type_no_lvt(_jvf)) {
 670       return;
 671     }
 672     if (method->has_localvariable_table() &&
 673         !check_slot_type_lvt(_jvf)) {
 674       return;
 675     }
 676   }

 738       StackValueCollection *locals = _jvf->locals();
 739 
 740       switch (_type) {
 741         case T_INT:    _value.i = locals->int_at   (_index);   break;
 742         case T_LONG:   _value.j = locals->long_at  (_index);   break;
 743         case T_FLOAT:  _value.f = locals->float_at (_index);   break;
 744         case T_DOUBLE: _value.d = locals->double_at(_index);   break;
 745         case T_OBJECT: {
 746           // Wrap the oop to be returned in a local JNI handle since
 747           // oops_do() no longer applies after doit() is finished.
 748           oop obj = locals->obj_at(_index)();
 749           _value.l = JNIHandles::make_local(_calling_thread, obj);
 750           break;
 751         }
 752         default: ShouldNotReachHere();
 753       }
 754     }
 755   }
 756 }
 757 
 758 
 759 bool VM_GetOrSetLocal::allow_nested_vm_operations() const {
 760   return true; // May need to deoptimize
 761 }
 762 
 763 


























































 764 VM_GetReceiver::VM_GetReceiver(
 765     JavaThread* thread, JavaThread* caller_thread, jint depth)
 766     : VM_GetOrSetLocal(thread, caller_thread, depth, 0) {}
 767 
 768 /////////////////////////////////////////////////////////////////////////////////////////
 769 















































































 770 //
 771 // class JvmtiSuspendControl - see comments in jvmtiImpl.hpp
 772 //
 773 
 774 bool JvmtiSuspendControl::suspend(JavaThread *java_thread) {
 775   return java_thread->java_suspend();
 776 }
 777 
 778 bool JvmtiSuspendControl::resume(JavaThread *java_thread) {
 779   return java_thread->java_resume();
 780 }
 781 
 782 void JvmtiSuspendControl::print() {
 783 #ifndef PRODUCT
 784   ResourceMark rm;
 785   LogStreamHandle(Trace, jvmti) log_stream;
 786   log_stream.print("Suspended Threads: [");
 787   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
 788 #ifdef JVMTI_TRACE
 789     const char *name   = JvmtiTrace::safe_get_thread_name(thread);

  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/symbolTable.hpp"
  28 #include "code/nmethod.hpp"
  29 #include "interpreter/interpreter.hpp"
  30 #include "interpreter/oopMapCache.hpp"
  31 #include "jvmtifiles/jvmtiEnv.hpp"
  32 #include "logging/log.hpp"
  33 #include "logging/logStream.hpp"
  34 #include "memory/allocation.inline.hpp"
  35 #include "memory/resourceArea.hpp"
  36 #include "oops/instanceKlass.hpp"
  37 #include "oops/klass.inline.hpp"
  38 #include "oops/oop.inline.hpp"
  39 #include "oops/oopHandle.inline.hpp"
  40 #include "prims/jvmtiAgentThread.hpp"
  41 #include "prims/jvmtiEventController.inline.hpp"
  42 #include "prims/jvmtiImpl.hpp"
  43 #include "prims/jvmtiRedefineClasses.hpp"
  44 #include "runtime/continuation.hpp"
  45 #include "runtime/deoptimization.hpp"
  46 #include "runtime/frame.inline.hpp"
  47 #include "runtime/handles.inline.hpp"
  48 #include "runtime/interfaceSupport.inline.hpp"
  49 #include "runtime/javaCalls.hpp"
  50 #include "runtime/jniHandles.hpp"
  51 #include "runtime/os.hpp"
  52 #include "runtime/serviceThread.hpp"
  53 #include "runtime/signature.hpp"
  54 #include "runtime/thread.inline.hpp"
  55 #include "runtime/threadSMR.hpp"
  56 #include "runtime/vframe.hpp"
  57 #include "runtime/vframe_hp.hpp"
  58 #include "runtime/vmOperations.hpp"
  59 #include "utilities/exceptions.hpp"
  60 
  61 //
  62 // class JvmtiAgentThread
  63 //
  64 // JavaThread used to wrap a thread started by an agent

 408 
 409 JvmtiBreakpoints& JvmtiCurrentBreakpoints::get_jvmti_breakpoints() {
 410   if (_jvmti_breakpoints != NULL) return (*_jvmti_breakpoints);
 411   _jvmti_breakpoints = new JvmtiBreakpoints(listener_fun);
 412   assert(_jvmti_breakpoints != NULL, "_jvmti_breakpoints != NULL");
 413   return (*_jvmti_breakpoints);
 414 }
 415 
 416 void  JvmtiCurrentBreakpoints::listener_fun(void *this_obj, address *cache) {
 417   JvmtiBreakpoints *this_jvmti = (JvmtiBreakpoints *) this_obj;
 418   assert(this_jvmti != NULL, "this_jvmti != NULL");
 419 
 420   debug_only(int n = this_jvmti->length(););
 421   assert(cache[n] == NULL, "cache must be NULL terminated");
 422 
 423   set_breakpoint_list(cache);
 424 }
 425 
 426 ///////////////////////////////////////////////////////////////
 427 //
 428 // class VM_BaseGetOrSetLocal
 429 //
 430 
 431 const jvalue VM_BaseGetOrSetLocal::_DEFAULT_VALUE = {0L};
 432 // Constructor for non-object getter












 433 
 434 VM_BaseGetOrSetLocal::VM_BaseGetOrSetLocal(JavaThread* calling_thread, jint depth,
 435                                            jint index, BasicType type, jvalue value, bool set)
 436   : _calling_thread(calling_thread)

 437   , _depth(depth)
 438   , _index(index)
 439   , _type(type)
 440   , _value(value)
 441   , _jvf(NULL)
 442   , _set(set)

 443   , _result(JVMTI_ERROR_NONE)
 444 {
 445 }
 446 











































 447 // Check that the klass is assignable to a type with the given signature.
 448 // Another solution could be to use the function Klass::is_subtype_of(type).
 449 // But the type class can be forced to load/initialize eagerly in such a case.
 450 // This may cause unexpected consequences like CFLH or class-init JVMTI events.
 451 // It is better to avoid such a behavior.
 452 bool VM_BaseGetOrSetLocal::is_assignable(const char* ty_sign, Klass* klass, Thread* thread) {
 453   assert(ty_sign != NULL, "type signature must not be NULL");
 454   assert(thread != NULL, "thread must not be NULL");
 455   assert(klass != NULL, "klass must not be NULL");
 456 
 457   int len = (int) strlen(ty_sign);
 458   if (ty_sign[0] == JVM_SIGNATURE_CLASS &&
 459       ty_sign[len-1] == JVM_SIGNATURE_ENDCLASS) { // Need pure class/interface name
 460     ty_sign++;
 461     len -= 2;
 462   }
 463   TempNewSymbol ty_sym = SymbolTable::new_symbol(ty_sign, len);
 464   if (klass->name() == ty_sym) {
 465     return true;
 466   }
 467   // Compare primary supers
 468   int super_depth = klass->super_depth();
 469   int idx;
 470   for (idx = 0; idx < super_depth; idx++) {
 471     if (klass->primary_super_of_depth(idx)->name() == ty_sym) {
 472       return true;
 473     }
 474   }
 475   // Compare secondary supers
 476   const Array<Klass*>* sec_supers = klass->secondary_supers();
 477   for (idx = 0; idx < sec_supers->length(); idx++) {
 478     if (((Klass*) sec_supers->at(idx))->name() == ty_sym) {
 479       return true;
 480     }
 481   }
 482   return false;
 483 }
 484 
 485 // Checks error conditions:
 486 //   JVMTI_ERROR_INVALID_SLOT
 487 //   JVMTI_ERROR_TYPE_MISMATCH
 488 // Returns: 'true' - everything is Ok, 'false' - error code
 489 
 490 bool VM_BaseGetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
 491   Method* method = jvf->method();
 492   if (!method->has_localvariable_table()) {
 493     // Just to check index boundaries
 494     jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
 495     if (_index < 0 || _index + extra_slot >= method->max_locals()) {
 496       _result = JVMTI_ERROR_INVALID_SLOT;
 497       return false;
 498     }
 499     return true;
 500   }
 501 
 502   jint num_entries = method->localvariable_table_length();
 503   if (num_entries == 0) {
 504     _result = JVMTI_ERROR_INVALID_SLOT;
 505     return false;       // There are no slots
 506   }
 507   int signature_idx = -1;
 508   int vf_bci = jvf->bci();
 509   LocalVariableTableElement* table = method->localvariable_table_start();
 510   for (int i = 0; i < num_entries; i++) {
 511     int start_bci = table[i].start_bci;
 512     int end_bci = start_bci + table[i].length;
 513 
 514     // Here we assume that locations of LVT entries
 515     // with the same slot number cannot be overlapped
 516     if (_index == (jint) table[i].slot && start_bci <= vf_bci && vf_bci <= end_bci) {
 517       signature_idx = (int) table[i].descriptor_cp_index;
 518       break;
 519     }
 520   }
 521   if (signature_idx == -1) {

 543     return false;
 544   }
 545 
 546   jobject jobj = _value.l;
 547   if (_set && slot_type == T_OBJECT && jobj != NULL) { // NULL reference is allowed
 548     // Check that the jobject class matches the return type signature.
 549     oop obj = JNIHandles::resolve_external_guard(jobj);
 550     NULL_CHECK(obj, (_result = JVMTI_ERROR_INVALID_OBJECT, false));
 551     Klass* ob_k = obj->klass();
 552     NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false));
 553 
 554     const char* signature = (const char *) sign_sym->as_utf8();
 555     if (!is_assignable(signature, ob_k, VMThread::vm_thread())) {
 556       _result = JVMTI_ERROR_TYPE_MISMATCH;
 557       return false;
 558     }
 559   }
 560   return true;
 561 }
 562 
 563 bool VM_BaseGetOrSetLocal::check_slot_type_no_lvt(javaVFrame* jvf) {
 564   Method* method = jvf->method();
 565   jint extra_slot = (_type == T_LONG || _type == T_DOUBLE) ? 1 : 0;
 566 
 567   if (_index < 0 || _index + extra_slot >= method->max_locals()) {
 568     _result = JVMTI_ERROR_INVALID_SLOT;
 569     return false;
 570   }
 571   StackValueCollection *locals = _jvf->locals();
 572   BasicType slot_type = locals->at(_index)->type();
 573 
 574   if (slot_type == T_CONFLICT) {
 575     _result = JVMTI_ERROR_INVALID_SLOT;
 576     return false;
 577   }
 578   if (extra_slot) {
 579     BasicType extra_slot_type = locals->at(_index + 1)->type();
 580     if (extra_slot_type != T_INT) {
 581       _result = JVMTI_ERROR_INVALID_SLOT;
 582       return false;
 583     }

 586     _result = JVMTI_ERROR_TYPE_MISMATCH;
 587     return false;
 588   }
 589   return true;
 590 }
 591 
 592 static bool can_be_deoptimized(vframe* vf) {
 593   return (vf->is_compiled_frame() && vf->fr().can_be_deoptimized());
 594 }
 595 
 596 bool VM_GetOrSetLocal::doit_prologue() {
 597   if (!_eb.deoptimize_objects(_depth, _depth)) {
 598     // The target frame is affected by a reallocation failure.
 599     _result = JVMTI_ERROR_OUT_OF_MEMORY;
 600     return false;
 601   }
 602 
 603   return true;
 604 }
 605 
 606 void VM_BaseGetOrSetLocal::doit() {
 607   _jvf = get_java_vframe();
 608   if (_jvf == NULL) {
 609     return;
 610   };
 611 
 612   if (_set && Continuation::is_frame_in_continuation(_jvf->thread(), _jvf->fr())) {
 613     _result = JVMTI_ERROR_OPAQUE_FRAME; // deferred locals currently unsupported in continuations
 614     return;
 615   }
 616 
 617   Method* method = _jvf->method();
 618   if (getting_receiver()) {
 619     if (method->is_static()) {
 620       _result = JVMTI_ERROR_INVALID_SLOT;
 621       return;
 622     }
 623   } else {
 624     if (method->is_native()) {
 625       _result = JVMTI_ERROR_OPAQUE_FRAME;
 626       return;
 627     }
 628 
 629     if (!check_slot_type_no_lvt(_jvf)) {
 630       return;
 631     }
 632     if (method->has_localvariable_table() &&
 633         !check_slot_type_lvt(_jvf)) {
 634       return;
 635     }
 636   }

 698       StackValueCollection *locals = _jvf->locals();
 699 
 700       switch (_type) {
 701         case T_INT:    _value.i = locals->int_at   (_index);   break;
 702         case T_LONG:   _value.j = locals->long_at  (_index);   break;
 703         case T_FLOAT:  _value.f = locals->float_at (_index);   break;
 704         case T_DOUBLE: _value.d = locals->double_at(_index);   break;
 705         case T_OBJECT: {
 706           // Wrap the oop to be returned in a local JNI handle since
 707           // oops_do() no longer applies after doit() is finished.
 708           oop obj = locals->obj_at(_index)();
 709           _value.l = JNIHandles::make_local(_calling_thread, obj);
 710           break;
 711         }
 712         default: ShouldNotReachHere();
 713       }
 714     }
 715   }
 716 }
 717 
 718 bool VM_BaseGetOrSetLocal::allow_nested_vm_operations() const {

 719   return true; // May need to deoptimize
 720 }
 721 
 722 
 723 ///////////////////////////////////////////////////////////////
 724 //
 725 // class VM_GetOrSetLocal
 726 //
 727 
 728 // Constructor for non-object getter
 729 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type)
 730   : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, _DEFAULT_VALUE, false),
 731     _thread(thread),
 732     _eb(false, NULL, NULL)
 733 {
 734 }
 735 
 736 // Constructor for object or non-object setter
 737 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value)
 738   : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, value, true),
 739     _thread(thread),
 740     _eb(type == T_OBJECT, JavaThread::current(), thread)
 741 {
 742 }
 743 
 744 // Constructor for object getter
 745 VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, JavaThread* calling_thread, jint depth, int index)
 746   : VM_BaseGetOrSetLocal(calling_thread, depth, index, T_OBJECT, _DEFAULT_VALUE, false),
 747     _thread(thread),
 748     _eb(true, calling_thread, thread)
 749 {
 750 }
 751 
 752 vframe *VM_GetOrSetLocal::get_vframe() {
 753   if (!_thread->has_last_Java_frame()) {
 754     return NULL;
 755   }
 756   RegisterMap reg_map(_thread, true, true, true);
 757   vframe *vf = JvmtiEnvBase::get_last_java_vframe(_thread, &reg_map);
 758   int d = 0;
 759   while ((vf != NULL) && (d < _depth)) {
 760     vf = vf->java_sender();
 761     d++;
 762   }
 763   return vf;
 764 }
 765 
 766 javaVFrame *VM_GetOrSetLocal::get_java_vframe() {
 767   vframe* vf = get_vframe();
 768   if (vf == NULL) {
 769     _result = JVMTI_ERROR_NO_MORE_FRAMES;
 770     return NULL;
 771   }
 772   javaVFrame *jvf = (javaVFrame*)vf;
 773 
 774   if (!vf->is_java_frame()) {
 775     _result = JVMTI_ERROR_OPAQUE_FRAME;
 776     return NULL;
 777   }
 778   return jvf;
 779 }
 780 
 781 VM_GetReceiver::VM_GetReceiver(
 782     JavaThread* thread, JavaThread* caller_thread, jint depth)
 783     : VM_GetOrSetLocal(thread, caller_thread, depth, 0) {}
 784 

 785 
 786 ///////////////////////////////////////////////////////////////
 787 //
 788 // class VM_VirtualThreadGetOrSetLocal
 789 //
 790 
 791 // Constructor for non-object getter
 792 VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Handle vthread_h, jint depth,
 793                                                              jint index, BasicType type)
 794   : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, _DEFAULT_VALUE, false)
 795 {
 796   _env = env;
 797   _vthread_h = vthread_h;
 798 }
 799 
 800 // Constructor for object or non-object setter
 801 VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Handle vthread_h, jint depth,
 802                                                              jint index, BasicType type, jvalue value)
 803   : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, value, true)
 804 {
 805   _env = env;
 806   _vthread_h = vthread_h;
 807 }
 808 
 809 // Constructor for object getter
 810 VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Handle vthread_h, JavaThread* calling_thread,
 811                                                              jint depth, int index)
 812   : VM_BaseGetOrSetLocal(calling_thread, depth, index, T_OBJECT, _DEFAULT_VALUE, false)
 813 {
 814   _env = env;
 815   _vthread_h = vthread_h;
 816 }
 817 
 818 javaVFrame *VM_VirtualThreadGetOrSetLocal::get_java_vframe() {
 819   Thread* cur_thread = Thread::current();
 820   oop cont = java_lang_VirtualThread::continuation(_vthread_h());
 821   javaVFrame* jvf = NULL;
 822 
 823   assert(cont != NULL, "vthread contintuation must not be NULL");
 824   if (jdk_internal_vm_Continuation::is_mounted(cont)) {
 825     oop carrier_thread = java_lang_VirtualThread::carrier_thread(_vthread_h());
 826     JavaThread* java_thread = java_lang_Thread::thread(carrier_thread);
 827     vframeStream vfs(java_thread, Handle(cur_thread, Continuation::continuation_scope(cont)));
 828 
 829     if (!vfs.at_end()) {
 830       jvf = vfs.asJavaVFrame();
 831       jvf = JvmtiEnvBase::check_and_skip_hidden_frames(java_thread, jvf);
 832     }
 833   } else {
 834     vframeStream vfs(cont);
 835 
 836     if (!vfs.at_end()) {
 837       jvf = vfs.asJavaVFrame();
 838       jvf = JvmtiEnvBase::check_and_skip_hidden_frames(_vthread_h(), jvf);
 839     }
 840   }
 841   int d = 0;
 842   while ((jvf != NULL) && (d < _depth)) {
 843     jvf = jvf->java_sender();
 844     d++;
 845   }
 846 
 847   if (d < _depth || jvf == NULL) {
 848     _result = JVMTI_ERROR_NO_MORE_FRAMES;
 849     return NULL;
 850   }
 851 
 852   if (!jvf->is_java_frame()) {
 853     _result = JVMTI_ERROR_OPAQUE_FRAME;
 854     return NULL;
 855   }
 856   return jvf;
 857 }
 858 
 859 VM_VirtualThreadGetReceiver::VM_VirtualThreadGetReceiver(
 860     JvmtiEnv* env, Handle vthread_h, JavaThread* caller_thread, jint depth)
 861     : VM_VirtualThreadGetOrSetLocal(env, vthread_h, caller_thread, depth, 0) {}
 862 
 863 
 864 /////////////////////////////////////////////////////////////////////////////////////////
 865 //
 866 // class JvmtiSuspendControl - see comments in jvmtiImpl.hpp
 867 //
 868 
 869 bool JvmtiSuspendControl::suspend(JavaThread *java_thread) {
 870   return java_thread->java_suspend();
 871 }
 872 
 873 bool JvmtiSuspendControl::resume(JavaThread *java_thread) {
 874   return java_thread->java_resume();
 875 }
 876 
 877 void JvmtiSuspendControl::print() {
 878 #ifndef PRODUCT
 879   ResourceMark rm;
 880   LogStreamHandle(Trace, jvmti) log_stream;
 881   log_stream.print("Suspended Threads: [");
 882   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
 883 #ifdef JVMTI_TRACE
 884     const char *name   = JvmtiTrace::safe_get_thread_name(thread);
< prev index next >