< prev index next >
src/share/vm/runtime/sharedRuntime.cpp
Print this page
*** 21,30 ****
--- 21,31 ----
* questions.
*
*/
#include "precompiled.hpp"
+ #include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/codeCacheExtensions.hpp"
*** 44,53 ****
--- 45,55 ----
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/biasedLocking.hpp"
+ #include "runtime/compilationPolicy.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/sharedRuntime.hpp"
*** 91,106 ****
_ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub");
_resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call");
_resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call");
_resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call");
! #ifdef COMPILER2
! // Vectors are generated only by C2.
! if (is_wide_vector(MaxVectorSize)) {
_polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
}
! #endif // COMPILER2
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);
generate_deopt_blob();
--- 93,109 ----
_ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub");
_resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call");
_resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), "resolve_virtual_call");
_resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call");
! #if defined(COMPILER2) || INCLUDE_JVMCI
! // Vectors are generated only by C2 and JVMCI.
! bool support_wide = is_wide_vector(MaxVectorSize);
! if (support_wide) {
_polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
}
! #endif // COMPILER2 || INCLUDE_JVMCI
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);
generate_deopt_blob();
*** 459,468 ****
--- 462,477 ----
assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?");
// Reset method handle flag.
thread->set_is_method_handle_return(false);
+ #if INCLUDE_JVMCI
+ // JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear
+ // and other exception handler continuations do not read it
+ thread->set_exception_pc(NULL);
+ #endif
+
// The fastest case first
CodeBlob* blob = CodeCache::find_blob(return_address);
nmethod* nm = (blob != NULL) ? blob->as_nmethod_or_null() : NULL;
if (nm != NULL) {
// Set flag if return address is a method handle call site.
*** 524,535 ****
// Look up the relocation information
assert(((nmethod*)cb)->is_at_poll_or_poll_return(pc),
"safepoint polling: type must be poll");
! assert(((NativeInstruction*)pc)->is_safepoint_poll(),
! "Only polling locations are used for safepoint");
bool at_poll_return = ((nmethod*)cb)->is_at_poll_return(pc);
bool has_wide_vectors = ((nmethod*)cb)->has_wide_vectors();
if (at_poll_return) {
assert(SharedRuntime::polling_page_return_handler_blob() != NULL,
--- 533,549 ----
// Look up the relocation information
assert(((nmethod*)cb)->is_at_poll_or_poll_return(pc),
"safepoint polling: type must be poll");
! #ifdef ASSERT
! if (!((NativeInstruction*)pc)->is_safepoint_poll()) {
! tty->print_cr("bad pc: " PTR_FORMAT, p2i(pc));
! Disassembler::decode(cb);
! fatal("Only polling locations are used for safepoint");
! }
! #endif
bool at_poll_return = ((nmethod*)cb)->is_at_poll_return(pc);
bool has_wide_vectors = ((nmethod*)cb)->has_wide_vectors();
if (at_poll_return) {
assert(SharedRuntime::polling_page_return_handler_blob() != NULL,
*** 615,624 ****
--- 629,665 ----
address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception,
bool force_unwind, bool top_frame_only) {
assert(nm != NULL, "must exist");
ResourceMark rm;
+ #if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci()) {
+ // lookup exception handler for this pc
+ int catch_pco = ret_pc - nm->code_begin();
+ ExceptionHandlerTable table(nm);
+ HandlerTableEntry *t = table.entry_for(catch_pco, -1, 0);
+ if (t != NULL) {
+ return nm->code_begin() + t->pco();
+ } else {
+ // there is no exception handler for this pc => deoptimize
+ nm->make_not_entrant();
+
+ // Use Deoptimization::deoptimize for all of its side-effects:
+ // revoking biases of monitors, gathering traps statistics, logging...
+ // it also patches the return pc but we do not care about that
+ // since we return a continuation to the deopt_blob below.
+ JavaThread* thread = JavaThread::current();
+ RegisterMap reg_map(thread, UseBiasedLocking);
+ frame runtime_frame = thread->last_frame();
+ frame caller_frame = runtime_frame.sender(®_map);
+ Deoptimization::deoptimize(thread, caller_frame, ®_map, Deoptimization::Reason_not_compiled_exception_handler);
+
+ return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
+ }
+ }
+ #endif // INCLUDE_JVMCI
+
ScopeDesc* sd = nm->scope_desc_at(ret_pc);
// determine handler bci, if any
EXCEPTION_MARK;
int handler_bci = -1;
*** 735,744 ****
--- 776,794 ----
// Increment counter for hs_err file reporting
Atomic::inc(&Exceptions::_stack_overflow_errors);
throw_and_post_jvmti_exception(thread, exception);
JRT_END
+ #if INCLUDE_JVMCI
+ address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* 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)
{
address target_pc = NULL;
*** 804,815 ****
// 3. Implicit null exception in nmethod
if (!cb->is_nmethod()) {
bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob();
if (!is_in_blob) {
! cb->print();
! fatal(err_msg("exception happened outside interpreter, nmethods and vtable stubs at pc " INTPTR_FORMAT, pc));
}
Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc);
// There is no handler here, so we will simply unwind.
return StubRoutines::throw_NullPointerException_at_call_entry();
}
--- 854,865 ----
// 3. Implicit null exception in nmethod
if (!cb->is_nmethod()) {
bool is_in_blob = cb->is_adapter_blob() || cb->is_method_handles_adapter_blob();
if (!is_in_blob) {
! // Allow normal crash reporting to handle this
! return NULL;
}
Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc);
// There is no handler here, so we will simply unwind.
return StubRoutines::throw_NullPointerException_at_call_entry();
}
*** 832,842 ****
--- 882,904 ----
}
#ifndef PRODUCT
_implicit_null_throws++;
#endif
+ #if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci() && nm->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, nm, Deoptimization::Reason_null_check);
+ } else {
+ #endif // INCLUDE_JVMCI
+ assert (nm->is_nmethod(), "Expect nmethod");
target_pc = nm->continuation_for_implicit_exception(pc);
+ #if INCLUDE_JVMCI
+ }
+ #endif // INCLUDE_JVMCI
// 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.
}
*** 844,858 ****
}
case IMPLICIT_DIVIDE_BY_ZERO: {
nmethod* nm = CodeCache::find_nmethod(pc);
! guarantee(nm != NULL, "must have containing nmethod for implicit division-by-zero exceptions");
#ifndef PRODUCT
_implicit_div0_throws++;
#endif
target_pc = nm->continuation_for_implicit_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.
break; // fall through
}
--- 906,928 ----
}
case IMPLICIT_DIVIDE_BY_ZERO: {
nmethod* nm = CodeCache::find_nmethod(pc);
! guarantee(nm != NULL, "must have containing compiled method for implicit division-by-zero exceptions");
#ifndef PRODUCT
_implicit_div0_throws++;
#endif
+ #if INCLUDE_JVMCI
+ if (nm->is_compiled_by_jvmci() && nm->pc_desc_at(pc) != NULL) {
+ return deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check);
+ } else {
+ #endif // INCLUDE_JVMCI
target_pc = nm->continuation_for_implicit_exception(pc);
+ #if INCLUDE_JVMCI
+ }
+ #endif // INCLUDE_JVMCI
// 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.
break; // fall through
}
*** 860,874 ****
default: ShouldNotReachHere();
}
assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind");
- // for AbortVMOnException flag
- NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException"));
if (exception_kind == IMPLICIT_NULL) {
Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
} else {
Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
}
return target_pc;
}
--- 930,950 ----
default: ShouldNotReachHere();
}
assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind");
if (exception_kind == IMPLICIT_NULL) {
+ #ifndef PRODUCT
+ // for AbortVMOnException flag
+ Exceptions::debug_check_abort("java.lang.NullPointerException");
+ #endif //PRODUCT
Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
} else {
+ #ifndef PRODUCT
+ // for AbortVMOnException flag
+ Exceptions::debug_check_abort("java.lang.ArithmeticException");
+ #endif //PRODUCT
Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc);
}
return target_pc;
}
*** 914,923 ****
--- 990,1009 ----
JRT_END
#endif // !PRODUCT
JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
assert(obj->is_oop(), "must be a valid oop");
+ #if INCLUDE_JVMCI
+ // This removes the requirement for JVMCI compilers to emit code
+ // performing a dynamic check that obj has a finalizer before
+ // calling this routine. There should be no performance impact
+ // for C1 since it emits a dynamic check. C2 and the interpreter
+ // uses other runtime routines for registering finalizers.
+ if (!obj->klass()->has_finalizer()) {
+ return;
+ }
+ #endif // INCLUDE_JVMCI
assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise");
InstanceKlass::register_finalizer(instanceOop(obj), CHECK);
JRT_END
*** 1155,1164 ****
--- 1241,1251 ----
Handle receiver = find_callee_info(thread, invoke_code,
call_info, CHECK_(methodHandle()));
methodHandle callee_method = call_info.selected_method();
assert((!is_virtual && invoke_code == Bytecodes::_invokestatic ) ||
+ (!is_virtual && invoke_code == Bytecodes::_invokespecial) ||
(!is_virtual && invoke_code == Bytecodes::_invokehandle ) ||
(!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
assert(caller_nm->is_alive(), "It should be alive");
*** 1365,1377 ****
assert(callee_method->verified_code_entry() != NULL, " Jump to zero!");
return callee_method->verified_code_entry();
JRT_END
-
-
-
methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, TRAPS) {
ResourceMark rm(thread);
CallInfo call_info;
Bytecodes::Code bc;
--- 1452,1461 ----
*** 1491,1500 ****
--- 1575,1586 ----
inline_cache->set_to_clean();
}
} else {
// Either clean or megamorphic
}
+ } else {
+ fatal("Unimplemented");
}
} // Release CompiledIC_lock
return callee_method;
}
*** 1518,1527 ****
--- 1604,1617 ----
if (caller.is_compiled_frame() && !caller.is_deoptimized_frame()) {
address pc = caller.pc();
+ // Check for static or virtual call
+ bool is_static_call = false;
+ nmethod* caller_nm = CodeCache::find_nmethod(pc);
+
// Default call_addr is the location of the "basic" call.
// Determine the address of the call we a reresolving. With
// Inline Caches we will always find a recognizable call.
// With Inline Caches disabled we may or may not find a
// recognizable call. We will always find a call for static
*** 1547,1560 ****
if (NativeCall::is_call_before(pc)) {
NativeCall *ncall = nativeCall_before(pc);
call_addr = ncall->instruction_address();
}
}
-
- // Check for static or virtual call
- bool is_static_call = false;
- nmethod* caller_nm = CodeCache::find_nmethod(pc);
// Make sure nmethod doesn't get deoptimized and removed until
// this is done with it.
// CLEANUP - with lazy deopt shouldn't need this lock
nmethodLocker nmlock(caller_nm);
--- 1637,1646 ----
*** 2565,2576 ****
{
// Perform the work while holding the lock, but perform any printing outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
// See if somebody beat us to it
! nm = method->code();
! if (nm != NULL) {
return;
}
const int compile_id = CompileBroker::assign_compile_id(method, CompileBroker::standard_entry_bci);
assert(compile_id > 0, "Must generate native wrapper");
--- 2651,2661 ----
{
// Perform the work while holding the lock, but perform any printing outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
// See if somebody beat us to it
! if (method->code() != NULL) {
return;
}
const int compile_id = CompileBroker::assign_compile_id(method, CompileBroker::standard_entry_bci);
assert(compile_id > 0, "Must generate native wrapper");
*** 2808,2827 ****
JRT_LEAF(void, SharedRuntime::OSR_migration_end( intptr_t* buf) )
FREE_C_HEAP_ARRAY(intptr_t, buf);
JRT_END
! bool AdapterHandlerLibrary::contains(CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) return true;
}
return false;
}
! void AdapterHandlerLibrary::print_handler_on(outputStream* st, CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) {
st->print("Adapter for signature: ");
--- 2893,2912 ----
JRT_LEAF(void, SharedRuntime::OSR_migration_end( intptr_t* buf) )
FREE_C_HEAP_ARRAY(intptr_t, buf);
JRT_END
! bool AdapterHandlerLibrary::contains(const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) return true;
}
return false;
}
! void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) {
AdapterHandlerTableIterator iter(_adapters);
while (iter.has_next()) {
AdapterHandlerEntry* a = iter.next();
if (b == CodeCache::find_blob(a->get_i2c_entry())) {
st->print("Adapter for signature: ");
< prev index next >