--- a/src/hotspot/share/runtime/sharedRuntime.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,6 @@
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
-#include "runtime/compilationPolicy.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
@@ -764,18 +763,9 @@
throw_and_post_jvmti_exception(thread, exception);
}
-#if INCLUDE_JVMCI
-address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, CompiledMethod* nm, int deopt_reason) {
- assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
- thread->set_jvmci_implicit_exception_pc(pc);
- thread->set_pending_deoptimization(Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret));
- return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
-}
-#endif // INCLUDE_JVMCI
-
address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
address pc,
- SharedRuntime::ImplicitExceptionKind exception_kind)
+ ImplicitExceptionKind exception_kind)
{
address target_pc = NULL;
@@ -876,19 +866,7 @@
#ifndef PRODUCT
_implicit_null_throws++;
#endif
-#if INCLUDE_JVMCI
- if (cm->is_compiled_by_jvmci() && cm->pc_desc_at(pc) != NULL) {
- // If there's no PcDesc then we'll die way down inside of
- // deopt instead of just getting normal error reporting,
- // so only go there if it will succeed.
- return deoptimize_for_implicit_exception(thread, pc, cm, Deoptimization::Reason_null_check);
- } else {
-#endif // INCLUDE_JVMCI
- assert (cm->is_nmethod(), "Expect nmethod");
- target_pc = ((nmethod*)cm)->continuation_for_implicit_exception(pc);
-#if INCLUDE_JVMCI
- }
-#endif // INCLUDE_JVMCI
+ target_pc = cm->continuation_for_implicit_null_exception(pc);
// If there's an unexpected fault, target_pc might be NULL,
// in which case we want to fall through into the normal
// error handling code.
@@ -904,15 +882,7 @@
#ifndef PRODUCT
_implicit_div0_throws++;
#endif
-#if INCLUDE_JVMCI
- if (cm->is_compiled_by_jvmci() && cm->pc_desc_at(pc) != NULL) {
- return deoptimize_for_implicit_exception(thread, pc, cm, Deoptimization::Reason_div0_check);
- } else {
-#endif // INCLUDE_JVMCI
- target_pc = cm->continuation_for_implicit_exception(pc);
-#if INCLUDE_JVMCI
- }
-#endif // INCLUDE_JVMCI
+ target_pc = cm->continuation_for_implicit_div0_exception(pc);
// If there's an unexpected fault, target_pc might be NULL,
// in which case we want to fall through into the normal
// error handling code.
@@ -1298,6 +1268,7 @@
// will be supported.
if (!callee_method->is_old() &&
(callee == NULL || (callee->is_in_use() && callee_method->code() == callee))) {
+ NoSafepointVerifier nsv;
#ifdef ASSERT
// We must not try to patch to jump to an already unloaded method.
if (dest_entry_point != 0) {
@@ -1314,6 +1285,12 @@
}
}
} else {
+ if (VM_Version::supports_fast_class_init_checks() &&
+ invoke_code == Bytecodes::_invokestatic &&
+ callee_method->needs_clinit_barrier() &&
+ callee != NULL && (callee->is_compiled_by_jvmci() || callee->is_aot())) {
+ return true; // skip patching for JVMCI or AOT code
+ }
CompiledStaticCall* ssc = caller_nm->compiledStaticCall_before(caller_frame.pc());
if (ssc->is_clean()) ssc->set(static_call_info);
}
@@ -1376,12 +1353,20 @@
}
#endif
- // Do not patch call site for static call when the class is not
- // fully initialized.
- if (invoke_code == Bytecodes::_invokestatic &&
- !callee_method->method_holder()->is_initialized()) {
- assert(callee_method->method_holder()->is_linked(), "must be");
- return callee_method;
+ if (invoke_code == Bytecodes::_invokestatic) {
+ assert(callee_method->method_holder()->is_initialized() ||
+ callee_method->method_holder()->is_reentrant_initialization(thread),
+ "invalid class initialization state for invoke_static");
+ if (!VM_Version::supports_fast_class_init_checks() && callee_method->needs_clinit_barrier()) {
+ // In order to keep class initialization check, do not patch call
+ // site for static call when the class is not fully initialized.
+ // Proper check is enforced by call site re-resolution on every invocation.
+ //
+ // When fast class initialization checks are supported (VM_Version::supports_fast_class_init_checks() == true),
+ // explicit class initialization check is put in nmethod entry (VEP).
+ assert(callee_method->method_holder()->is_linked(), "must be");
+ return callee_method;
+ }
}
// JSR 292 key invariant:
@@ -1461,7 +1446,19 @@
guarantee(callee != NULL && callee->is_method(), "bad handshake");
thread->set_vm_result_2(callee);
thread->set_callee_target(NULL);
- return callee->get_c2i_entry();
+ if (caller_frame.is_entry_frame() && VM_Version::supports_fast_class_init_checks()) {
+ // Bypass class initialization checks in c2i when caller is in native.
+ // JNI calls to static methods don't have class initialization checks.
+ // Fast class initialization checks are present in c2i adapters and call into
+ // SharedRuntime::handle_wrong_method() on the slow path.
+ //
+ // JVM upcalls may land here as well, but there's a proper check present in
+ // LinkResolver::resolve_static_call (called from JavaCalls::call_static),
+ // so bypassing it in c2i adapter is benign.
+ return callee->get_c2i_no_clinit_check_entry();
+ } else {
+ return callee->get_c2i_entry();
+ }
}
// Must be compiled to compiled path which is safe to stackwalk
@@ -2035,7 +2032,7 @@
const char* caster_name = caster_klass->external_name();
assert(target_klass != NULL || target_klass_name != NULL, "one must be provided");
- const char* target_name = target_klass == NULL ? target_klass_name->as_C_string() :
+ const char* target_name = target_klass == NULL ? target_klass_name->as_klass_external_name() :
target_klass->external_name();
size_t msglen = strlen(caster_name) + strlen("class ") + strlen(" cannot be cast to class ") + strlen(target_name) + 1;
@@ -2094,12 +2091,7 @@
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(THREAD, obj);
- if (UseBiasedLocking) {
- // Retry fast entry if bias is revoked to avoid unnecessary inflation
- ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
- } else {
- ObjectSynchronizer::slow_enter(h_obj, lock, CHECK);
- }
+ ObjectSynchronizer::enter(h_obj, lock, CHECK);
assert(!HAS_PENDING_EXCEPTION, "Should have no exception here");
JRT_BLOCK_END
JRT_END
@@ -2130,7 +2122,7 @@
{
// Exit must be non-blocking, and therefore no exceptions can be thrown.
EXCEPTION_MARK;
- ObjectSynchronizer::slow_exit(obj, lock, THREAD);
+ ObjectSynchronizer::exit(obj, lock, THREAD);
}
#ifdef MIGHT_HAVE_PENDING
@@ -2465,9 +2457,9 @@
: BasicHashtable<mtCode>(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { }
// Create a new entry suitable for insertion in the table
- AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
+ AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry) {
AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
- entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+ entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
if (DumpSharedSpaces) {
((CDSAdapterHandlerEntry*)entry)->init();
}
@@ -2616,8 +2608,9 @@
AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint,
address i2c_entry,
address c2i_entry,
- address c2i_unverified_entry) {
- return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
+ address c2i_unverified_entry,
+ address c2i_no_clinit_check_entry) {
+ return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
}
AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
@@ -2793,6 +2786,7 @@
if (base == NULL) base = _c2i_entry;
assert(base <= _c2i_entry || _c2i_entry == NULL, "");
assert(base <= _c2i_unverified_entry || _c2i_unverified_entry == NULL, "");
+ assert(base <= _c2i_no_clinit_check_entry || _c2i_no_clinit_check_entry == NULL, "");
return base;
}
@@ -2806,6 +2800,8 @@
_c2i_entry += delta;
if (_c2i_unverified_entry != NULL)
_c2i_unverified_entry += delta;
+ if (_c2i_no_clinit_check_entry != NULL)
+ _c2i_no_clinit_check_entry += delta;
assert(base_address() == new_base, "");
}
@@ -2813,7 +2809,7 @@
void AdapterHandlerEntry::deallocate() {
delete _fingerprint;
#ifdef ASSERT
- if (_saved_code) FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
+ FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
#endif
}
@@ -2848,11 +2844,17 @@
void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
ResourceMark rm;
nmethod* nm = NULL;
+ address critical_entry = NULL;
assert(method->is_native(), "must be native");
assert(method->is_method_handle_intrinsic() ||
method->has_native_function(), "must have something valid to call!");
+ if (CriticalJNINatives && !method->is_method_handle_intrinsic()) {
+ // We perform the I/O with transition to native before acquiring AdapterHandlerLibrary_lock.
+ critical_entry = NativeLookup::lookup_critical_entry(method);
+ }
+
{
// Perform the work while holding the lock, but perform any printing outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
@@ -2897,10 +2899,15 @@
int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing);
// Generate the compiled-to-native wrapper code
- nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type);
+ nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type, critical_entry);
if (nm != NULL) {
- method->set_code(method, nm);
+ {
+ MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
+ if (nm->make_in_use()) {
+ method->set_code(method, nm);
+ }
+ }
DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
if (directive->PrintAssemblyOption) {
@@ -3105,10 +3112,10 @@
if (kptr2->obj() != NULL) { // Avoid 'holes' in the monitor array
BasicLock *lock = kptr2->lock();
// Inflate so the displaced header becomes position-independent
- if (lock->displaced_header()->is_unlocked())
+ if (lock->displaced_header().is_unlocked())
ObjectSynchronizer::inflate_helper(kptr2->obj());
// Now the displaced header is free to move
- buf[i++] = (intptr_t)lock->displaced_header();
+ buf[i++] = (intptr_t)lock->displaced_header().value();
buf[i++] = cast_from_oop<intptr_t>(kptr2->obj());
}
}
@@ -3144,10 +3151,20 @@
}
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
- st->print_cr("AHE@" INTPTR_FORMAT ": %s i2c: " INTPTR_FORMAT " c2i: " INTPTR_FORMAT " c2iUV: " INTPTR_FORMAT,
- p2i(this), fingerprint()->as_string(),
- p2i(get_i2c_entry()), p2i(get_c2i_entry()), p2i(get_c2i_unverified_entry()));
-
+ st->print("AHE@" INTPTR_FORMAT ": %s", p2i(this), fingerprint()->as_string());
+ if (get_i2c_entry() != NULL) {
+ st->print(" i2c: " INTPTR_FORMAT, p2i(get_i2c_entry()));
+ }
+ if (get_c2i_entry() != NULL) {
+ st->print(" c2i: " INTPTR_FORMAT, p2i(get_c2i_entry()));
+ }
+ if (get_c2i_unverified_entry() != NULL) {
+ st->print(" c2iUV: " INTPTR_FORMAT, p2i(get_c2i_unverified_entry()));
+ }
+ if (get_c2i_no_clinit_check_entry() != NULL) {
+ st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
+ }
+ st->cr();
}
#if INCLUDE_CDS