--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon May 09 13:13:07 2016 +0300
@@ -825,17 +825,6 @@
return start;
}
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- //
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ function_entry();
- __ unimplemented("StubRoutines::handler_for_unsafe_access", 93);
- return start;
- }
-
#if !defined(PRODUCT)
// Wrapper which calls oopDesc::is_oop_or_null()
// Only called by MacroAssembler::verify_oop
@@ -3111,8 +3100,6 @@
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
- StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access();
-
// support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Mon May 09 13:13:07 2016 +0300
@@ -64,20 +64,6 @@
// -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- address npc = thread->saved_exception_npc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -746,62 +732,6 @@
Label _atomic_add_stub; // called from other stubs
- //------------------------------------------------------------------------------------------------------------------------
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- //
- // Arguments :
- //
- // trapping PC: O7
- //
- // Results:
- // posts an asynchronous exception, skips the trapping instruction
- //
-
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- const int preserve_register_words = (64 * 2);
- Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
-
- Register Lthread = L7_thread_cache;
- int i;
-
- __ save_frame(0);
- __ mov(G1, L1);
- __ mov(G2, L2);
- __ mov(G3, L3);
- __ mov(G4, L4);
- __ mov(G5, L5);
- for (i = 0; i < 64; i += 2) {
- __ stf(FloatRegisterImpl::D, as_FloatRegister(i), preserve_addr, i * wordSize);
- }
-
- address entry_point = CAST_FROM_FN_PTR(address, handle_unsafe_access);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(entry_point, relocInfo::runtime_call_type);
- __ delayed()->nop();
-
- __ mov(L1, G1);
- __ mov(L2, G2);
- __ mov(L3, G3);
- __ mov(L4, G4);
- __ mov(L5, G5);
- for (i = 0; i < 64; i += 2) {
- __ ldf(FloatRegisterImpl::D, preserve_addr, as_FloatRegister(i), i * wordSize);
- }
-
- __ verify_thread();
-
- __ jmp(O0, 0);
- __ delayed()->restore();
-
- return start;
- }
-
-
// Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
// Arguments :
//
@@ -5218,9 +5148,6 @@
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// support for verify_oop (must happen after universe_init)
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -63,21 +63,6 @@
// -------------------------------------------------------------------------------------------------------------------------
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = Assembler::locate_next_instruction(pc);
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -623,27 +608,6 @@
}
- //---------------------------------------------------------------------------
- // The following routine generates a subroutine to throw an asynchronous
- // UnknownError when an unsafe access gets a fault that could not be
- // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- __ push(0); // hole for return address-to-be
- __ pusha(); // push registers
- Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
- __ movptr(next_pc, rax); // stuff next address
- __ popa();
- __ ret(0); // jump to next address
-
- return start;
- }
-
-
//----------------------------------------------------------------------------------------------------
// Non-destructive plausibility checks for oops
@@ -3865,9 +3829,6 @@
// These are currently used by Solaris/Intel
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// platform dependent
create_control_words();
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -61,21 +61,6 @@
// Stub Code definitions
-static address handle_unsafe_access() {
- JavaThread* thread = JavaThread::current();
- address pc = thread->saved_exception_pc();
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = Assembler::locate_next_instruction(pc);
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
class StubGenerator: public StubCodeGenerator {
private:
@@ -989,32 +974,6 @@
return start;
}
- // The following routine generates a subroutine to throw an
- // asynchronous UnknownError when an unsafe access gets a fault that
- // could not be reasonably prevented by the programmer. (Example:
- // SIGBUS/OBJERR.)
- address generate_handler_for_unsafe_access() {
- StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
- address start = __ pc();
-
- __ push(0); // hole for return address-to-be
- __ pusha(); // push registers
- Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
-
- // FIXME: this probably needs alignment logic
-
- __ subptr(rsp, frame::arg_reg_save_area_bytes);
- BLOCK_COMMENT("call handle_unsafe_access");
- __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
- __ addptr(rsp, frame::arg_reg_save_area_bytes);
-
- __ movptr(next_pc, rax); // stuff next address
- __ popa();
- __ ret(0); // jump to next address
-
- return start;
- }
-
// Non-destructive plausibility checks for oops
//
// Arguments:
@@ -5139,9 +5098,6 @@
StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr();
StubRoutines::_fence_entry = generate_orderaccess_fence();
- StubRoutines::_handler_for_unsafe_access_entry =
- generate_handler_for_unsafe_access();
-
// platform dependent
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
--- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -261,10 +261,6 @@
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub();
StubRoutines::_fence_entry = ShouldNotCallThisStub();
-
- // amd64 does this here, sparc does it in generate_all()
- StubRoutines::_handler_for_unsafe_access_entry =
- ShouldNotCallThisStub();
}
void generate_all() {
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Mon May 09 13:13:07 2016 +0300
@@ -392,11 +392,9 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Aix::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
}
}
@@ -415,11 +413,9 @@
}
else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Aix::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
}
}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Mon May 09 13:13:07 2016 +0300
@@ -584,7 +584,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -655,7 +656,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Mon May 09 13:13:07 2016 +0300
@@ -226,23 +226,6 @@
extern "C" void FetchNResume () ;
#endif
-// An operation in Unsafe has faulted. We're going to return to the
-// instruction after the faulting load or store. We also set
-// pending_unsafe_access_error so that at some point in the future our
-// user will get a helpful message.
-static address handle_unsafe_access(JavaThread* thread, address pc) {
- // pc is the instruction which we must emulate
- // doing a no-op is fine: return garbage from the load
- // therefore, compute npc
- address npc = pc + NativeCall::instruction_size;
-
- // request an async exception
- thread->set_pending_unsafe_access_error();
-
- // return address of next instruction to execute
- return npc;
-}
-
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
@@ -387,7 +370,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = handle_unsafe_access(thread, pc);
+ address next_pc = pc + NativeCall::instruction_size;
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -408,7 +392,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = handle_unsafe_access(thread, pc);
+ address next_pc = pc + NativeCall::instruction_size;
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Mon May 09 13:13:07 2016 +0300
@@ -366,11 +366,9 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
- os::Linux::ucontext_set_pc(uc, pc + 4);
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
+ os::Linux::ucontext_set_pc(uc, next_pc);
return true;
}
}
@@ -385,10 +383,8 @@
}
else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && thread->doing_unsafe_access()) {
- // We don't really need a stub here! Just set the pending exeption and
- // continue at the next instruction after the faulting read. Returning
- // garbage from this read is ok.
- thread->set_pending_unsafe_access_error();
+ address next_pc = pc + 4;
+ next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
os::Linux::ucontext_set_pc(uc, pc + 4);
return true;
}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Mon May 09 13:13:07 2016 +0300
@@ -433,14 +433,14 @@
return false;
}
-inline static bool checkByteBuffer(address pc, address* stub) {
+inline static bool checkByteBuffer(address pc, address npc, address* stub) {
// BugId 4454115: A read from a MappedByteBuffer can fault
// here if the underlying file has been truncated.
// Do not crash the VM in such a case.
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- *stub = StubRoutines::handler_for_unsafe_access();
+ *stub = SharedRuntime::handle_unsafe_access(thread, npc);
return true;
}
return false;
@@ -613,7 +613,7 @@
if (sig == SIGBUS &&
thread->thread_state() == _thread_in_vm &&
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
if (thread->thread_state() == _thread_in_Java) {
@@ -625,7 +625,7 @@
break;
}
- if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) {
+ if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
break;
}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon May 09 13:13:07 2016 +0300
@@ -420,7 +420,8 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
else
@@ -469,7 +470,8 @@
} else if (thread->thread_state() == _thread_in_vm &&
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Mon May 09 13:13:07 2016 +0300
@@ -441,7 +441,7 @@
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
}
@@ -480,7 +480,7 @@
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ stub = SharedRuntime::handle_unsafe_access(thread, npc);
}
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Mon May 09 13:13:07 2016 +0300
@@ -503,7 +503,8 @@
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
@@ -520,7 +521,8 @@
if (cb != NULL) {
CompiledMethod* nm = cb->as_compiled_method_or_null();
if (nm != NULL && nm->has_unsafe_access()) {
- stub = StubRoutines::handler_for_unsafe_access();
+ address next_pc = Assembler::locate_next_instruction(pc);
+ stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
}
}
}
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Mon May 09 13:13:07 2016 +0300
@@ -198,20 +198,6 @@
case vmIntrinsics::_putLongVolatile:
case vmIntrinsics::_putFloatVolatile:
case vmIntrinsics::_putDoubleVolatile:
- case vmIntrinsics::_getByte_raw:
- case vmIntrinsics::_getShort_raw:
- case vmIntrinsics::_getChar_raw:
- case vmIntrinsics::_getInt_raw:
- case vmIntrinsics::_getLong_raw:
- case vmIntrinsics::_getFloat_raw:
- case vmIntrinsics::_getDouble_raw:
- case vmIntrinsics::_putByte_raw:
- case vmIntrinsics::_putShort_raw:
- case vmIntrinsics::_putChar_raw:
- case vmIntrinsics::_putInt_raw:
- case vmIntrinsics::_putLong_raw:
- case vmIntrinsics::_putFloat_raw:
- case vmIntrinsics::_putDouble_raw:
case vmIntrinsics::_getShortUnaligned:
case vmIntrinsics::_getCharUnaligned:
case vmIntrinsics::_getIntUnaligned:
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Mon May 09 13:13:07 2016 +0300
@@ -3465,20 +3465,6 @@
case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return;
case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return;
case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return;
- case vmIntrinsics::_getByte_raw : append_unsafe_get_raw(callee, T_BYTE ); return;
- case vmIntrinsics::_getShort_raw : append_unsafe_get_raw(callee, T_SHORT ); return;
- case vmIntrinsics::_getChar_raw : append_unsafe_get_raw(callee, T_CHAR ); return;
- case vmIntrinsics::_getInt_raw : append_unsafe_get_raw(callee, T_INT ); return;
- case vmIntrinsics::_getLong_raw : append_unsafe_get_raw(callee, T_LONG ); return;
- case vmIntrinsics::_getFloat_raw : append_unsafe_get_raw(callee, T_FLOAT ); return;
- case vmIntrinsics::_getDouble_raw : append_unsafe_get_raw(callee, T_DOUBLE); return;
- case vmIntrinsics::_putByte_raw : append_unsafe_put_raw(callee, T_BYTE ); return;
- case vmIntrinsics::_putShort_raw : append_unsafe_put_raw(callee, T_SHORT ); return;
- case vmIntrinsics::_putChar_raw : append_unsafe_put_raw(callee, T_CHAR ); return;
- case vmIntrinsics::_putInt_raw : append_unsafe_put_raw(callee, T_INT ); return;
- case vmIntrinsics::_putLong_raw : append_unsafe_put_raw(callee, T_LONG ); return;
- case vmIntrinsics::_putFloat_raw : append_unsafe_put_raw(callee, T_FLOAT ); return;
- case vmIntrinsics::_putDouble_raw : append_unsafe_put_raw(callee, T_DOUBLE); return;
case vmIntrinsics::_compareAndSwapLong:
case vmIntrinsics::_compareAndSwapInt:
case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return;
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Mon May 09 13:13:07 2016 +0300
@@ -580,20 +580,6 @@
case vmIntrinsics::_putLongOpaque:
case vmIntrinsics::_putFloatOpaque:
case vmIntrinsics::_putDoubleOpaque:
- case vmIntrinsics::_getByte_raw:
- case vmIntrinsics::_getShort_raw:
- case vmIntrinsics::_getChar_raw:
- case vmIntrinsics::_getInt_raw:
- case vmIntrinsics::_getLong_raw:
- case vmIntrinsics::_getFloat_raw:
- case vmIntrinsics::_getDouble_raw:
- case vmIntrinsics::_putByte_raw:
- case vmIntrinsics::_putShort_raw:
- case vmIntrinsics::_putChar_raw:
- case vmIntrinsics::_putInt_raw:
- case vmIntrinsics::_putLong_raw:
- case vmIntrinsics::_putFloat_raw:
- case vmIntrinsics::_putDouble_raw:
case vmIntrinsics::_getAndAddInt:
case vmIntrinsics::_getAndAddLong:
case vmIntrinsics::_getAndSetInt:
@@ -634,8 +620,6 @@
case vmIntrinsics::_putIntUnaligned:
case vmIntrinsics::_putLongUnaligned:
case vmIntrinsics::_allocateInstance:
- case vmIntrinsics::_getAddress_raw:
- case vmIntrinsics::_putAddress_raw:
if (!InlineUnsafeOps || !UseUnalignedAccesses) return true;
break;
case vmIntrinsics::_hashCode:
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon May 09 13:13:07 2016 +0300
@@ -1232,43 +1232,6 @@
do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \
do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \
\
- /* %%% these are redundant except perhaps for getAddress, but Unsafe has native methods for them */ \
- do_signature(getByte_raw_signature, "(J)B") \
- do_signature(putByte_raw_signature, "(JB)V") \
- do_signature(getShort_raw_signature, "(J)S") \
- do_signature(putShort_raw_signature, "(JS)V") \
- do_signature(getChar_raw_signature, "(J)C") \
- do_signature(putChar_raw_signature, "(JC)V") \
- do_signature(putInt_raw_signature, "(JI)V") \
- do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \
- do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \
- do_signature(getFloat_raw_signature, "(J)F") \
- do_signature(putFloat_raw_signature, "(JF)V") \
- do_alias(getDouble_raw_signature, /*(J)D*/ long_double_signature) \
- do_signature(putDouble_raw_signature, "(JD)V") \
- do_alias(getAddress_raw_signature, /*(J)J*/ long_long_signature) \
- do_alias(putAddress_raw_signature, /*(JJ)V*/ long_long_void_signature) \
- \
- do_name( getAddress_name, "getAddress") \
- do_name( putAddress_name, "putAddress") \
- \
- do_intrinsic(_getByte_raw, jdk_internal_misc_Unsafe, getByte_name, getByte_raw_signature, F_R) \
- do_intrinsic(_getShort_raw, jdk_internal_misc_Unsafe, getShort_name, getShort_raw_signature, F_R) \
- do_intrinsic(_getChar_raw, jdk_internal_misc_Unsafe, getChar_name, getChar_raw_signature, F_R) \
- do_intrinsic(_getInt_raw, jdk_internal_misc_Unsafe, getInt_name, long_int_signature, F_R) \
- do_intrinsic(_getLong_raw, jdk_internal_misc_Unsafe, getLong_name, getLong_raw_signature, F_R) \
- do_intrinsic(_getFloat_raw, jdk_internal_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_R) \
- do_intrinsic(_getDouble_raw, jdk_internal_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_R) \
- do_intrinsic(_getAddress_raw, jdk_internal_misc_Unsafe, getAddress_name, getAddress_raw_signature, F_R) \
- do_intrinsic(_putByte_raw, jdk_internal_misc_Unsafe, putByte_name, putByte_raw_signature, F_R) \
- do_intrinsic(_putShort_raw, jdk_internal_misc_Unsafe, putShort_name, putShort_raw_signature, F_R) \
- do_intrinsic(_putChar_raw, jdk_internal_misc_Unsafe, putChar_name, putChar_raw_signature, F_R) \
- do_intrinsic(_putInt_raw, jdk_internal_misc_Unsafe, putInt_name, putInt_raw_signature, F_R) \
- do_intrinsic(_putLong_raw, jdk_internal_misc_Unsafe, putLong_name, putLong_raw_signature, F_R) \
- do_intrinsic(_putFloat_raw, jdk_internal_misc_Unsafe, putFloat_name, putFloat_raw_signature, F_R) \
- do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \
- do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \
- \
do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
--- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "gc/parallel/gcTaskManager.hpp"
#include "gc/parallel/gcTaskThread.hpp"
-#include "gc/shared/adaptiveSizePolicy.hpp"
#include "gc/shared/gcId.hpp"
+#include "gc/shared/workerManager.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
@@ -34,6 +34,7 @@
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
+#include "runtime/os.hpp"
//
// GCTask
@@ -372,10 +373,28 @@
GCTaskManager::GCTaskManager(uint workers) :
_workers(workers),
_active_workers(0),
- _idle_workers(0) {
+ _idle_workers(0),
+ _created_workers(0) {
initialize();
}
+GCTaskThread* GCTaskManager::install_worker(uint t) {
+ GCTaskThread* new_worker = GCTaskThread::create(this, t, _processor_assignment[t]);
+ set_thread(t, new_worker);
+ return new_worker;
+}
+
+void GCTaskManager::add_workers(bool initializing) {
+ os::ThreadType worker_type = os::pgc_thread;
+ _created_workers = WorkerManager::add_workers(this,
+ _active_workers,
+ (uint) _workers,
+ _created_workers,
+ worker_type,
+ initializing);
+ _active_workers = MIN2(_created_workers, _active_workers);
+}
+
void GCTaskManager::initialize() {
if (TraceGCTaskManager) {
tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
@@ -394,28 +413,30 @@
// Set up worker threads.
// Distribute the workers among the available processors,
// unless we were told not to, or if the os doesn't want to.
- uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
+ _processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
if (!BindGCTaskThreadsToCPUs ||
- !os::distribute_processes(workers(), processor_assignment)) {
+ !os::distribute_processes(workers(), _processor_assignment)) {
for (uint a = 0; a < workers(); a += 1) {
- processor_assignment[a] = sentinel_worker();
+ _processor_assignment[a] = sentinel_worker();
}
}
+
_thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
- for (uint t = 0; t < workers(); t += 1) {
- set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
+ _active_workers = ParallelGCThreads;
+ if (UseDynamicNumberOfGCThreads && !FLAG_IS_CMDLINE(ParallelGCThreads)) {
+ _active_workers = 1U;
}
+
Log(gc, task, thread) log;
if (log.is_trace()) {
ResourceMark rm;
outputStream* out = log.trace_stream();
out->print("GCTaskManager::initialize: distribution:");
for (uint t = 0; t < workers(); t += 1) {
- out->print(" %u", processor_assignment[t]);
+ out->print(" %u", _processor_assignment[t]);
}
out->cr();
}
- FREE_C_HEAP_ARRAY(uint, processor_assignment);
}
reset_busy_workers();
set_unblocked();
@@ -426,9 +447,8 @@
reset_completed_tasks();
reset_barriers();
reset_emptied_queue();
- for (uint s = 0; s < workers(); s += 1) {
- thread(s)->start();
- }
+
+ add_workers(true);
}
GCTaskManager::~GCTaskManager() {
@@ -437,13 +457,17 @@
NoopGCTask::destroy(_noop_task);
_noop_task = NULL;
if (_thread != NULL) {
- for (uint i = 0; i < workers(); i += 1) {
+ for (uint i = 0; i < created_workers(); i += 1) {
GCTaskThread::destroy(thread(i));
set_thread(i, NULL);
}
FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
_thread = NULL;
}
+ if (_processor_assignment != NULL) {
+ FREE_C_HEAP_ARRAY(uint, _processor_assignment);
+ _processor_assignment = NULL;
+ }
if (_resource_flag != NULL) {
FREE_C_HEAP_ARRAY(bool, _resource_flag);
_resource_flag = NULL;
@@ -470,6 +494,9 @@
"all_workers_active() is incorrect: "
"active %d ParallelGCThreads %u", active_workers(),
ParallelGCThreads);
+ _active_workers = MIN2(_active_workers, _workers);
+ // "add_workers" does not guarantee any additional workers
+ add_workers(false);
log_trace(gc, task)("GCTaskManager::set_active_gang(): "
"all_workers_active() %d workers %d "
"active %d ParallelGCThreads %u",
@@ -499,7 +526,7 @@
// is starting). Try later to release enough idle_workers
// to allow the desired number of active_workers.
more_inactive_workers =
- workers() - active_workers() - idle_workers();
+ created_workers() - active_workers() - idle_workers();
if (more_inactive_workers < 0) {
int reduced_active_workers = active_workers() + more_inactive_workers;
set_active_workers(reduced_active_workers);
@@ -507,7 +534,7 @@
}
log_trace(gc, task)("JT: %d workers %d active %d idle %d more %d",
Threads::number_of_non_daemon_threads(),
- workers(),
+ created_workers(),
active_workers(),
idle_workers(),
more_inactive_workers);
@@ -517,7 +544,7 @@
q->enqueue(IdleGCTask::create_on_c_heap());
increment_idle_workers();
}
- assert(workers() == active_workers() + idle_workers(),
+ assert(created_workers() == active_workers() + idle_workers(),
"total workers should equal active + inactive");
add_list(q);
// GCTaskQueue* q was created in a ResourceArea so a
@@ -539,14 +566,15 @@
if (!log_is_enabled(Debug, gc, task, time)) {
return;
}
- for(uint i=0; i<ParallelGCThreads; i++) {
+ uint num_thr = created_workers();
+ for(uint i=0; i < num_thr; i++) {
GCTaskThread* t = thread(i);
t->print_task_time_stamps();
}
}
void GCTaskManager::print_threads_on(outputStream* st) {
- uint num_thr = workers();
+ uint num_thr = created_workers();
for (uint i = 0; i < num_thr; i++) {
thread(i)->print_on(st);
st->cr();
@@ -555,19 +583,20 @@
void GCTaskManager::threads_do(ThreadClosure* tc) {
assert(tc != NULL, "Null ThreadClosure");
- uint num_thr = workers();
+ uint num_thr = created_workers();
for (uint i = 0; i < num_thr; i++) {
tc->do_thread(thread(i));
}
}
GCTaskThread* GCTaskManager::thread(uint which) {
- assert(which < workers(), "index out of bounds");
+ assert(which < created_workers(), "index out of bounds");
assert(_thread[which] != NULL, "shouldn't have null thread");
return _thread[which];
}
void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
+ // "_created_workers" may not have been updated yet so use workers()
assert(which < workers(), "index out of bounds");
assert(value != NULL, "shouldn't have null thread");
_thread[which] = value;
@@ -728,7 +757,7 @@
void GCTaskManager::release_all_resources() {
// If you want this to be done atomically, do it in a WaitForBarrierGCTask.
- for (uint i = 0; i < workers(); i += 1) {
+ for (uint i = 0; i < created_workers(); i += 1) {
set_resource_flag(i, true);
}
}
--- a/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskManager.hpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -370,6 +370,7 @@
Monitor* _monitor; // Notification of changes.
SynchronizedGCTaskQueue* _queue; // Queue of tasks.
GCTaskThread** _thread; // Array of worker threads.
+ uint _created_workers; // Number of workers created.
uint _active_workers; // Number of active workers.
uint _busy_workers; // Number of busy workers.
uint _blocking_worker; // The worker that's blocking.
@@ -381,6 +382,8 @@
NoopGCTask* _noop_task; // The NoopGCTask instance.
WaitHelper _wait_helper; // Used by inactive worker
volatile uint _idle_workers; // Number of idled workers
+ uint* _processor_assignment; // Worker to cpu mappings. May
+ // be used lazily
public:
// Factory create and destroy methods.
static GCTaskManager* create(uint workers) {
@@ -546,6 +549,13 @@
uint active_workers() const {
return _active_workers;
}
+ uint created_workers() const {
+ return _created_workers;
+ }
+ // Create a GC worker and install into GCTaskManager
+ GCTaskThread* install_worker(uint worker_id);
+ // Add GC workers as needed.
+ void add_workers(bool initializing);
};
//
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.cpp Mon May 09 13:13:07 2016 +0300
@@ -44,9 +44,6 @@
_time_stamps(NULL),
_time_stamp_index(0)
{
- if (!os::create_thread(this, os::pgc_thread))
- vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GC thread. Out of system resources.");
-
set_id(which);
set_name("ParGC Thread#%d", which);
}
@@ -57,10 +54,6 @@
}
}
-void GCTaskThread::start() {
- os::start_thread(this);
-}
-
GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) {
guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries");
if (_time_stamps == NULL) {
--- a/hotspot/src/share/vm/gc/parallel/gcTaskThread.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/parallel/gcTaskThread.hpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -48,13 +48,13 @@
bool _is_working; // True if participating in GC tasks
- public:
// Factory create and destroy methods.
static GCTaskThread* create(GCTaskManager* manager,
uint which,
uint processor_id) {
return new GCTaskThread(manager, which, processor_id);
}
+ public:
static void destroy(GCTaskThread* manager) {
if (manager != NULL) {
delete manager;
@@ -65,8 +65,6 @@
return true;
}
virtual void run();
- // Methods.
- void start();
void print_task_time_stamps();
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -130,10 +130,7 @@
uintx max_active_workers =
MAX2(active_workers_by_JT, active_workers_by_heap_size);
- // Limit the number of workers to the the number created,
- // (workers()).
- new_active_workers = MIN2(max_active_workers,
- (uintx) total_workers);
+ new_active_workers = MIN2(max_active_workers, (uintx) total_workers);
// Increase GC workers instantly but decrease them more
// slowly.
@@ -167,7 +164,7 @@
"Jiggled active workers too much");
}
- log_trace(gc, task)("GCTaskManager::calc_default_active_workers() : "
+ log_trace(gc, task)("GCTaskManager::calc_default_active_workers() : "
"active_workers(): " UINTX_FORMAT " new_active_workers: " UINTX_FORMAT " "
"prev_active_workers: " UINTX_FORMAT "\n"
" active_workers_by_JT: " UINTX_FORMAT " active_workers_by_heap_size: " UINTX_FORMAT,
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.hpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/workerManager.hpp Mon May 09 13:13:07 2016 +0300
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
+#define SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
+
+#include "gc/shared/adaptiveSizePolicy.hpp"
+
+class WorkerManager : public AllStatic {
+ public:
+ // Create additional workers as needed.
+ // active_workers - number of workers being requested for an upcoming
+ // parallel task.
+ // total_workers - total number of workers. This is the maximum
+ // number possible.
+ // created_workers - number of workers already created. This maybe
+ // less than, equal to, or greater than active workers. If greater than
+ // or equal to active_workers, nothing is done.
+ // worker_type - type of thread.
+ // initializing - true if this is called to get the initial number of
+ // GC workers.
+ // If initializing is true, do a vm exit if the workers cannot be created.
+ // The initializing = true case is for JVM start up and failing to
+ // create all the worker at start should considered a problem so exit.
+ // If initializing = false, there are already some number of worker
+ // threads and a failure would not be optimal but should not be fatal.
+ template <class WorkerType>
+ static uint add_workers (WorkerType* holder,
+ uint active_workers,
+ uint total_workers,
+ uint created_workers,
+ os::ThreadType worker_type,
+ bool initializing) {
+ uint start = created_workers;
+ uint end = MIN2(active_workers, total_workers);
+ for (uint worker_id = start; worker_id < end; worker_id += 1) {
+ WorkerThread* new_worker = holder->install_worker(worker_id);
+ assert(new_worker != NULL, "Failed to allocate GangWorker");
+ if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
+ if(initializing) {
+ vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
+ "Cannot create worker GC thread. Out of system resources.");
+ }
+ }
+ created_workers++;
+ os::start_thread(new_worker);
+ }
+
+ log_trace(gc, task)("AdaptiveSizePolicy::add_workers() : "
+ "active_workers: %u created_workers: %u",
+ active_workers, created_workers);
+
+ return created_workers;
+ }
+};
+#endif // SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp Mon May 09 13:13:07 2016 +0300
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/workgroup.hpp"
+#include "gc/shared/workerManager.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/atomic.inline.hpp"
@@ -35,37 +36,45 @@
// Definitions of WorkGang methods.
// The current implementation will exit if the allocation
-// of any worker fails. Still, return a boolean so that
-// a future implementation can possibly do a partial
-// initialization of the workers and report such to the
-// caller.
-bool AbstractWorkGang::initialize_workers() {
+// of any worker fails.
+void AbstractWorkGang::initialize_workers() {
log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
_workers = NEW_C_HEAP_ARRAY(AbstractGangWorker*, total_workers(), mtInternal);
if (_workers == NULL) {
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array.");
- return false;
+ }
+
+ _active_workers = ParallelGCThreads;
+ if (UseDynamicNumberOfGCThreads && !FLAG_IS_CMDLINE(ParallelGCThreads)) {
+ _active_workers = 1U;
}
+
+ add_workers(true);
+}
+
+
+AbstractGangWorker* AbstractWorkGang::install_worker(uint worker_id) {
+ AbstractGangWorker* new_worker = allocate_worker(worker_id);
+ set_thread(worker_id, new_worker);
+ return new_worker;
+}
+
+void AbstractWorkGang::add_workers(bool initializing) {
+
os::ThreadType worker_type;
if (are_ConcurrentGC_threads()) {
worker_type = os::cgc_thread;
} else {
worker_type = os::pgc_thread;
}
- for (uint worker = 0; worker < total_workers(); worker += 1) {
- AbstractGangWorker* new_worker = allocate_worker(worker);
- assert(new_worker != NULL, "Failed to allocate GangWorker");
- _workers[worker] = new_worker;
- if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
- vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
- "Cannot create worker GC thread. Out of system resources.");
- return false;
- }
- if (!DisableStartThread) {
- os::start_thread(new_worker);
- }
- }
- return true;
+
+ _created_workers = WorkerManager::add_workers(this,
+ _active_workers,
+ _total_workers,
+ _created_workers,
+ worker_type,
+ initializing);
+ _active_workers = MIN2(_created_workers, _active_workers);
}
AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
@@ -79,7 +88,7 @@
}
void AbstractWorkGang::print_worker_threads_on(outputStream* st) const {
- uint workers = total_workers();
+ uint workers = created_workers();
for (uint i = 0; i < workers; i++) {
worker(i)->print_on(st);
st->cr();
@@ -88,7 +97,7 @@
void AbstractWorkGang::threads_do(ThreadClosure* tc) const {
assert(tc != NULL, "Null ThreadClosure");
- uint workers = total_workers();
+ uint workers = created_workers();
for (uint i = 0; i < workers; i++) {
tc->do_thread(worker(i));
}
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp Mon May 09 13:13:07 2016 +0300
@@ -112,6 +112,8 @@
uint _total_workers;
// The currently active workers in this gang.
uint _active_workers;
+ // The count of created workers in the gang.
+ uint _created_workers;
// Printing support.
const char* _name;
@@ -120,23 +122,32 @@
const bool _are_GC_task_threads;
const bool _are_ConcurrentGC_threads;
+ void set_thread(uint worker_id, AbstractGangWorker* worker) {
+ _workers[worker_id] = worker;
+ }
+
public:
AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
_name(name),
_total_workers(workers),
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
+ _created_workers(0),
_are_GC_task_threads(are_GC_task_threads),
_are_ConcurrentGC_threads(are_ConcurrentGC_threads)
{ }
// Initialize workers in the gang. Return true if initialization succeeded.
- bool initialize_workers();
+ void initialize_workers();
bool are_GC_task_threads() const { return _are_GC_task_threads; }
bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
uint total_workers() const { return _total_workers; }
+ uint created_workers() const {
+ return _created_workers;
+ }
+
virtual uint active_workers() const {
assert(_active_workers <= _total_workers,
"_active_workers: %u > _total_workers: %u", _active_workers, _total_workers);
@@ -144,22 +155,29 @@
"Unless dynamic should use total workers");
return _active_workers;
}
+
void set_active_workers(uint v) {
assert(v <= _total_workers,
"Trying to set more workers active than there are");
_active_workers = MIN2(v, _total_workers);
+ add_workers(false /* exit_on_failure */);
assert(v != 0, "Trying to set active workers to 0");
- _active_workers = MAX2(1U, _active_workers);
assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
"Unless dynamic should use total workers");
log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
}
+ // Add GC workers as needed.
+ void add_workers(bool initializing);
+
// Return the Ith worker.
AbstractGangWorker* worker(uint i) const;
void threads_do(ThreadClosure* tc) const;
+ // Create a GC worker and install it into the work gang.
+ virtual AbstractGangWorker* install_worker(uint which);
+
// Debugging.
const char* name() const { return _name; }
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Mon May 09 13:13:07 2016 +0300
@@ -409,22 +409,6 @@
case vmIntrinsics::_putLong:
case vmIntrinsics::_putFloat:
case vmIntrinsics::_putDouble:
- case vmIntrinsics::_getByte_raw:
- case vmIntrinsics::_getShort_raw:
- case vmIntrinsics::_getChar_raw:
- case vmIntrinsics::_getInt_raw:
- case vmIntrinsics::_getLong_raw:
- case vmIntrinsics::_getFloat_raw:
- case vmIntrinsics::_getDouble_raw:
- case vmIntrinsics::_getAddress_raw:
- case vmIntrinsics::_putByte_raw:
- case vmIntrinsics::_putShort_raw:
- case vmIntrinsics::_putChar_raw:
- case vmIntrinsics::_putInt_raw:
- case vmIntrinsics::_putLong_raw:
- case vmIntrinsics::_putFloat_raw:
- case vmIntrinsics::_putDouble_raw:
- case vmIntrinsics::_putAddress_raw:
case vmIntrinsics::_getObjectVolatile:
case vmIntrinsics::_getBooleanVolatile:
case vmIntrinsics::_getByteVolatile:
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon May 09 13:13:07 2016 +0300
@@ -93,7 +93,7 @@
Node* _result; // the result node, if any
int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted
- const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false);
+ const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type);
public:
LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic)
@@ -247,7 +247,7 @@
void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar);
typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind;
- bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
+ bool inline_unsafe_access(bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
static bool klass_needs_init_guard(Node* kls);
bool inline_unsafe_allocate();
bool inline_unsafe_newArray(bool uninitialized);
@@ -475,7 +475,6 @@
// Handle symbolic names for otherwise undistinguished boolean switches:
const bool is_store = true;
const bool is_compress = true;
- const bool is_native_ptr = true;
const bool is_static = true;
const bool is_volatile = true;
@@ -555,113 +554,95 @@
case vmIntrinsics::_inflateStringC:
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
- case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Relaxed, false);
- case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Relaxed, false);
- case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Relaxed, false);
- case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, false);
- case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, false);
- case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, false);
- case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, false);
- case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
- case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
-
- case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false);
- case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false);
- case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false);
- case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false);
- case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false);
- case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false);
- case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false);
- case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Relaxed, false);
- case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
-
- case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, Relaxed, false);
- case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, Relaxed, false);
- case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, Relaxed, false);
- case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, Relaxed, false);
- case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, Relaxed, false);
- case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
- case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
- case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, Relaxed, false);
-
- case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false);
- case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false);
- case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false);
- case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false);
- case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false);
- case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false);
- case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
- case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, false);
-
- case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Volatile, false);
- case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Volatile, false);
- case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Volatile, false);
- case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Volatile, false);
- case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Volatile, false);
- case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Volatile, false);
- case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Volatile, false);
- case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Volatile, false);
- case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Volatile, false);
-
- case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false);
- case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false);
- case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false);
- case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Volatile, false);
- case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Volatile, false);
- case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Volatile, false);
- case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Volatile, false);
- case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Volatile, false);
- case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Volatile, false);
-
- case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, true);
- case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, true);
- case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, true);
- case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true);
-
- case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true);
- case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true);
- case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, true);
- case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, true);
-
- case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false);
- case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false);
- case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false);
- case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false);
- case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Acquire, false);
- case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Acquire, false);
- case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Acquire, false);
- case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Acquire, false);
- case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Acquire, false);
-
- case vmIntrinsics::_putObjectRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
- case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Release, false);
- case vmIntrinsics::_putByteRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Release, false);
- case vmIntrinsics::_putShortRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Release, false);
- case vmIntrinsics::_putCharRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Release, false);
- case vmIntrinsics::_putIntRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
- case vmIntrinsics::_putLongRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
- case vmIntrinsics::_putFloatRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Release, false);
- case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Release, false);
-
- case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Opaque, false);
- case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Opaque, false);
- case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Opaque, false);
- case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Opaque, false);
- case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Opaque, false);
- case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Opaque, false);
- case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Opaque, false);
- case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Opaque, false);
- case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Opaque, false);
-
- case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Opaque, false);
- case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Opaque, false);
- case vmIntrinsics::_putByteOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Opaque, false);
- case vmIntrinsics::_putShortOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Opaque, false);
- case vmIntrinsics::_putCharOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Opaque, false);
- case vmIntrinsics::_putIntOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Opaque, false);
- case vmIntrinsics::_putLongOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Opaque, false);
- case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Opaque, false);
- case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Opaque, false);
+ case vmIntrinsics::_getObject: return inline_unsafe_access(!is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_getByte: return inline_unsafe_access(!is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_getShort: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_getChar: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_getInt: return inline_unsafe_access(!is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_getLong: return inline_unsafe_access(!is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_putObject: return inline_unsafe_access( is_store, T_OBJECT, Relaxed, false);
+ case vmIntrinsics::_putBoolean: return inline_unsafe_access( is_store, T_BOOLEAN, Relaxed, false);
+ case vmIntrinsics::_putByte: return inline_unsafe_access( is_store, T_BYTE, Relaxed, false);
+ case vmIntrinsics::_putShort: return inline_unsafe_access( is_store, T_SHORT, Relaxed, false);
+ case vmIntrinsics::_putChar: return inline_unsafe_access( is_store, T_CHAR, Relaxed, false);
+ case vmIntrinsics::_putInt: return inline_unsafe_access( is_store, T_INT, Relaxed, false);
+ case vmIntrinsics::_putLong: return inline_unsafe_access( is_store, T_LONG, Relaxed, false);
+ case vmIntrinsics::_putFloat: return inline_unsafe_access( is_store, T_FLOAT, Relaxed, false);
+ case vmIntrinsics::_putDouble: return inline_unsafe_access( is_store, T_DOUBLE, Relaxed, false);
+
+ case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access( is_store, T_OBJECT, Volatile, false);
+ case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access( is_store, T_BOOLEAN, Volatile, false);
+ case vmIntrinsics::_putByteVolatile: return inline_unsafe_access( is_store, T_BYTE, Volatile, false);
+ case vmIntrinsics::_putShortVolatile: return inline_unsafe_access( is_store, T_SHORT, Volatile, false);
+ case vmIntrinsics::_putCharVolatile: return inline_unsafe_access( is_store, T_CHAR, Volatile, false);
+ case vmIntrinsics::_putIntVolatile: return inline_unsafe_access( is_store, T_INT, Volatile, false);
+ case vmIntrinsics::_putLongVolatile: return inline_unsafe_access( is_store, T_LONG, Volatile, false);
+ case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access( is_store, T_FLOAT, Volatile, false);
+ case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access( is_store, T_DOUBLE, Volatile, false);
+
+ case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access( is_store, T_SHORT, Relaxed, true);
+ case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access( is_store, T_CHAR, Relaxed, true);
+ case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access( is_store, T_INT, Relaxed, true);
+ case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access( is_store, T_LONG, Relaxed, true);
+
+ case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_store, T_OBJECT, Acquire, false);
+ case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_store, T_BOOLEAN, Acquire, false);
+ case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_store, T_BYTE, Acquire, false);
+ case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_store, T_SHORT, Acquire, false);
+ case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_store, T_CHAR, Acquire, false);
+ case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_store, T_INT, Acquire, false);
+ case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_store, T_LONG, Acquire, false);
+ case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_store, T_FLOAT, Acquire, false);
+ case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_store, T_DOUBLE, Acquire, false);
+
+ case vmIntrinsics::_putObjectRelease: return inline_unsafe_access( is_store, T_OBJECT, Release, false);
+ case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access( is_store, T_BOOLEAN, Release, false);
+ case vmIntrinsics::_putByteRelease: return inline_unsafe_access( is_store, T_BYTE, Release, false);
+ case vmIntrinsics::_putShortRelease: return inline_unsafe_access( is_store, T_SHORT, Release, false);
+ case vmIntrinsics::_putCharRelease: return inline_unsafe_access( is_store, T_CHAR, Release, false);
+ case vmIntrinsics::_putIntRelease: return inline_unsafe_access( is_store, T_INT, Release, false);
+ case vmIntrinsics::_putLongRelease: return inline_unsafe_access( is_store, T_LONG, Release, false);
+ case vmIntrinsics::_putFloatRelease: return inline_unsafe_access( is_store, T_FLOAT, Release, false);
+ case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access( is_store, T_DOUBLE, Release, false);
+
+ case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_store, T_DOUBLE, Opaque, false);
+
+ case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access( is_store, T_OBJECT, Opaque, false);
+ case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access( is_store, T_BOOLEAN, Opaque, false);
+ case vmIntrinsics::_putByteOpaque: return inline_unsafe_access( is_store, T_BYTE, Opaque, false);
+ case vmIntrinsics::_putShortOpaque: return inline_unsafe_access( is_store, T_SHORT, Opaque, false);
+ case vmIntrinsics::_putCharOpaque: return inline_unsafe_access( is_store, T_CHAR, Opaque, false);
+ case vmIntrinsics::_putIntOpaque: return inline_unsafe_access( is_store, T_INT, Opaque, false);
+ case vmIntrinsics::_putLongOpaque: return inline_unsafe_access( is_store, T_LONG, Opaque, false);
+ case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access( is_store, T_FLOAT, Opaque, false);
+ case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access( is_store, T_DOUBLE, Opaque, false);
case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile);
case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile);
@@ -2196,8 +2177,6 @@
//----------------------------inline_unsafe_access----------------------------
-const static BasicType T_ADDRESS_HOLDER = T_LONG;
-
// Helper that guards and inserts a pre-barrier.
void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
Node* pre_val, bool need_mem_bar) {
@@ -2298,13 +2277,12 @@
}
-const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) {
+const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type) {
// Attempt to infer a sharper value type from the offset and base type.
ciKlass* sharpened_klass = NULL;
// See if it is an instance field, with an object type.
if (alias_type->field() != NULL) {
- assert(!is_native_ptr, "native pointer op cannot use a java address");
if (alias_type->field()->type()->is_klass()) {
sharpened_klass = alias_type->field()->type()->as_klass();
}
@@ -2337,7 +2315,7 @@
return NULL;
}
-bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
+bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
if (callee()->is_static()) return false; // caller must have the capability!
guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads");
guarantee( is_store || kind != Release, "Release accesses can be produced only for stores");
@@ -2352,31 +2330,17 @@
if (!is_store) {
// Object getObject(Object base, int/long offset), etc.
BasicType rtype = sig->return_type()->basic_type();
- if (rtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::getAddress_name())
- rtype = T_ADDRESS; // it is really a C void*
assert(rtype == type, "getter must return the expected value");
- if (!is_native_ptr) {
- assert(sig->count() == 2, "oop getter has 2 arguments");
- assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object");
- assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct");
- } else {
- assert(sig->count() == 1, "native getter has 1 argument");
- assert(sig->type_at(0)->basic_type() == T_LONG, "getter base is long");
- }
+ assert(sig->count() == 2, "oop getter has 2 arguments");
+ assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object");
+ assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct");
} else {
// void putObject(Object base, int/long offset, Object x), etc.
assert(sig->return_type()->basic_type() == T_VOID, "putter must not return a value");
- if (!is_native_ptr) {
- assert(sig->count() == 3, "oop putter has 3 arguments");
- assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object");
- assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct");
- } else {
- assert(sig->count() == 2, "native putter has 2 arguments");
- assert(sig->type_at(0)->basic_type() == T_LONG, "putter base is long");
- }
+ assert(sig->count() == 3, "oop putter has 3 arguments");
+ assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object");
+ assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct");
BasicType vtype = sig->type_at(sig->count()-1)->basic_type();
- if (vtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::putAddress_name())
- vtype = T_ADDRESS; // it is really a C void*
assert(vtype == type, "putter must accept the expected value");
}
#endif // ASSERT
@@ -2393,27 +2357,22 @@
Node* offset = top();
Node* val;
- if (!is_native_ptr) {
- // The base is either a Java object or a value produced by Unsafe.staticFieldBase
- Node* base = argument(1); // type: oop
- // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset
- offset = argument(2); // type: long
- // We currently rely on the cookies produced by Unsafe.xxxFieldOffset
- // to be plain byte offsets, which are also the same as those accepted
- // by oopDesc::field_base.
- assert(Unsafe_field_offset_to_byte_offset(11) == 11,
- "fieldOffset must be byte-scaled");
- // 32-bit machines ignore the high half!
- offset = ConvL2X(offset);
- adr = make_unsafe_address(base, offset);
+ // The base is either a Java object or a value produced by Unsafe.staticFieldBase
+ Node* base = argument(1); // type: oop
+ // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset
+ offset = argument(2); // type: long
+ // We currently rely on the cookies produced by Unsafe.xxxFieldOffset
+ // to be plain byte offsets, which are also the same as those accepted
+ // by oopDesc::field_base.
+ assert(Unsafe_field_offset_to_byte_offset(11) == 11,
+ "fieldOffset must be byte-scaled");
+ // 32-bit machines ignore the high half!
+ offset = ConvL2X(offset);
+ adr = make_unsafe_address(base, offset);
+ if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
heap_base_oop = base;
- val = is_store ? argument(4) : NULL;
- } else {
- Node* ptr = argument(1); // type: long
- ptr = ConvL2X(ptr); // adjust Java long to machine word
- adr = make_unsafe_address(NULL, ptr);
- val = is_store ? argument(3) : NULL;
- }
+ }
+ val = is_store ? argument(4) : NULL;
const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
@@ -2494,11 +2453,11 @@
// SATB log buffer using the pre-barrier mechanism.
// Also we need to add memory barrier to prevent commoning reads
// from this field across safepoint since GC can change its value.
- bool need_read_barrier = !is_native_ptr && !is_store &&
+ bool need_read_barrier = !is_store &&
offset != top() && heap_base_oop != top();
if (!is_store && type == T_OBJECT) {
- const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type, is_native_ptr);
+ const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
if (tjp != NULL) {
value_type = tjp;
}
--- a/hotspot/src/share/vm/prims/stackwalk.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/prims/stackwalk.cpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 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
@@ -37,44 +37,44 @@
#include "utilities/globalDefinitions.hpp"
// setup and cleanup actions
-void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) {
+void JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
frames_array->obj_at_put(magic_pos, _thread->threadObj());
_anchor = address_value();
assert(check_magic(frames_array), "invalid magic");
}
-bool StackWalkAnchor::check_magic(objArrayHandle frames_array) {
+bool JavaFrameStream::check_magic(objArrayHandle frames_array) {
oop m1 = frames_array->obj_at(magic_pos);
jlong m2 = _anchor;
if (m1 == _thread->threadObj() && m2 == address_value()) return true;
return false;
}
-bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) {
+bool JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
bool ok = check_magic(frames_array);
frames_array->obj_at_put(magic_pos, NULL);
_anchor = 0L;
return ok;
}
-// Returns StackWalkAnchor for the current stack being traversed.
+// Returns JavaFrameStream for the current stack being traversed.
//
// Parameters:
// thread Current Java thread.
// magic Magic value used for each stack walking
// frames_array User-supplied buffers. The 0th element is reserved
-// to this StackWalkAnchor to use
+// to this JavaFrameStream to use
//
-StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
+JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
objArrayHandle frames_array)
{
assert(thread != NULL && thread->is_Java_thread(), "");
oop m1 = frames_array->obj_at(magic_pos);
if (m1 != thread->threadObj()) return NULL;
if (magic == 0L) return NULL;
- StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic;
- if (!anchor->is_valid_in(thread, frames_array)) return NULL;
- return anchor;
+ JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic;
+ if (!stream->is_valid_in(thread, frames_array)) return NULL;
+ return stream;
}
// Unpacks one or more frames into user-supplied buffers.
@@ -84,19 +84,19 @@
// In other words, do not leave any stale data in the vfst.
//
// Parameters:
-// mode Restrict which frames to be decoded.
-// vfst vFrameStream.
-// max_nframes Maximum number of frames to be filled.
-// start_index Start index to the user-supplied buffers.
-// frames_array Buffer to store Class or StackFrame in, starting at start_index.
-// frames array is a Class<?>[] array when only getting caller
-// reference, and a StackFrameInfo[] array (or derivative)
-// otherwise. It should never be null.
-// end_index End index to the user-supplied buffers with unpacked frames.
+// mode Restrict which frames to be decoded.
+// JavaFrameStream stream of javaVFrames
+// max_nframes Maximum number of frames to be filled.
+// start_index Start index to the user-supplied buffers.
+// frames_array Buffer to store Class or StackFrame in, starting at start_index.
+// frames array is a Class<?>[] array when only getting caller
+// reference, and a StackFrameInfo[] array (or derivative)
+// otherwise. It should never be null.
+// end_index End index to the user-supplied buffers with unpacked frames.
//
// Returns the number of frames whose information was transferred into the buffers.
//
-int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
+int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
int max_nframes, int start_index,
objArrayHandle frames_array,
int& end_index, TRAPS) {
@@ -108,9 +108,9 @@
assert(start_index + max_nframes <= frames_array->length(), "oob");
int frames_decoded = 0;
- for (; !vfst.at_end(); vfst.next()) {
- Method* method = vfst.method();
- int bci = vfst.bci();
+ for (; !stream.at_end(); stream.next()) {
+ Method* method = stream.method();
+ int bci = stream.bci();
if (method == NULL) continue;
if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
@@ -133,7 +133,7 @@
if (live_frame_info(mode)) {
assert (use_frames_array(mode), "Bad mode for get live frame");
Handle stackFrame(frames_array->obj_at(index));
- fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0);
+ fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0);
} else if (need_method_info(mode)) {
assert (use_frames_array(mode), "Bad mode for get stack frame");
Handle stackFrame(frames_array->obj_at(index));
@@ -294,6 +294,7 @@
int skip_frames, int frame_count, int start_index,
objArrayHandle frames_array,
TRAPS) {
+ ResourceMark rm(THREAD);
JavaThread* jt = (JavaThread*)THREAD;
if (TraceStackWalk) {
tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
@@ -309,41 +310,39 @@
methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
- // Open up a traversable stream onto my stack.
- // This stream will be made available by *reference* to the inner Java call.
- StackWalkAnchor anchor(jt);
- vframeStream& vfst = anchor.vframe_stream();
-
+ // Setup traversal onto my stack.
+ RegisterMap regMap(jt, true);
+ JavaFrameStream stream(jt, ®Map);
{
- while (!vfst.at_end()) {
- InstanceKlass* ik = vfst.method()->method_holder();
+ while (!stream.at_end()) {
+ InstanceKlass* ik = stream.method()->method_holder();
if (ik != stackWalker_klass &&
ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
break;
}
if (TraceStackWalk) {
- tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n");
+ tty->print(" skip "); stream.method()->print_short_name(); tty->print("\n");
}
- vfst.next();
+ stream.next();
}
// stack frame has been traversed individually and resume stack walk
// from the stack frame at depth == skip_frames.
- for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) {
+ for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
if (TraceStackWalk) {
- tty->print(" skip "); vfst.method()->print_short_name();
+ tty->print(" skip "); stream.method()->print_short_name();
tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
- p2i(vfst.frame_id()), p2i(vfst.frame_pc()));
+ p2i(stream.java_frame()->fr().id()),
+ p2i(stream.java_frame()->fr().pc()));
}
}
}
- // The Method* pointer in the vfst has a very short shelf life. Grab it now.
int end_index = start_index;
int numFrames = 0;
- if (!vfst.at_end()) {
- numFrames = fill_in_frames(mode, vfst, frame_count, start_index,
+ if (!stream.at_end()) {
+ numFrames = fill_in_frames(mode, stream, frame_count, start_index,
frames_array, end_index, CHECK_NULL);
if (numFrames < 1) {
THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
@@ -356,19 +355,19 @@
// When JVM_CallStackWalk returns, it invalidates the stack stream.
JavaValue result(T_OBJECT);
JavaCallArguments args(stackStream);
- args.push_long(anchor.address_value());
+ args.push_long(stream.address_value());
args.push_int(skip_frames);
args.push_int(frame_count);
args.push_int(start_index);
args.push_int(end_index);
// Link the thread and vframe stream into the callee-visible object
- anchor.setup_magic_on_entry(frames_array);
+ stream.setup_magic_on_entry(frames_array);
JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
// Do this before anything else happens, to disable any lingering stream objects
- bool ok = anchor.cleanup_magic_on_exit(frames_array);
+ bool ok = stream.cleanup_magic_on_exit(frames_array);
// Throw pending exception if we must
(void) (CHECK_NULL);
@@ -379,7 +378,6 @@
// Return normally
return (oop)result.get_jobject();
-
}
// Walk the next batch of stack frames
@@ -400,8 +398,8 @@
TRAPS)
{
JavaThread* jt = (JavaThread*)THREAD;
- StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array);
- if (existing_anchor == NULL) {
+ JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
+ if (existing_stream == NULL) {
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
}
@@ -410,8 +408,8 @@
}
if (TraceStackWalk) {
- tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
- frame_count, p2i(existing_anchor), start_index, frames_array->length());
+ tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
+ frame_count, p2i(existing_stream), start_index, frames_array->length());
}
int end_index = start_index;
if (frame_count <= 0) {
@@ -421,12 +419,11 @@
int count = frame_count + start_index;
assert (frames_array->length() >= count, "not enough space in buffers");
- StackWalkAnchor& anchor = (*existing_anchor);
- vframeStream& vfst = anchor.vframe_stream();
- if (!vfst.at_end()) {
- vfst.next(); // this was the last frame decoded in the previous batch
- if (!vfst.at_end()) {
- int n = fill_in_frames(mode, vfst, frame_count, start_index,
+ JavaFrameStream& stream = (*existing_stream);
+ if (!stream.at_end()) {
+ stream.next(); // advance past the last frame decoded in previous batch
+ if (!stream.at_end()) {
+ int n = fill_in_frames(mode, stream, frame_count, start_index,
frames_array, end_index, CHECK_0);
if (n < 1) {
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
--- a/hotspot/src/share/vm/prims/stackwalk.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/prims/stackwalk.hpp Mon May 09 13:13:07 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 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
@@ -29,21 +29,31 @@
#include "oops/oop.hpp"
#include "runtime/vframe.hpp"
-class StackWalkAnchor : public StackObj {
+//
+// JavaFrameStream is used by StackWalker to iterate through Java stack frames
+// on the given JavaThread.
+//
+class JavaFrameStream : public StackObj {
private:
enum {
magic_pos = 0
};
JavaThread* _thread;
- vframeStream _vfst;
+ javaVFrame* _jvf;
jlong _anchor;
public:
- StackWalkAnchor(JavaThread* thread)
- : _thread(thread), _vfst(thread), _anchor(0L) {}
+ JavaFrameStream(JavaThread* thread, RegisterMap* rm)
+ : _thread(thread), _anchor(0L) {
+ _jvf = _thread->last_java_vframe(rm);
+ }
- vframeStream& vframe_stream() { return _vfst; }
- JavaThread* thread() { return _thread; }
+ javaVFrame* java_frame() { return _jvf; }
+ void next() { _jvf = _jvf->java_sender(); }
+ bool at_end() { return _jvf == NULL; }
+
+ Method* method() { return _jvf->method(); }
+ int bci() { return _jvf->bci(); }
void setup_magic_on_entry(objArrayHandle frames_array);
bool check_magic(objArrayHandle frames_array);
@@ -57,12 +67,12 @@
return (jlong) castable_address(this);
}
- static StackWalkAnchor* from_current(JavaThread* thread, jlong anchor, objArrayHandle frames_array);
+ static JavaFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array);
};
class StackWalk : public AllStatic {
private:
- static int fill_in_frames(jlong mode, vframeStream& vfst,
+ static int fill_in_frames(jlong mode, JavaFrameStream& stream,
int max_nframes, int start_index,
objArrayHandle frames_array,
int& end_index, TRAPS);
--- a/hotspot/src/share/vm/prims/unsafe.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Mon May 09 13:13:07 2016 +0300
@@ -131,38 +131,137 @@
}
-///// Data in the Java heap.
+///// Data read/writes on the Java heap and in native (off-heap) memory
+
+/**
+ * Helper class for accessing memory.
+ *
+ * Normalizes values and wraps accesses in
+ * JavaThread::doing_unsafe_access() if needed.
+ */
+class MemoryAccess : StackObj {
+ JavaThread* _thread;
+ jobject _obj;
+ jlong _offset;
-#define truncate_jboolean(x) ((x) & 1)
-#define truncate_jbyte(x) (x)
-#define truncate_jshort(x) (x)
-#define truncate_jchar(x) (x)
-#define truncate_jint(x) (x)
-#define truncate_jlong(x) (x)
-#define truncate_jfloat(x) (x)
-#define truncate_jdouble(x) (x)
+ // Resolves and returns the address of the memory access
+ void* addr() {
+ return index_oop_from_field_offset_long(JNIHandles::resolve(_obj), _offset);
+ }
+
+ template <typename T>
+ T normalize(T x) {
+ return x;
+ }
-#define GET_FIELD(obj, offset, type_name, v) \
- oop p = JNIHandles::resolve(obj); \
- type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
+ jboolean normalize(jboolean x) {
+ return x & 1;
+ }
+
+ /**
+ * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
+ */
+ class GuardUnsafeAccess {
+ JavaThread* _thread;
+ bool _active;
-#define SET_FIELD(obj, offset, type_name, x) \
- oop p = JNIHandles::resolve(obj); \
- *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x)
+ public:
+ GuardUnsafeAccess(JavaThread* thread, jobject _obj) : _thread(thread) {
+ if (JNIHandles::resolve(_obj) == NULL) {
+ // native/off-heap access which may raise SIGBUS if accessing
+ // memory mapped file data in a region of the file which has
+ // been truncated and is now invalid
+ _thread->set_doing_unsafe_access(true);
+ _active = true;
+ } else {
+ _active = false;
+ }
+ }
+
+ ~GuardUnsafeAccess() {
+ if (_active) {
+ _thread->set_doing_unsafe_access(false);
+ }
+ }
+ };
-#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
- oop p = JNIHandles::resolve(obj); \
- if (support_IRIW_for_not_multiple_copy_atomic_cpu) { \
- OrderAccess::fence(); \
- } \
- volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
+public:
+ MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
+ : _thread(thread), _obj(obj), _offset(offset) {
+ }
+
+ template <typename T>
+ T get() {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ T* p = (T*)addr();
-#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
- oop p = JNIHandles::resolve(obj); \
- OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x));
+ T x = *p;
+
+ return x;
+ }
+
+ template <typename T>
+ void put(T x) {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ T* p = (T*)addr();
+
+ *p = normalize(x);
+ }
-// Get/SetObject must be special-cased, since it works with handles.
+ template <typename T>
+ T get_volatile() {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ T* p = (T*)addr();
+
+ if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+ OrderAccess::fence();
+ }
+
+ T x = OrderAccess::load_acquire((volatile T*)p);
+
+ return x;
+ }
+
+ template <typename T>
+ void put_volatile(T x) {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ T* p = (T*)addr();
+
+ OrderAccess::release_store_fence((volatile T*)p, normalize(x));
+ }
+
+
+#ifndef SUPPORTS_NATIVE_CX8
+ jlong get_jlong_locked() {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+
+ jlong* p = (jlong*)addr();
+
+ jlong x = Atomic::load(p);
+
+ return x;
+ }
+
+ void put_jlong_locked(jlong x) {
+ GuardUnsafeAccess guard(_thread, _obj);
+
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+
+ jlong* p = (jlong*)addr();
+
+ Atomic::store(normalize(x), p);
+ }
+#endif
+};
+
+// Get/PutObject must be special-cased, since it works with handles.
// These functions allow a null base pointer with an arbitrary address.
// But if the base pointer is non-null, the offset should make some sense.
@@ -208,7 +307,7 @@
return ret;
} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
+UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
@@ -236,7 +335,7 @@
return JNIHandles::make_local(env, v);
} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
+UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
@@ -301,25 +400,17 @@
UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
if (VM_Version::supports_cx8()) {
- GET_FIELD_VOLATILE(obj, offset, jlong, v);
- return v;
+ return MemoryAccess(thread, obj, offset).get_volatile<jlong>();
} else {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
- MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
- jlong value = Atomic::load(addr);
- return value;
+ return MemoryAccess(thread, obj, offset).get_jlong_locked();
}
} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
+UNSAFE_ENTRY(void, Unsafe_PutLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
if (VM_Version::supports_cx8()) {
- SET_FIELD_VOLATILE(obj, offset, jlong, x);
+ MemoryAccess(thread, obj, offset).put_volatile<jlong>(x);
} else {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
- MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
- Atomic::store(x, addr);
+ MemoryAccess(thread, obj, offset).put_jlong_locked(x);
}
} UNSAFE_END
@@ -337,15 +428,14 @@
return UseUnalignedAccesses;
} UNSAFE_END
-#define DEFINE_GETSETOOP(java_type, Type) \
+#define DEFINE_GETSETOOP(java_type, Type) \
\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
- GET_FIELD(obj, offset, java_type, v); \
- return v; \
+ return MemoryAccess(thread, obj, offset).get<java_type>(); \
} UNSAFE_END \
\
-UNSAFE_ENTRY(void, Unsafe_Set##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
- SET_FIELD(obj, offset, java_type, x); \
+UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
+ MemoryAccess(thread, obj, offset).put<java_type>(x); \
} UNSAFE_END \
\
// END DEFINE_GETSETOOP.
@@ -364,12 +454,11 @@
#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
- GET_FIELD_VOLATILE(obj, offset, java_type, v); \
- return v; \
+ return MemoryAccess(thread, obj, offset).get_volatile<java_type>(); \
} UNSAFE_END \
\
-UNSAFE_ENTRY(void, Unsafe_Set##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
- SET_FIELD_VOLATILE(obj, offset, java_type, x); \
+UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
+ MemoryAccess(thread, obj, offset).put_volatile<java_type>(x); \
} UNSAFE_END \
\
// END DEFINE_GETSETOOP_VOLATILE.
@@ -400,98 +489,6 @@
OrderAccess::fence();
} UNSAFE_END
-////// Data in the C heap.
-
-// Note: These do not throw NullPointerException for bad pointers.
-// They just crash. Only a oop base pointer can generate a NullPointerException.
-//
-#define DEFINE_GETSETNATIVE(java_type, Type, native_type) \
- \
-UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) { \
- void* p = addr_from_java(addr); \
- JavaThread* t = JavaThread::current(); \
- t->set_doing_unsafe_access(true); \
- java_type x = *(volatile native_type*)p; \
- t->set_doing_unsafe_access(false); \
- return x; \
-} UNSAFE_END \
- \
-UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) { \
- JavaThread* t = JavaThread::current(); \
- t->set_doing_unsafe_access(true); \
- void* p = addr_from_java(addr); \
- *(volatile native_type*)p = x; \
- t->set_doing_unsafe_access(false); \
-} UNSAFE_END \
- \
-// END DEFINE_GETSETNATIVE.
-
-DEFINE_GETSETNATIVE(jbyte, Byte, signed char)
-DEFINE_GETSETNATIVE(jshort, Short, signed short);
-DEFINE_GETSETNATIVE(jchar, Char, unsigned short);
-DEFINE_GETSETNATIVE(jint, Int, jint);
-// no long -- handled specially
-DEFINE_GETSETNATIVE(jfloat, Float, float);
-DEFINE_GETSETNATIVE(jdouble, Double, double);
-
-#undef DEFINE_GETSETNATIVE
-
-UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) {
- JavaThread* t = JavaThread::current();
- // We do it this way to avoid problems with access to heap using 64
- // bit loads, as jlong in heap could be not 64-bit aligned, and on
- // some CPUs (SPARC) it leads to SIGBUS.
- t->set_doing_unsafe_access(true);
- void* p = addr_from_java(addr);
- jlong x;
-
- if (is_ptr_aligned(p, sizeof(jlong)) == 0) {
- // jlong is aligned, do a volatile access
- x = *(volatile jlong*)p;
- } else {
- jlong_accessor acc;
- acc.words[0] = ((volatile jint*)p)[0];
- acc.words[1] = ((volatile jint*)p)[1];
- x = acc.long_value;
- }
-
- t->set_doing_unsafe_access(false);
-
- return x;
-} UNSAFE_END
-
-UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
- JavaThread* t = JavaThread::current();
- // see comment for Unsafe_GetNativeLong
- t->set_doing_unsafe_access(true);
- void* p = addr_from_java(addr);
-
- if (is_ptr_aligned(p, sizeof(jlong))) {
- // jlong is aligned, do a volatile access
- *(volatile jlong*)p = x;
- } else {
- jlong_accessor acc;
- acc.long_value = x;
- ((volatile jint*)p)[0] = acc.words[0];
- ((volatile jint*)p)[1] = acc.words[1];
- }
-
- t->set_doing_unsafe_access(false);
-} UNSAFE_END
-
-
-UNSAFE_LEAF(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) {
- void* p = addr_from_java(addr);
-
- return addr_to_java(*(void**)p);
-} UNSAFE_END
-
-UNSAFE_LEAF(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
- void* p = addr_from_java(addr);
- *(void**)p = addr_from_java(x);
-} UNSAFE_END
-
-
////// Allocation requests
UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
@@ -980,8 +977,8 @@
} UNSAFE_END
UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+ Handle p(THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
#ifdef SUPPORTS_NATIVE_CX8
return (jlong)(Atomic::cmpxchg(x, addr, e));
@@ -1017,7 +1014,7 @@
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
oop p = JNIHandles::resolve(obj);
- jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
+ jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
} UNSAFE_END
@@ -1143,20 +1140,16 @@
#define DECLARE_GETPUTOOP(Type, Desc) \
{CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
- {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type)}, \
+ {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \
{CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
- {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type##Volatile)}
+ {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)}
-#define DECLARE_GETPUTNATIVE(Byte, B) \
- {CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \
- {CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)}
-
static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)},
- {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)},
+ {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutObject)},
{CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)},
- {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)},
+ {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutObjectVolatile)},
{CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
{CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)},
@@ -1171,17 +1164,6 @@
DECLARE_GETPUTOOP(Float, F),
DECLARE_GETPUTOOP(Double, D),
- DECLARE_GETPUTNATIVE(Byte, B),
- DECLARE_GETPUTNATIVE(Short, S),
- DECLARE_GETPUTNATIVE(Char, C),
- DECLARE_GETPUTNATIVE(Int, I),
- DECLARE_GETPUTNATIVE(Long, J),
- DECLARE_GETPUTNATIVE(Float, F),
- DECLARE_GETPUTNATIVE(Double, D),
-
- {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)},
- {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)},
-
{CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
{CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
{CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
@@ -1239,7 +1221,6 @@
#undef DAC_Args
#undef DECLARE_GETPUTOOP
-#undef DECLARE_GETPUTNATIVE
// This function is exported, used by NativeLookup.
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon May 09 13:13:07 2016 +0300
@@ -1762,6 +1762,21 @@
return callee_method;
}
+address SharedRuntime::handle_unsafe_access(JavaThread* thread, address next_pc) {
+ // The faulting unsafe accesses should be changed to throw the error
+ // synchronously instead. Meanwhile the faulting instruction will be
+ // skipped over (effectively turning it into a no-op) and an
+ // asynchronous exception will be raised which the thread will
+ // handle at a later point. If the instruction is a load it will
+ // return garbage.
+
+ // Request an async exception.
+ thread->set_pending_unsafe_access_error();
+
+ // Return address of next instruction to execute.
+ return next_pc;
+}
+
#ifdef ASSERT
void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
const BasicType* sig_bt,
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Mon May 09 13:13:07 2016 +0300
@@ -522,6 +522,8 @@
static address handle_wrong_method_abstract(JavaThread* thread);
static address handle_wrong_method_ic_miss(JavaThread* thread);
+ static address handle_unsafe_access(JavaThread* thread, address next_pc);
+
#ifndef PRODUCT
// Collect and print inline cache miss statistics
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Mon May 09 13:13:07 2016 +0300
@@ -55,7 +55,6 @@
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
address StubRoutines::_throw_StackOverflowError_entry = NULL;
address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL;
-address StubRoutines::_handler_for_unsafe_access_entry = NULL;
jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_verify_oop_subroutine_entry = NULL;
address StubRoutines::_atomic_xchg_entry = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Mon May 09 13:13:07 2016 +0300
@@ -111,7 +111,6 @@
static address _throw_NullPointerException_at_call_entry;
static address _throw_StackOverflowError_entry;
static address _throw_delayed_StackOverflowError_entry;
- static address _handler_for_unsafe_access_entry;
static address _atomic_xchg_entry;
static address _atomic_xchg_ptr_entry;
@@ -288,10 +287,6 @@
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; }
- // Exceptions during unsafe access - should throw Java exception rather
- // than crash.
- static address handler_for_unsafe_access() { return _handler_for_unsafe_access_entry; }
-
static address atomic_xchg_entry() { return _atomic_xchg_entry; }
static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
static address atomic_store_entry() { return _atomic_store_entry; }
--- a/hotspot/src/share/vm/runtime/vframe.hpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/runtime/vframe.hpp Mon May 09 13:13:07 2016 +0300
@@ -317,14 +317,6 @@
intptr_t* frame_id() const { return _frame.id(); }
address frame_pc() const { return _frame.pc(); }
- javaVFrame* java_frame() {
- vframe* vf = vframe::new_vframe(&_frame, &_reg_map, _thread);
- if (vf->is_java_frame()) {
- return (javaVFrame*)vf;
- }
- return NULL;
- }
-
CodeBlob* cb() const { return _frame.cb(); }
CompiledMethod* nm() const {
assert( cb() != NULL && cb()->is_compiled(), "usage");
--- a/hotspot/src/share/vm/utilities/vmError.cpp Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon May 09 13:13:07 2016 +0300
@@ -290,8 +290,8 @@
void VMError::report(outputStream* st, bool _verbose) {
-# define BEGIN if (_current_step == 0) { _current_step = 1;
-# define STEP(n, s) } if (_current_step < n) { _current_step = n; _current_step_info = s;
+# define BEGIN if (_current_step == 0) { _current_step = __LINE__;
+# define STEP(s) } if (_current_step < __LINE__) { _current_step = __LINE__; _current_step_info = s;
# define END }
// don't allocate large buffer on stack
@@ -299,7 +299,7 @@
BEGIN
- STEP(10, "(printing fatal error message)")
+ STEP("printing fatal error message")
st->print_cr("#");
if (should_report_bug(_id)) {
@@ -314,21 +314,21 @@
// test secondary error handling. Test it twice, to test that resetting
// error handler after a secondary crash works.
- STEP(20, "(test secondary crash 1)")
+ STEP("test secondary crash 1")
if (_verbose && TestCrashInErrorHandler != 0) {
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
TestCrashInErrorHandler);
controlled_crash(TestCrashInErrorHandler);
}
- STEP(30, "(test secondary crash 2)")
+ STEP("test secondary crash 2")
if (_verbose && TestCrashInErrorHandler != 0) {
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
TestCrashInErrorHandler);
controlled_crash(TestCrashInErrorHandler);
}
- STEP(40, "(test safefetch in error handler)")
+ STEP("test safefetch in error handler")
// test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
// to test that resetting the signal handler works correctly.
if (_verbose && TestSafeFetchInErrorHandler) {
@@ -349,7 +349,7 @@
}
#endif // PRODUCT
- STEP(50, "(printing type of error)")
+ STEP("printing type of error")
switch(_id) {
case OOM_MALLOC_ERROR:
@@ -384,7 +384,7 @@
break;
}
- STEP(60, "(printing exception/signal name)")
+ STEP("printing exception/signal name")
st->print_cr("#");
st->print("# ");
@@ -414,14 +414,14 @@
}
}
- STEP(70, "(printing current thread and pid)")
+ STEP("printing current thread and pid")
// process id, thread id
st->print(", pid=%d", os::current_process_id());
st->print(", tid=" UINTX_FORMAT, os::current_thread_id());
st->cr();
- STEP(80, "(printing error message)")
+ STEP("printing error message")
if (should_report_bug(_id)) { // already printed the message.
// error message
@@ -432,11 +432,11 @@
}
}
- STEP(90, "(printing Java version string)")
+ STEP("printing Java version string")
report_vm_version(st, buf, sizeof(buf));
- STEP(100, "(printing problematic frame)")
+ STEP("printing problematic frame")
// Print current frame if we have a context (i.e. it's a crash)
if (_context) {
@@ -448,7 +448,7 @@
st->print_cr("#");
}
- STEP(110, "(printing core file information)")
+ STEP("printing core file information")
st->print("# ");
if (CreateCoredumpOnCrash) {
if (coredump_status) {
@@ -462,13 +462,13 @@
st->cr();
st->print_cr("#");
- STEP(120, "(printing bug submit message)")
+ STEP("printing bug submit message")
if (should_report_bug(_id) && _verbose) {
print_bug_submit_message(st, _thread);
}
- STEP(130, "(printing summary)" )
+ STEP("printing summary")
if (_verbose) {
st->cr();
@@ -476,7 +476,7 @@
st->cr();
}
- STEP(140, "(printing VM option summary)" )
+ STEP("printing VM option summary")
if (_verbose) {
// VM options
@@ -484,20 +484,20 @@
st->cr();
}
- STEP(150, "(printing summary machine and OS info)")
+ STEP("printing summary machine and OS info")
if (_verbose) {
os::print_summary_info(st, buf, sizeof(buf));
}
- STEP(160, "(printing date and time)" )
+ STEP("printing date and time")
if (_verbose) {
os::print_date_and_time(st, buf, sizeof(buf));
}
- STEP(170, "(printing thread)" )
+ STEP("printing thread")
if (_verbose) {
st->cr();
@@ -505,7 +505,7 @@
st->cr();
}
- STEP(180, "(printing current thread)" )
+ STEP("printing current thread")
// current thread
if (_verbose) {
@@ -519,7 +519,7 @@
st->cr();
}
- STEP(190, "(printing current compile task)" )
+ STEP("printing current compile task")
if (_verbose && _thread && _thread->is_Compiler_thread()) {
CompilerThread* t = (CompilerThread*)_thread;
@@ -532,7 +532,7 @@
}
- STEP(200, "(printing stack bounds)" )
+ STEP("printing stack bounds")
if (_verbose) {
st->print("Stack: ");
@@ -563,7 +563,7 @@
st->cr();
}
- STEP(210, "(printing native stack)" )
+ STEP("printing native stack")
if (_verbose) {
if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
@@ -577,13 +577,13 @@
}
}
- STEP(220, "(printing Java stack)" )
+ STEP("printing Java stack")
if (_verbose && _thread && _thread->is_Java_thread()) {
print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
}
- STEP(230, "(printing target Java thread stack)" )
+ STEP("printing target Java thread stack")
// printing Java thread stack trace if it is involved in GC crash
if (_verbose && _thread && (_thread->is_Named_thread())) {
@@ -594,7 +594,7 @@
}
}
- STEP(240, "(printing siginfo)" )
+ STEP("printing siginfo")
// signal no, signal code, address that caused the fault
if (_verbose && _siginfo) {
@@ -603,7 +603,7 @@
st->cr();
}
- STEP(245, "(CDS archive access warning)" )
+ STEP("CDS archive access warning")
// Print an explicit hint if we crashed on access to the CDS archive.
if (_verbose && _siginfo) {
@@ -611,7 +611,7 @@
st->cr();
}
- STEP(250, "(printing register info)")
+ STEP("printing register info")
// decode register contents if possible
if (_verbose && _context && Universe::is_fully_initialized()) {
@@ -619,7 +619,7 @@
st->cr();
}
- STEP(260, "(printing registers, top of stack, instructions near pc)")
+ STEP("printing registers, top of stack, instructions near pc")
// registers, top of stack, instructions near pc
if (_verbose && _context) {
@@ -627,7 +627,7 @@
st->cr();
}
- STEP(265, "(printing code blob if possible)")
+ STEP("printing code blob if possible")
if (_verbose && _context) {
CodeBlob* cb = CodeCache::find_blob(_pc);
@@ -652,7 +652,7 @@
}
}
- STEP(270, "(printing VM operation)" )
+ STEP("printing VM operation")
if (_verbose && _thread && _thread->is_VM_thread()) {
VMThread* t = (VMThread*)_thread;
@@ -664,7 +664,7 @@
}
}
- STEP(280, "(printing process)" )
+ STEP("printing process")
if (_verbose) {
st->cr();
@@ -672,7 +672,7 @@
st->cr();
}
- STEP(290, "(printing all threads)" )
+ STEP("printing all threads")
// all threads
if (_verbose && _thread) {
@@ -680,7 +680,7 @@
st->cr();
}
- STEP(300, "(printing VM state)" )
+ STEP("printing VM state")
if (_verbose) {
// Safepoint state
@@ -702,7 +702,7 @@
st->cr();
}
- STEP(310, "(printing owned locks on error)" )
+ STEP("printing owned locks on error")
// mutexes/monitors that currently have an owner
if (_verbose) {
@@ -710,7 +710,7 @@
st->cr();
}
- STEP(320, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
+ STEP("printing number of OutOfMemoryError and StackOverflow exceptions")
if (_verbose && Exceptions::has_exception_counts()) {
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
@@ -718,7 +718,7 @@
st->cr();
}
- STEP(330, "(printing compressed oops mode")
+ STEP("printing compressed oops mode")
if (_verbose && UseCompressedOops) {
Universe::print_compressed_oops_mode(st);
@@ -728,7 +728,7 @@
st->cr();
}
- STEP(340, "(printing heap information)" )
+ STEP("printing heap information")
if (_verbose && Universe::is_fully_initialized()) {
Universe::heap()->print_on_error(st);
@@ -737,7 +737,7 @@
st->cr();
}
- STEP(350, "(printing code cache information)" )
+ STEP("printing code cache information")
if (_verbose && Universe::is_fully_initialized()) {
// print code cache information before vm abort
@@ -745,14 +745,14 @@
st->cr();
}
- STEP(360, "(printing ring buffers)" )
+ STEP("printing ring buffers")
if (_verbose) {
Events::print_all(st);
st->cr();
}
- STEP(370, "(printing dynamic libraries)" )
+ STEP("printing dynamic libraries")
if (_verbose) {
// dynamic libraries, or memory map
@@ -760,7 +760,7 @@
st->cr();
}
- STEP(380, "(printing VM options)" )
+ STEP("printing VM options")
if (_verbose) {
// VM options
@@ -768,40 +768,40 @@
st->cr();
}
- STEP(390, "(printing warning if internal testing API used)" )
+ STEP("printing warning if internal testing API used")
if (WhiteBox::used()) {
st->print_cr("Unsupported internal testing APIs have been used.");
st->cr();
}
- STEP(395, "(printing log configuration)")
+ STEP("printing log configuration")
if (_verbose){
st->print_cr("Logging:");
LogConfiguration::describe_current_configuration(st);
st->cr();
}
- STEP(400, "(printing all environment variables)" )
+ STEP("printing all environment variables")
if (_verbose) {
os::print_environment_variables(st, env_list);
st->cr();
}
- STEP(410, "(printing signal handlers)" )
+ STEP("printing signal handlers")
if (_verbose) {
os::print_signal_handlers(st, buf, sizeof(buf));
st->cr();
}
- STEP(420, "(Native Memory Tracking)" )
+ STEP("Native Memory Tracking")
if (_verbose) {
MemTracker::error_report(st);
}
- STEP(430, "(printing system)" )
+ STEP("printing system")
if (_verbose) {
st->cr();
@@ -809,27 +809,27 @@
st->cr();
}
- STEP(440, "(printing OS information)" )
+ STEP("printing OS information")
if (_verbose) {
os::print_os_info(st);
st->cr();
}
- STEP(450, "(printing CPU info)" )
+ STEP("printing CPU info")
if (_verbose) {
os::print_cpu_info(st, buf, sizeof(buf));
st->cr();
}
- STEP(460, "(printing memory info)" )
+ STEP("printing memory info")
if (_verbose) {
os::print_memory_info(st);
st->cr();
}
- STEP(470, "(printing internal vm info)" )
+ STEP("printing internal vm info")
if (_verbose) {
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
@@ -837,7 +837,7 @@
}
// print a defined marker to show that error handling finished correctly.
- STEP(480, "(printing end marker)" )
+ STEP("printing end marker")
if (_verbose) {
st->print_cr("END.");
@@ -858,35 +858,35 @@
char buf[O_BUFLEN];
report_vm_version(st, buf, sizeof(buf));
- // STEP("(printing summary)")
+ // STEP("printing summary")
st->cr();
st->print_cr("--------------- S U M M A R Y ------------");
st->cr();
- // STEP("(printing VM option summary)")
+ // STEP("printing VM option summary")
// VM options
Arguments::print_summary_on(st);
st->cr();
- // STEP("(printing summary machine and OS info)")
+ // STEP("printing summary machine and OS info")
os::print_summary_info(st, buf, sizeof(buf));
- // STEP("(printing date and time)")
+ // STEP("printing date and time")
os::print_date_and_time(st, buf, sizeof(buf));
- // Skip: STEP("(printing thread)")
+ // Skip: STEP("printing thread")
- // STEP("(printing process)")
+ // STEP("printing process")
st->cr();
st->print_cr("--------------- P R O C E S S ---------------");
st->cr();
- // STEP("(printing number of OutOfMemoryError and StackOverflow exceptions)")
+ // STEP("printing number of OutOfMemoryError and StackOverflow exceptions")
if (Exceptions::has_exception_counts()) {
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
@@ -894,7 +894,7 @@
st->cr();
}
- // STEP("(printing compressed oops mode")
+ // STEP("printing compressed oops mode")
if (UseCompressedOops) {
Universe::print_compressed_oops_mode(st);
@@ -904,7 +904,7 @@
st->cr();
}
- // STEP("(printing heap information)")
+ // STEP("printing heap information")
if (Universe::is_fully_initialized()) {
Universe::heap()->print_on_error(st);
@@ -913,7 +913,7 @@
st->cr();
}
- // STEP("(printing code cache information)")
+ // STEP("printing code cache information")
if (Universe::is_fully_initialized()) {
// print code cache information before vm abort
@@ -921,77 +921,77 @@
st->cr();
}
- // STEP("(printing ring buffers)")
+ // STEP("printing ring buffers")
Events::print_all(st);
st->cr();
- // STEP("(printing dynamic libraries)")
+ // STEP("printing dynamic libraries")
// dynamic libraries, or memory map
os::print_dll_info(st);
st->cr();
- // STEP("(printing VM options)")
+ // STEP("printing VM options")
// VM options
Arguments::print_on(st);
st->cr();
- // STEP("(printing warning if internal testing API used)")
+ // STEP("printing warning if internal testing API used")
if (WhiteBox::used()) {
st->print_cr("Unsupported internal testing APIs have been used.");
st->cr();
}
- // STEP("(printing log configuration)")
+ // STEP("printing log configuration")
st->print_cr("Logging:");
LogConfiguration::describe(st);
st->cr();
- // STEP("(printing all environment variables)")
+ // STEP("printing all environment variables")
os::print_environment_variables(st, env_list);
st->cr();
- // STEP("(printing signal handlers)")
+ // STEP("printing signal handlers")
os::print_signal_handlers(st, buf, sizeof(buf));
st->cr();
- // STEP("(Native Memory Tracking)")
+ // STEP("Native Memory Tracking")
MemTracker::error_report(st);
- // STEP("(printing system)")
+ // STEP("printing system")
st->cr();
st->print_cr("--------------- S Y S T E M ---------------");
st->cr();
- // STEP("(printing OS information)")
+ // STEP("printing OS information")
os::print_os_info(st);
st->cr();
- // STEP("(printing CPU info)")
+ // STEP("printing CPU info")
os::print_cpu_info(st, buf, sizeof(buf));
st->cr();
- // STEP("(printing memory info)")
+ // STEP("printing memory info")
os::print_memory_info(st);
st->cr();
- // STEP("(printing internal vm info)")
+ // STEP("printing internal vm info")
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
st->cr();
// print a defined marker to show that error handling finished correctly.
- // STEP("(printing end marker)")
+ // STEP("printing end marker")
st->print_cr("END.");
}
@@ -1190,7 +1190,7 @@
}
jio_snprintf(buffer, sizeof(buffer),
- "[error occurred during error reporting %s, id 0x%x]",
+ "[error occurred during error reporting (%s), id 0x%x]",
_current_step_info, _id);
if (log.is_open()) {
log.cr();
--- a/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java Fri May 06 19:45:22 2016 +0300
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java Mon May 09 13:13:07 2016 +0300
@@ -24,6 +24,7 @@
/*
* @test
* @bug 8136421
+ * @ignore 8155216
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
* @library / /testlibrary /test/lib/
* @library ../common/patches