// Double-check the size. (Condy can have any type.)
BasicType type = ldc.result_type(); switch (type2size[type]) { case2: guarantee(bytecode == Bytecodes::_ldc2_w, ""); break; case1: guarantee(bytecode != Bytecodes::_ldc2_w, ""); break; default: ShouldNotReachHere();
}
// Resolve the constant. This does not do unboxing. // But it does replace Universe::the_null_sentinel by null.
oop result = ldc.resolve_constant(CHECK);
assert(result != NULL || is_fast_aldc, "null result only valid for fast_aldc");
#ifdef ASSERT
{ // The bytecode wrappers aren't GC-safe so construct a new one
Bytecode_loadconstant ldc2(m, last_frame.bci()); int rindex = ldc2.cache_index(); if (rindex < 0)
rindex = m->constants()->cp_to_object_index(ldc2.pool_index()); if (rindex >= 0) {
oop coop = m->constants()->resolved_references()->obj_at(rindex);
oop roop = (result == NULL ? Universe::the_null_sentinel() : result);
assert(roop == coop, "expected result for assembly code");
}
} #endif
current->set_vm_result(result); if (!is_fast_aldc) { // Tell the interpreter how to unbox the primitive.
guarantee(java_lang_boxing_object::is_instance(result, type), ""); int offset = java_lang_boxing_object::value_offset(type);
intptr_t flags = ((as_TosState(type) << ConstantPoolCacheEntry::tos_state_shift)
| (offset & ConstantPoolCacheEntry::field_index_mask));
current->set_vm_result_2((Metadata*)flags);
}
}
JRT_END
JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* current, ConstantPool* pool, intindex))
Klass* k = pool->klass_at(index, CHECK);
InstanceKlass* klass = InstanceKlass::cast(k);
// Make sure we are not instantiating an abstract klass
klass->check_valid_for_instantiation(true, CHECK);
// Make sure klass is initialized
klass->initialize(CHECK);
// At this point the class may not be fully initialized // because of recursive initialization. If it is fully // initialized & has_finalized is not set, we rewrite // it into its fast version (Note: no locking is needed // here since this is an atomic byte write and can be // done more than once). // // Note: In case of classes with has_finalized we don't // rewrite since that saves us an extra check in // the fast version which then would call the // slow version anyway (and do a call back into // Java). // If we have a breakpoint, then we don't rewrite // because the _breakpoint bytecode would be lost.
oop obj = klass->allocate_instance(CHECK);
current->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::anewarray(JavaThread* current, ConstantPool* pool, int index, jint size))
Klass* klass = pool->klass_at(index, CHECK);
objArrayOop obj = oopFactory::new_objArray(klass, size, CHECK);
current->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* current, jint* first_size_address)) // We may want to pass in more arguments - could make this slightly faster
LastFrameAccessor last_frame(current);
ConstantPool* constants = last_frame.method()->constants(); int i = last_frame.get_index_u2(Bytecodes::_multianewarray);
Klass* klass = constants->klass_at(i, CHECK); int nof_dims = last_frame.number_of_dimensions();
assert(klass->is_klass(), "not a class");
assert(nof_dims >= 1, "multianewarray rank must be nonzero");
// We must create an array of jints to pass to multi_allocate.
ResourceMark rm(current); constint small_dims = 10;
jint dim_array[small_dims];
jint *dims = &dim_array[0]; if (nof_dims > small_dims) {
dims = (jint*) NEW_RESOURCE_ARRAY(jint, nof_dims);
} for (int index = 0; index < nof_dims; index++) { // offset from first_size_address is addressed as local[index] int n = Interpreter::local_offset_in_bytes(index)/jintSize;
dims[index] = first_size_address[n];
}
oop obj = ArrayKlass::cast(klass)->multi_allocate(nof_dims, dims, CHECK);
current->set_vm_result(obj);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::register_finalizer(JavaThread* current, oopDesc* obj))
assert(oopDesc::is_oop(obj), "must be a valid oop");
assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
JRT_END
// Quicken instance-of and check-cast bytecodes
JRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* current)) // Force resolving; quicken the bytecode
LastFrameAccessor last_frame(current); int which = last_frame.get_index_u2(Bytecodes::_checkcast);
ConstantPool* cpool = last_frame.method()->constants(); // We'd expect to assert that we're only here to quicken bytecodes, but in a multithreaded // program we might have seen an unquick'd bytecode in the interpreter but have another // thread quicken the bytecode before we get here. // assert( cpool->tag_at(which).is_unresolved_klass(), "should only come here to quicken bytecodes" );
Klass* klass = cpool->klass_at(which, CHECK);
current->set_vm_result_2(klass);
JRT_END
void InterpreterRuntime::note_trap_inner(JavaThread* current, int reason, const methodHandle& trap_method, int trap_bci) { if (trap_method.not_null()) {
MethodData* trap_mdo = trap_method->method_data(); if (trap_mdo == NULL) {
ExceptionMark em(current);
JavaThread* THREAD = current; // For exception macros.
Method::build_profiling_method_data(trap_method, THREAD); if (HAS_PENDING_EXCEPTION) { // Only metaspace OOM is expected. No Java code executed.
assert((PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())), "we expect only an OOM error here");
CLEAR_PENDING_EXCEPTION;
}
trap_mdo = trap_method->method_data(); // and fall through...
} if (trap_mdo != NULL) { // Update per-method count of trap events. The interpreter // is updating the MDO to simulate the effect of compiler traps.
Deoptimization::update_method_data_from_interpreter(trap_mdo, trap_bci, reason);
}
}
}
// Assume the compiler is (or will be) interested in this event. // If necessary, create an MDO to hold the information, and record it. void InterpreterRuntime::note_trap(JavaThread* current, int reason) {
assert(ProfileTraps, "call me only if profiling");
LastFrameAccessor last_frame(current);
methodHandle trap_method(current, last_frame.method()); int trap_bci = trap_method->bci_from(last_frame.bcp());
note_trap_inner(current, reason, trap_method, trap_bci);
}
static Handle get_preinitialized_exception(Klass* k, TRAPS) { // get klass
InstanceKlass* klass = InstanceKlass::cast(k);
assert(klass->is_initialized(), "this klass should have been initialized during VM initialization"); // create instance - do not call constructor since we may have no // (java) stack space left (should assert constructor is empty)
Handle exception;
oop exception_oop = klass->allocate_instance(CHECK_(exception));
exception = Handle(THREAD, exception_oop); if (StackTraceInThrowable) {
java_lang_Throwable::fill_in_stack_trace(exception);
} return exception;
}
// Special handling for stack overflow: since we don't have any (java) stack // space left we use the pre-allocated & pre-initialized StackOverflowError // klass to create an stack overflow error instance. We do not call its // constructor for the same reason (it is empty, anyway).
JRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* current))
Handle exception = get_preinitialized_exception(
vmClasses::StackOverflowError_klass(),
CHECK); // Increment counter for hs_err file reporting
Atomic::inc(&Exceptions::_stack_overflow_errors); // Remove the ScopedValue bindings in case we got a StackOverflowError // while we were trying to manipulate ScopedValue bindings.
current->clear_scopedValueBindings();
THROW_HANDLE(exception);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* current))
Handle exception = get_preinitialized_exception(
vmClasses::StackOverflowError_klass(),
CHECK);
java_lang_Throwable::set_message(exception(),
Universe::delayed_stack_overflow_error_message()); // Increment counter for hs_err file reporting
Atomic::inc(&Exceptions::_stack_overflow_errors); // Remove the ScopedValue bindings in case we got a StackOverflowError // while we were trying to manipulate ScopedValue bindings.
current->clear_scopedValueBindings();
THROW_HANDLE(exception);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* current, char* name, char* message)) // lookup exception klass
TempNewSymbol s = SymbolTable::new_symbol(name); if (ProfileTraps) { if (s == vmSymbols::java_lang_ArithmeticException()) {
note_trap(current, Deoptimization::Reason_div0_check);
} elseif (s == vmSymbols::java_lang_NullPointerException()) {
note_trap(current, Deoptimization::Reason_null_check);
}
} // create exception
Handle exception = Exceptions::new_exception(current, s, message);
current->set_vm_result(exception());
JRT_END
JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* current, char* name, oopDesc* obj)) // Produce the error message first because note_trap can safepoint
ResourceMark rm(current); constchar* klass_name = obj->klass()->external_name(); // lookup exception klass
TempNewSymbol s = SymbolTable::new_symbol(name); if (ProfileTraps) { if (s == vmSymbols::java_lang_ArrayStoreException()) {
note_trap(current, Deoptimization::Reason_array_check);
} else {
note_trap(current, Deoptimization::Reason_class_check);
}
} // create exception, with klass name as detail message
Handle exception = Exceptions::new_exception(current, s, klass_name);
current->set_vm_result(exception());
JRT_END
JRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThread* current, arrayOopDesc* a, jint index)) // Produce the error message first because note_trap can safepoint
ResourceMark rm(current);
stringStream ss;
ss.print("Index %d out of bounds for length %d", index, a->length());
if (ProfileTraps) {
note_trap(current, Deoptimization::Reason_range_check);
}
// Produce the error message first because note_trap can safepoint
ResourceMark rm(current); char* message = SharedRuntime::generate_class_cast_message(
current, obj->klass());
if (ProfileTraps) {
note_trap(current, Deoptimization::Reason_class_check);
}
// exception_handler_for_exception(...) returns the continuation address, // the exception oop (via TLS) and sets the bci/bcp for the continuation. // The exception oop is returned to make sure it is preserved over GC (it // is only on the stack if the exception was thrown explicitly via athrow). // During this operation, the expression stack contains the values for the // bci where the exception happened. If the exception was propagated back // from a call, the expression stack contains the values for the bci at the // invoke w/o arguments (i.e., as if one were inside the call).
JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* current, oopDesc* exception)) // We get here after we have unwound from a callee throwing an exception // into the interpreter. Any deferred stack processing is notified of // the event via the StackWatermarkSet.
StackWatermarkSet::after_unwind(current);
LastFrameAccessor last_frame(current);
Handle h_exception(current, exception);
methodHandle h_method (current, last_frame.method());
constantPoolHandle h_constants(current, h_method->constants()); bool should_repeat; int handler_bci; int current_bci = last_frame.bci();
if (current->frames_to_pop_failed_realloc() > 0) { // Allocation of scalar replaced object used in this frame // failed. Unconditionally pop the frame.
current->dec_frames_to_pop_failed_realloc();
current->set_vm_result(h_exception()); // If the method is synchronized we already unlocked the monitor // during deoptimization so the interpreter needs to skip it when // the frame is popped.
current->set_do_not_unlock_if_synchronized(true); return Interpreter::remove_activation_entry();
}
// Need to do this check first since when _do_not_unlock_if_synchronized // is set, we don't want to trigger any classloading which may make calls // into java, or surprisingly find a matching exception handler for bci 0 // since at this moment the method hasn't been "officially" entered yet. if (current->do_not_unlock_if_synchronized()) {
ResourceMark rm;
assert(current_bci == 0, "bci isn't zero for do_not_unlock_if_synchronized");
current->set_vm_result(exception); return Interpreter::remove_activation_entry();
}
do {
should_repeat = false;
// assertions
assert(h_exception.not_null(), "NULL exceptions should be handled by athrow"); // Check that exception is a subclass of Throwable.
assert(h_exception->is_a(vmClasses::Throwable_klass()), "Exception not subclass of Throwable");
// tracing if (log_is_enabled(Info, exceptions)) {
ResourceMark rm(current);
stringStream tempst;
tempst.print("interpreter method <%s>\n" " at bci %d for thread " INTPTR_FORMAT " (%s)",
h_method->print_value_string(), current_bci, p2i(current), current->name());
Exceptions::log_exception(h_exception, tempst.as_string());
} // Don't go paging in something which won't be used. // else if (extable->length() == 0) { // // disabled for now - interpreter is not using shortcut yet // // (shortcut is not to call runtime if we have no exception handlers) // // warning("performance bug: should not call runtime if method has no exception handlers"); // } // for AbortVMOnException flag
Exceptions::debug_check_abort(h_exception);
// exception handler lookup
Klass* klass = h_exception->klass();
handler_bci = Method::fast_exception_handler_bci_for(h_method, klass, current_bci, THREAD); if (HAS_PENDING_EXCEPTION) { // We threw an exception while trying to find the exception handler. // Transfer the new exception to the exception handle which will // be set into thread local storage, and do another lookup for an // exception handler for this exception, this time starting at the // BCI of the exception handler which caused the exception to be // thrown (bug 4307310).
h_exception = Handle(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION; if (handler_bci >= 0) {
current_bci = handler_bci;
should_repeat = true;
}
}
} while (should_repeat == true);
// notify JVMTI of an exception throw; JVMTI will detect if this is a first // time throw or a stack unwinding throw and accordingly notify the debugger if (JvmtiExport::can_post_on_exceptions()) {
JvmtiExport::post_exception_throw(current, h_method(), last_frame.bcp(), h_exception());
}
address continuation = NULL;
address handler_pc = NULL; if (handler_bci < 0 || !current->stack_overflow_state()->reguard_stack((address) &continuation)) { // Forward exception to callee (leaving bci/bcp untouched) because (a) no // handler in this method, or (b) after a stack overflow there is not yet // enough stack space available to reprotect the stack.
continuation = Interpreter::remove_activation_entry(); #if COMPILER2_OR_JVMCI // Count this for compilation purposes
h_method->interpreter_throwout_increment(THREAD); #endif
} else { // handler in this method => change bci/bcp to handler bci/bcp and continue there
handler_pc = h_method->code_base() + handler_bci; #ifndef ZERO
set_bcp_and_mdp(handler_pc, current);
continuation = Interpreter::dispatch_table(vtos)[*handler_pc]; #else
continuation = (address)(intptr_t) handler_bci; #endif
}
// notify debugger of an exception catch // (this is good for exceptions caught in native methods as well) if (JvmtiExport::can_post_on_exceptions()) {
JvmtiExport::notice_unwind_due_to_exception(current, h_method(), handler_pc, h_exception(), (handler_pc != NULL));
}
JRT_ENTRY(void, InterpreterRuntime::throw_pending_exception(JavaThread* current))
assert(current->has_pending_exception(), "must only be called if there's an exception pending"); // nothing to do - eventually we should remove this code entirely (see comments @ call sites)
JRT_END
// This method is called from the "abstract_entry" of the interpreter. // At that point, the arguments have already been removed from the stack // and therefore we don't have the receiver object at our fingertips. (Though, // on some platforms the receiver still resides in a register...). Thus, // we have no choice but print an error message not containing the receiver // type.
JRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorWithMethod(JavaThread* current,
Method* missingMethod))
ResourceMark rm(current);
assert(missingMethod != NULL, "sanity");
methodHandle m(current, missingMethod);
LinkResolver::throw_abstract_method_error(m, THREAD);
JRT_END
{
JvmtiHideSingleStepping jhss(current);
JavaThread* THREAD = current; // For exception macros.
LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode),
m, bytecode, CHECK);
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry(); if (cp_cache_entry->is_resolved(bytecode)) return;
// compute auxiliary field attributes
TosState state = as_TosState(info.field_type());
// Resolution of put instructions on final fields is delayed. That is required so that // exceptions are thrown at the correct place (when the instruction is actually invoked). // If we do not resolve an instruction in the current pass, leaving the put_code // set to zero will cause the next put instruction to the same field to reresolve.
// Resolution of put instructions to final instance fields with invalid updates (i.e., // to final instance fields with updates originating from a method different than <init>) // is inhibited. A putfield instruction targeting an instance final field must throw // an IllegalAccessError if the instruction is not in an instance // initializer method <init>. If resolution were not inhibited, a putfield // in an initializer method could be resolved in the initializer. Subsequent // putfield instructions to the same field would then use cached information. // As a result, those instructions would not pass through the VM. That is, // checks in resolve_field_access() would not be executed for those instructions // and the required IllegalAccessError would not be thrown. // // Also, we need to delay resolving getstatic and putstatic instructions until the // class is initialized. This is required so that access to the static // field will call the initialization function every time until the class // is completely initialized ala. in 2.17.5 in JVM Specification.
InstanceKlass* klass = info.field_holder(); bool uninitialized_static = is_static && !klass->is_initialized(); bool has_initialized_final_update = info.field_holder()->major_version() >= 53 &&
info.has_initialized_final_update();
assert(!(has_initialized_final_update && !info.access_flags().is_final()), "Fields with initialized final updates must be final");
//------------------------------------------------------------------------------------------------------------------------ // Synchronization // // The interpreter's synchronization code is factored out so that it can // be shared by method invocation and synchronized blocks. //%note synchronization_3
//%note monitor_1
JRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* current, BasicObjectLock* elem)) #ifdef ASSERT
current->last_frame().interpreter_frame_verify_monitor(elem); #endif
Handle h_obj(current, elem->obj());
assert(Universe::heap()->is_in_or_null(h_obj()), "must be NULL or an object");
ObjectSynchronizer::enter(h_obj, elem->lock(), current);
assert(Universe::heap()->is_in_or_null(elem->obj()), "must be NULL or an object"); #ifdef ASSERT
current->last_frame().interpreter_frame_verify_monitor(elem); #endif
JRT_END
JRT_LEAF(void, InterpreterRuntime::monitorexit(BasicObjectLock* elem))
oop obj = elem->obj();
assert(Universe::heap()->is_in(obj), "must be an object"); // The object could become unlocked through a JNI call, which we have no other checks for. // Give a fatal message if CheckJNICalls. Otherwise we ignore it. if (obj->is_unlocked()) { if (CheckJNICalls) {
fatal("Object has been unlocked by JNI");
} return;
}
ObjectSynchronizer::exit(obj, elem->lock(), JavaThread::current()); // Free entry. If it is not cleared, the exception handling code will try to unlock the monitor // again at method exit or in the case of an exception.
elem->set_obj(NULL);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThread* current)) // Returns an illegal exception to install into the current thread. The // pending_exception flag is cleared so normal exception handling does not // trigger. Any current installed exception will be overwritten. This // method will be called during an exception unwind.
assert(!HAS_PENDING_EXCEPTION, "no pending exception");
Handle exception(current, current->vm_result());
assert(exception() != NULL, "vm result should be set");
current->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures)
exception = get_preinitialized_exception(vmClasses::IllegalMonitorStateException_klass(), CATCH);
current->set_vm_result(exception());
JRT_END
{
JvmtiHideSingleStepping jhss(current);
JavaThread* THREAD = current; // For exception macros.
LinkResolver::resolve_invoke(info, receiver, pool,
last_frame.get_index_u2_cpcache(bytecode), bytecode,
THREAD);
if (HAS_PENDING_EXCEPTION) { if (ProfileTraps && PENDING_EXCEPTION->klass()->name() == vmSymbols::java_lang_NullPointerException()) { // Preserve the original exception across the call to note_trap()
PreserveExceptionMark pm(current); // Recording the trap will help the compiler to potentially recognize this exception as "hot"
note_trap(current, Deoptimization::Reason_null_check);
} return;
}
// check if link resolution caused cpCache to be updated
ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry(); if (cp_cache_entry->is_resolved(bytecode)) return;
#ifdef ASSERT if (bytecode == Bytecodes::_invokeinterface) { if (resolved_method->method_holder() == vmClasses::Object_klass()) { // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec // (see also CallInfo::set_interface for details)
assert(info.call_kind() == CallInfo::vtable_call ||
info.call_kind() == CallInfo::direct_call, "");
assert(resolved_method->is_final() || info.has_vtable_index(), "should have been set already");
} elseif (!resolved_method->has_itable_index()) { // Resolved something like CharSequence.toString. Use vtable not itable.
assert(info.call_kind() != CallInfo::itable_call, "");
} else { // Setup itable entry
assert(info.call_kind() == CallInfo::itable_call, ""); int index = resolved_method->itable_index();
assert(info.itable_index() == index, "");
}
} elseif (bytecode == Bytecodes::_invokespecial) {
assert(info.call_kind() == CallInfo::direct_call, "must be direct call");
} else {
assert(info.call_kind() == CallInfo::direct_call ||
info.call_kind() == CallInfo::vtable_call, "");
} #endif // Get sender and only set cpCache entry to resolved if it is not an // interface. The receiver for invokespecial calls within interface // methods must be checked for every call.
InstanceKlass* sender = pool->pool_holder();
switch (info.call_kind()) { case CallInfo::direct_call:
cp_cache_entry->set_direct_call(
bytecode,
resolved_method,
sender->is_interface()); break; case CallInfo::vtable_call:
cp_cache_entry->set_vtable_call(
bytecode,
resolved_method,
info.vtable_index()); break; case CallInfo::itable_call:
cp_cache_entry->set_itable_call(
bytecode,
info.resolved_klass(),
resolved_method,
info.itable_index()); break; default: ShouldNotReachHere();
}
}
// First time execution: Resolve symbols, create a permanent MethodType object. void InterpreterRuntime::resolve_invokehandle(JavaThread* current) { const Bytecodes::Code bytecode = Bytecodes::_invokehandle;
LastFrameAccessor last_frame(current);
// resolve method
CallInfo info;
constantPoolHandle pool(current, last_frame.method()->constants());
{
JvmtiHideSingleStepping jhss(current);
JavaThread* THREAD = current; // For exception macros.
LinkResolver::resolve_invoke(info, Handle(), pool,
last_frame.get_index_u2_cpcache(bytecode), bytecode,
CHECK);
} // end JvmtiHideSingleStepping
// This function is the interface to the assembly code. It returns the resolved // cpCache entry. This doesn't safepoint, but the helper routines safepoint. // This function will check for redefinition!
JRT_ENTRY(void, InterpreterRuntime::resolve_from_cache(JavaThread* current, Bytecodes::Code bytecode)) { switch (bytecode) { case Bytecodes::_getstatic: case Bytecodes::_putstatic: case Bytecodes::_getfield: case Bytecodes::_putfield:
resolve_get_put(current, bytecode); break; case Bytecodes::_invokevirtual: case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokeinterface:
resolve_invoke(current, bytecode); break; case Bytecodes::_invokehandle:
resolve_invokehandle(current); break; case Bytecodes::_invokedynamic:
resolve_invokedynamic(current); break; default:
fatal("unexpected bytecode: %s", Bytecodes::name(bytecode)); break;
}
}
JRT_END
nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* current, address branch_bcp) { // Enable WXWrite: the function is called directly by interpreter.
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, current));
// frequency_counter_overflow_inner can throw async exception.
nmethod* nm = frequency_counter_overflow_inner(current, branch_bcp);
assert(branch_bcp != NULL || nm == NULL, "always returns null for non OSR requests"); if (branch_bcp != NULL && nm != NULL) { // This was a successful request for an OSR nmethod. Because // frequency_counter_overflow_inner ends with a safepoint check, // nm could have been unloaded so look it up again. It's unsafe // to examine nm directly since it might have been freed and used // for something else.
LastFrameAccessor last_frame(current);
Method* method = last_frame.method(); int bci = method->bci_from(last_frame.bcp());
nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false);
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); if (nm != NULL && bs_nm != NULL) { // in case the transition passed a safepoint we need to barrier this again if (!bs_nm->nmethod_osr_entry_barrier(nm)) {
nm = NULL;
}
}
} if (nm != NULL && current->is_interp_only_mode()) { // Normally we never get an nm if is_interp_only_mode() is true, because // policy()->event has a check for this and won't compile the method when // true. However, it's possible for is_interp_only_mode() to become true // during the compilation. We don't want to return the nm in that case // because we want to continue to execute interpreted.
nm = NULL;
} #ifndef PRODUCT if (TraceOnStackReplacement) { if (nm != NULL) {
tty->print("OSR entry @ pc: " INTPTR_FORMAT ": ", p2i(nm->osr_entry()));
nm->print();
}
} #endif return nm;
}
JRT_ENTRY(nmethod*,
InterpreterRuntime::frequency_counter_overflow_inner(JavaThread* current, address branch_bcp)) // use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized // flag, in case this method triggers classloading which will call into Java.
UnlockFlagSaver fs(current);
MethodData* mdo = method->method_data();
assert(mdo != NULL, "must not be null");
int bci = method->bci_from(bcp);
address mdp2 = mdo->bci_to_dp(bci); if (mdp != mdp2) {
ResourceMark rm;
tty->print_cr("FAILED verify : actual mdp %p expected mdp %p @ bci %d", mdp, mdp2, bci); int current_di = mdo->dp_to_di(mdp); int expected_di = mdo->dp_to_di(mdp2);
tty->print_cr(" actual di %d expected di %d", current_di, expected_di); int expected_approx_bci = mdo->data_at(expected_di)->bci(); int approx_bci = -1; if (current_di >= 0) {
approx_bci = mdo->data_at(current_di)->bci();
}
tty->print_cr(" actual bci is %d expected bci %d", approx_bci, expected_approx_bci);
mdo->print_on(tty);
method->print_codes();
}
assert(mdp == mdp2, "wrong mdp");
JRT_END #endif// ASSERT
JRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* current, int return_bci))
assert(ProfileInterpreter, "must be profiling interpreter");
ResourceMark rm(current);
LastFrameAccessor last_frame(current);
assert(last_frame.is_interpreted_frame(), "must come from interpreter");
MethodData* h_mdo = last_frame.method()->method_data();
// Grab a lock to ensure atomic access to setting the return bci and // the displacement. This can block and GC, invalidating all naked oops.
MutexLocker ml(RetData_lock);
// ProfileData is essentially a wrapper around a derived oop, so we // need to take the lock before making any ProfileData structures.
ProfileData* data = h_mdo->data_at(h_mdo->dp_to_di(last_frame.mdp()));
guarantee(data != NULL, "profile data must be valid");
RetData* rdata = data->as_RetData();
address new_mdp = rdata->fixup_ret(return_bci, h_mdo);
last_frame.set_mdp(new_mdp);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* current)) // We used to need an explicit preserve_arguments here for invoke bytecodes. However, // stack traversal automatically takes care of preserving arguments for invoke, so // this is no longer needed.
// JRT_END does an implicit safepoint check, hence we are guaranteed to block // if this is called during a safepoint
if (java_lang_VirtualThread::notify_jvmti_events()) {
JvmtiExport::check_vthread_and_suspend_at_safepoint(current);
}
if (JvmtiExport::should_post_single_step()) { // This function is called by the interpreter when single stepping. Such single // stepping could unwind a frame. Then, it is important that we process any frames // that we might return into.
StackWatermarkSet::before_unwind(current);
// We are called during regular safepoints and when the VM is // single stepping. If any thread is marked for single stepping, // then we may have JVMTI work to do.
LastFrameAccessor last_frame(current);
JvmtiExport::at_single_stepping_point(current, last_frame.method(), last_frame.bcp());
}
JRT_END
JRT_LEAF(void, InterpreterRuntime::at_unwind(JavaThread* current))
assert(current == JavaThread::current(), "pre-condition"); // This function is called by the interpreter when the return poll found a reason // to call the VM. The reason could be that we are returning into a not yet safe // to access frame. We handle that below. // Note that this path does not check for single stepping, because we do not want // to single step when unwinding frames for an exception being thrown. Instead, // such single stepping code will use the safepoint table, which will use the // InterpreterRuntime::at_safepoint callback.
StackWatermarkSet::before_unwind(current);
JRT_END
// check the access_flags for the field in the klass
InstanceKlass* ik = InstanceKlass::cast(cp_entry->f1_as_klass()); int index = cp_entry->field_index(); if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
// check the access_flags for the field in the klass
InstanceKlass* ik = InstanceKlass::cast(k); int index = cp_entry->field_index(); // bail out if field modifications are not watched if ((ik->field_access_flags(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return;
char sig_type = '\0';
switch(cp_entry->flag_state()) { case btos: sig_type = JVM_SIGNATURE_BYTE; break; case ztos: sig_type = JVM_SIGNATURE_BOOLEAN; break; case ctos: sig_type = JVM_SIGNATURE_CHAR; break; case stos: sig_type = JVM_SIGNATURE_SHORT; break; case itos: sig_type = JVM_SIGNATURE_INT; break; case ftos: sig_type = JVM_SIGNATURE_FLOAT; break; case atos: sig_type = JVM_SIGNATURE_CLASS; break; case ltos: sig_type = JVM_SIGNATURE_LONG; break; case dtos: sig_type = JVM_SIGNATURE_DOUBLE; break; default: ShouldNotReachHere(); return;
} bool is_static = (obj == NULL);
HandleMark hm(current);
jfieldID fid = jfieldIDWorkaround::to_jfieldID(ik, cp_entry->f2_as_index(), is_static);
jvalue fvalue; #ifdef _LP64
fvalue = *value; #else // Long/double values are stored unaligned and also noncontiguously with // tagged stacks. We can't just do a simple assignment even in the non- // J/D cases because a C++ compiler is allowed to assume that a jvalue is // 8-byte aligned, and interpreter stack slots are only 4-byte aligned. // We assume that the two halves of longs/doubles are stored in interpreter // stack slots in platform-endian order.
jlong_accessor u;
jint* newval = (jint*)value;
u.words[0] = newval[0];
u.words[1] = newval[Interpreter::stackElementWords]; // skip if tag
fvalue.j = u.long_value; #endif// _LP64
Handle h_obj; if (!is_static) { // non-static field accessors have an object, but we need a handle
h_obj = Handle(current, obj);
}
// This is a JRT_BLOCK_ENTRY because we have to stash away the return oop // before transitioning to VM, and restore it after transitioning back // to Java. The return oop at the top-of-stack, is not walked by the GC.
JRT_BLOCK_ENTRY(void, InterpreterRuntime::post_method_exit(JavaThread* current))
LastFrameAccessor last_frame(current);
JvmtiExport::post_method_exit(current, last_frame.method(), last_frame.get_frame());
JRT_END
JRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* current, Method* method))
methodHandle m(current, method);
assert(m->is_native(), "sanity check"); // lookup native function entry point if it doesn't exist if (!m->has_native_function()) {
NativeLookup::lookup(m, CHECK);
} // make sure signature handler is installed
SignatureHandlerLibrary::add(m); // The interpreter entry point checks the signature handler first, // before trying to fetch the native entry point and klass mirror. // We must set the signature handler last, so that multiple processors // preparing the same method will be sure to see non-null entry & mirror.
JRT_END
#if INCLUDE_JVMTI // This is a support of the JVMTI PopFrame interface. // Make sure it is an invokestatic of a polymorphic intrinsic that has a member_name argument // and return it as a vm_result so that it can be reloaded in the list of invokestatic parameters. // The member_name argument is a saved reference (in local#0) to the member_name. // For backward compatibility with some JDK versions (7, 8) it can also be a direct method handle. // FIXME: remove DMH case after j.l.i.InvokerBytecodeGenerator code shape is updated.
JRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* current, address member_name,
Method* method, address bcp))
Bytecodes::Code code = Bytecodes::code_at(method, bcp); if (code != Bytecodes::_invokestatic) { return;
}
ConstantPool* cpool = method->constants(); int cp_index = Bytes::get_native_u2(bcp + 1) + ConstantPool::CPCACHE_INDEX_TAG;
Symbol* cname = cpool->klass_name_at(cpool->klass_ref_index_at(cp_index));
Symbol* mname = cpool->name_ref_at(cp_index);
if (MethodHandles::has_member_arg(cname, mname)) {
oop member_name_oop = cast_to_oop(member_name); if (java_lang_invoke_DirectMethodHandle::is_instance(member_name_oop)) { // FIXME: remove after j.l.i.InvokerBytecodeGenerator code shape is updated.
member_name_oop = java_lang_invoke_DirectMethodHandle::member(member_name_oop);
}
current->set_vm_result(member_name_oop);
} else {
current->set_vm_result(NULL);
}
JRT_END #endif// INCLUDE_JVMTI
#ifndef PRODUCT // This must be a JRT_LEAF function because the interpreter must save registers on x86 to // call this, which changes rsp and makes the interpreter's expression stack not walkable. // The generated code still uses call_VM because that will set up the frame pointer for // bcp and method.
JRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* current, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
assert(current == JavaThread::current(), "pre-condition");
LastFrameAccessor last_frame(current);
assert(last_frame.is_interpreted_frame(), "must be an interpreted frame");
methodHandle mh(current, last_frame.method());
BytecodeTracer::trace_interpreter(mh, last_frame.bcp(), tos, tos2); return preserve_this_value;
JRT_END #endif// !PRODUCT
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet am 2026-09-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Angebot
Hier finden Sie eine Liste der Produkte des Unternehmens