Merge
This commit is contained in:
commit
c7d1cae645
@ -825,17 +825,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -64,20 +64,6 @@ static const Register& Lstub_temp = L2;
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// 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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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 :
|
||||
//
|
||||
@ -5380,9 +5310,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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();
|
||||
|
||||
|
@ -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 @@ const int FPU_CNTRL_WRD_MASK = 0xFFFF;
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// 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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// 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();
|
||||
|
||||
|
@ -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 @@ const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
|
||||
|
||||
// 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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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:
|
||||
@ -5136,9 +5095,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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();
|
||||
|
@ -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 @@ class StubGenerator: public StubCodeGenerator {
|
||||
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() {
|
||||
|
@ -392,11 +392,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
|
||||
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 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -584,7 +584,8 @@ JVM_handle_bsd_signal(int sig,
|
||||
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 @@ JVM_handle_bsd_signal(int sig,
|
||||
} 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
|
||||
|
@ -226,23 +226,6 @@ extern "C" void FetchNPFI () ;
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
} 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
|
||||
|
@ -366,11 +366,9 @@ JVM_handle_linux_signal(int sig,
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -433,14 +433,14 @@ inline static bool checkPollingPage(address pc, address fault, address* stub) {
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
break;
|
||||
}
|
||||
|
||||
if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) {
|
||||
if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -420,7 +420,8 @@ JVM_handle_linux_signal(int sig,
|
||||
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 @@ JVM_handle_linux_signal(int sig,
|
||||
} 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
|
||||
|
@ -441,7 +441,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||
|
||||
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 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,8 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||
|
||||
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 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,20 +198,6 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
|
||||
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:
|
||||
|
@ -3465,20 +3465,6 @@ void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) {
|
||||
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;
|
||||
|
@ -140,9 +140,10 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL;
|
||||
PerfCounter* ClassLoader::_isUnsyncloadClass = NULL;
|
||||
PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
||||
|
||||
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
||||
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
||||
int ClassLoader::_num_entries = 0;
|
||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_xpatch_entries = NULL;
|
||||
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
||||
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
||||
int ClassLoader::_num_entries = 0;
|
||||
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
|
||||
bool ClassLoader::_has_jimage = false;
|
||||
#if INCLUDE_CDS
|
||||
@ -179,6 +180,44 @@ bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
|
||||
return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
|
||||
}
|
||||
|
||||
// Used to obtain the package name from a fully qualified class name.
|
||||
// It is the responsibility of the caller to establish ResourceMark.
|
||||
const char* ClassLoader::package_from_name(const char* class_name) {
|
||||
const char* last_slash = strrchr(class_name, '/');
|
||||
if (last_slash == NULL) {
|
||||
// No package name
|
||||
return NULL;
|
||||
}
|
||||
int length = last_slash - class_name;
|
||||
|
||||
// A class name could have just the slash character in the name,
|
||||
// resulting in a negative length.
|
||||
if (length <= 0) {
|
||||
// No package name
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// drop name after last slash (including slash)
|
||||
// Ex., "java/lang/String.class" => "java/lang"
|
||||
char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
|
||||
strncpy(pkg_name, class_name, length);
|
||||
*(pkg_name+length) = '\0';
|
||||
|
||||
return (const char *)pkg_name;
|
||||
}
|
||||
|
||||
// Given a fully qualified class name, find its defining package in the class loader's
|
||||
// package entry table.
|
||||
static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
const char *pkg_name = ClassLoader::package_from_name(class_name);
|
||||
if (pkg_name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PackageEntryTable* pkgEntryTable = loader_data->packages();
|
||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(pkg_name, CHECK_NULL);
|
||||
return pkgEntryTable->lookup_only(pkg_symbol);
|
||||
}
|
||||
|
||||
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
|
||||
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
|
||||
@ -281,8 +320,7 @@ u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_ter
|
||||
#if INCLUDE_CDS
|
||||
u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
|
||||
u1* buffer = NULL;
|
||||
if (!_is_boot_append) {
|
||||
assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time");
|
||||
if (DumpSharedSpaces) {
|
||||
// We presume default is multi-release enabled
|
||||
const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
|
||||
const char* verstr = Arguments::get_property("jdk.util.jar.version");
|
||||
@ -402,31 +440,6 @@ ClassPathImageEntry::~ClassPathImageEntry() {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassPathImageEntry::name_to_package(const char* name, char* buffer, int length) {
|
||||
const char *pslash = strrchr(name, '/');
|
||||
if (pslash == NULL) {
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
int len = pslash - name;
|
||||
#if INCLUDE_CDS
|
||||
if (len <= 0 && DumpSharedSpaces) {
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert(len > 0, "Bad length for package name");
|
||||
if (len >= length) {
|
||||
buffer[0] = '\0';
|
||||
return;
|
||||
}
|
||||
// drop name after last slash (including slash)
|
||||
// Ex., "java/lang/String.class" => "java/lang"
|
||||
strncpy(buffer, name, len);
|
||||
// ensure string termination (strncpy does not guarantee)
|
||||
buffer[len] = '\0';
|
||||
}
|
||||
|
||||
// For a class in a named module, look it up in the jimage file using this syntax:
|
||||
// /<module-name>/<package-name>/<base-class>
|
||||
//
|
||||
@ -439,15 +452,10 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);
|
||||
|
||||
if (location == 0) {
|
||||
char package[JIMAGE_MAX_PATH];
|
||||
name_to_package(name, package, JIMAGE_MAX_PATH);
|
||||
ResourceMark rm;
|
||||
const char* pkg_name = ClassLoader::package_from_name(name);
|
||||
|
||||
#if INCLUDE_CDS
|
||||
if (package[0] == '\0' && DumpSharedSpaces) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (package[0] != '\0') {
|
||||
if (pkg_name != NULL) {
|
||||
if (!Universe::is_module_initialized()) {
|
||||
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
|
||||
#if INCLUDE_CDS
|
||||
@ -455,7 +463,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||
// modules defined for other class loaders. So, for now, get their module
|
||||
// names from the "modules" jimage file.
|
||||
if (DumpSharedSpaces && location == 0) {
|
||||
const char* module_name = (*JImagePackageToModule)(_jimage, package);
|
||||
const char* module_name = (*JImagePackageToModule)(_jimage, pkg_name);
|
||||
if (module_name != NULL) {
|
||||
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
|
||||
}
|
||||
@ -463,13 +471,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// Get boot class loader's package entry table
|
||||
PackageEntryTable* pkgEntryTable =
|
||||
ClassLoaderData::the_null_class_loader_data()->packages();
|
||||
// Get package's package entry
|
||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
|
||||
PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
|
||||
|
||||
PackageEntry* package_entry = get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), THREAD);
|
||||
if (package_entry != NULL) {
|
||||
ResourceMark rm;
|
||||
// Get the module name
|
||||
@ -542,6 +544,33 @@ void ClassLoader::exit_with_path_failure(const char* error, const char* message)
|
||||
}
|
||||
#endif
|
||||
|
||||
ModuleClassPathList::ModuleClassPathList(Symbol* module_name) {
|
||||
_module_name = module_name;
|
||||
_module_first_entry = NULL;
|
||||
_module_last_entry = NULL;
|
||||
}
|
||||
|
||||
ModuleClassPathList::~ModuleClassPathList() {
|
||||
// Clean out each ClassPathEntry on list
|
||||
ClassPathEntry* e = _module_first_entry;
|
||||
while (e != NULL) {
|
||||
ClassPathEntry* next_entry = e->next();
|
||||
delete e;
|
||||
e = next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleClassPathList::add_to_list(ClassPathEntry* new_entry) {
|
||||
if (new_entry != NULL) {
|
||||
if (_module_last_entry == NULL) {
|
||||
_module_first_entry = _module_last_entry = new_entry;
|
||||
} else {
|
||||
_module_last_entry->set_next(new_entry);
|
||||
_module_last_entry = new_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoader::trace_class_path(const char* msg, const char* name) {
|
||||
if (log_is_enabled(Info, class, path)) {
|
||||
ResourceMark rm;
|
||||
@ -619,6 +648,61 @@ bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Construct the array of module/path pairs as specified to -Xpatch
|
||||
// for the boot loader to search ahead of the jimage, if the class being
|
||||
// loaded is defined to a module that has been specified to -Xpatch.
|
||||
void ClassLoader::setup_xpatch_entries() {
|
||||
Thread* THREAD = Thread::current();
|
||||
GrowableArray<ModuleXPatchPath*>* xpatch_args = Arguments::get_xpatchprefix();
|
||||
int num_of_entries = xpatch_args->length();
|
||||
|
||||
// Set up the boot loader's xpatch_entries list
|
||||
_xpatch_entries = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
|
||||
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
const char* module_name = (xpatch_args->at(i))->module_name();
|
||||
Symbol* const module_sym = SymbolTable::lookup(module_name, (int)strlen(module_name), CHECK);
|
||||
assert(module_sym != NULL, "Failed to obtain Symbol for module name");
|
||||
ModuleClassPathList* module_cpl = new ModuleClassPathList(module_sym);
|
||||
|
||||
char* class_path = (xpatch_args->at(i))->path_string();
|
||||
int len = (int)strlen(class_path);
|
||||
int end = 0;
|
||||
// Iterate over the module's class path entries
|
||||
for (int start = 0; start < len; start = end) {
|
||||
while (class_path[end] && class_path[end] != os::path_separator()[0]) {
|
||||
end++;
|
||||
}
|
||||
EXCEPTION_MARK;
|
||||
ResourceMark rm(THREAD);
|
||||
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
||||
strncpy(path, &class_path[start], end - start);
|
||||
path[end - start] = '\0';
|
||||
|
||||
struct stat st;
|
||||
if (os::stat(path, &st) == 0) {
|
||||
// File or directory found
|
||||
Thread* THREAD = Thread::current();
|
||||
ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
|
||||
// If the path specification is valid, enter it into this module's list
|
||||
if (new_entry != NULL) {
|
||||
module_cpl->add_to_list(new_entry);
|
||||
}
|
||||
}
|
||||
|
||||
while (class_path[end] == os::path_separator()[0]) {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
// Record the module into the list of -Xpatch entries only if
|
||||
// valid ClassPathEntrys have been created
|
||||
if (module_cpl->module_first_entry() != NULL) {
|
||||
_xpatch_entries->push(module_cpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
|
||||
int offset = 0;
|
||||
int len = (int)strlen(class_path);
|
||||
@ -850,8 +934,29 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
|
||||
}
|
||||
|
||||
void ClassLoader::print_bootclasspath() {
|
||||
ClassPathEntry* e = _first_entry;
|
||||
ClassPathEntry* e;
|
||||
tty->print("[bootclasspath= ");
|
||||
|
||||
// Print -Xpatch module/path specifications first
|
||||
if (_xpatch_entries != NULL) {
|
||||
ResourceMark rm;
|
||||
int num_of_entries = _xpatch_entries->length();
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
ModuleClassPathList* mpl = _xpatch_entries->at(i);
|
||||
tty->print("%s=", mpl->module_name()->as_C_string());
|
||||
e = mpl->module_first_entry();
|
||||
while (e != NULL) {
|
||||
tty->print("%s", e->name());
|
||||
e = e->next();
|
||||
if (e != NULL) {
|
||||
tty->print("%s", os::path_separator());
|
||||
}
|
||||
}
|
||||
tty->print(" ;");
|
||||
}
|
||||
}
|
||||
|
||||
e = _first_entry;
|
||||
while (e != NULL) {
|
||||
tty->print("%s ;", e->name());
|
||||
e = e->next();
|
||||
@ -945,6 +1050,7 @@ void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
|
||||
return; // only needed for CDS dump time
|
||||
}
|
||||
|
||||
ResourceMark rm;
|
||||
jlong size;
|
||||
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
|
||||
if (location == 0) {
|
||||
@ -989,7 +1095,6 @@ void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
|
||||
begin_ptr = ++end_ptr;
|
||||
end_ptr = strchr(begin_ptr, '\n');
|
||||
}
|
||||
FREE_RESOURCE_ARRAY(u1, buffer, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1110,8 +1215,7 @@ s2 ClassLoader::module_to_classloader(const char* module_name) {
|
||||
return APP_LOADER;
|
||||
}
|
||||
|
||||
s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
|
||||
int classpath_index, TRAPS) {
|
||||
s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e, int classpath_index, TRAPS) {
|
||||
assert(DumpSharedSpaces, "Only used for CDS dump time");
|
||||
|
||||
// obtain the classloader type based on the class name.
|
||||
@ -1160,12 +1264,11 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
||||
}
|
||||
|
||||
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
|
||||
|
||||
assert(name != NULL, "invariant");
|
||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
||||
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
ResourceMark rm(THREAD);
|
||||
HandleMark hm(THREAD);
|
||||
|
||||
const char* const class_name = name->as_C_string();
|
||||
|
||||
@ -1181,30 +1284,101 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
||||
// Lookup stream for parsing .class file
|
||||
ClassFileStream* stream = NULL;
|
||||
s2 classpath_index = 0;
|
||||
ClassPathEntry* e = NULL;
|
||||
|
||||
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
|
||||
// to be _first_entry to the end (all path entries).
|
||||
// to be _first_entry to the end (all path entries). No -Xpatch entries are
|
||||
// included since CDS and AppCDS are not supported if -Xpatch is specified.
|
||||
//
|
||||
// If search_append_only is true, boot loader visibility boundaries are
|
||||
// set to be _fist_append_entry to the end. This includes:
|
||||
// set to be _first_append_entry to the end. This includes:
|
||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
//
|
||||
// If both DumpSharedSpaces and search_append_only are false, boot loader
|
||||
// visibility boundaries are set to be _first_entry to the entry before
|
||||
// the _first_append_entry. This would include:
|
||||
// [-Xpatch:<dirs>]; [exploded build | modules]
|
||||
// [-Xpatch:<module>=<file>(<pathsep><file>)*]; [exploded build | jimage]
|
||||
//
|
||||
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
|
||||
// be true at the same time.
|
||||
ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
|
||||
ClassPathEntry* last_e =
|
||||
(search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
|
||||
assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
|
||||
|
||||
{
|
||||
// Load Attempt #1: -Xpatch
|
||||
// Determine the class' defining module. If it appears in the _xpatch_entries,
|
||||
// attempt to load the class from those locations specific to the module.
|
||||
// Note: The -Xpatch entries are never searched if the boot loader's
|
||||
// visibility boundary is limited to only searching the append entries.
|
||||
if (_xpatch_entries != NULL && !search_append_only && !DumpSharedSpaces) {
|
||||
// Find the module in the boot loader's module entry table
|
||||
PackageEntry* pkg_entry = get_package_entry(class_name, ClassLoaderData::the_null_class_loader_data(), THREAD);
|
||||
ModuleEntry* mod_entry = (pkg_entry != NULL) ? pkg_entry->module() : NULL;
|
||||
|
||||
// If the module system has not defined java.base yet, then
|
||||
// classes loaded are assumed to be defined to java.base.
|
||||
// When java.base is eventually defined by the module system,
|
||||
// all packages of classes that have been previously loaded
|
||||
// are verified in ModuleEntryTable::verify_javabase_packages().
|
||||
if (!Universe::is_module_initialized() &&
|
||||
!ModuleEntryTable::javabase_defined() &&
|
||||
mod_entry == NULL) {
|
||||
mod_entry = ModuleEntryTable::javabase_module();
|
||||
}
|
||||
|
||||
// The module must be a named module
|
||||
if (mod_entry != NULL && mod_entry->is_named()) {
|
||||
int num_of_entries = _xpatch_entries->length();
|
||||
const Symbol* class_module_name = mod_entry->name();
|
||||
|
||||
// Loop through all the xpatch entries looking for module
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
ModuleClassPathList* module_cpl = _xpatch_entries->at(i);
|
||||
Symbol* module_cpl_name = module_cpl->module_name();
|
||||
|
||||
if (module_cpl_name->fast_compare(class_module_name) == 0) {
|
||||
// Class' module has been located, attempt to load
|
||||
// the class from the module's ClassPathEntry list.
|
||||
e = module_cpl->module_first_entry();
|
||||
while (e != NULL) {
|
||||
stream = e->open_stream(file_name, CHECK_NULL);
|
||||
// No context.check is required since both CDS
|
||||
// and AppCDS are turned off if -Xpatch is specified.
|
||||
if (NULL != stream) {
|
||||
break;
|
||||
}
|
||||
e = e->next();
|
||||
}
|
||||
// If the module was located in the xpatch entries, break out
|
||||
// even if the class was not located successfully from that module's
|
||||
// ClassPathEntry list. There will not be another valid entry for
|
||||
// that module in the _xpatch_entries array.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load Attempt #2: [exploded build | jimage]
|
||||
if (!search_append_only && (NULL == stream)) {
|
||||
e = _first_entry;
|
||||
while ((e != NULL) && (e != _first_append_entry)) {
|
||||
stream = e->open_stream(file_name, CHECK_NULL);
|
||||
if (!context.check(stream, classpath_index)) {
|
||||
return NULL;
|
||||
}
|
||||
if (NULL != stream) {
|
||||
break;
|
||||
}
|
||||
e = e->next();
|
||||
++classpath_index;
|
||||
}
|
||||
}
|
||||
|
||||
// Load Attempt #3: [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
if ((search_append_only || DumpSharedSpaces) && (NULL == stream)) {
|
||||
// For the boot loader append path search, must calculate
|
||||
// the starting classpath_index prior to attempting to
|
||||
// load the classfile.
|
||||
if (search_append_only) {
|
||||
// For the boot loader append path search, must calculate
|
||||
// the starting classpath_index prior to attempting to
|
||||
// load the classfile.
|
||||
ClassPathEntry *tmp_e = _first_entry;
|
||||
while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
|
||||
tmp_e = tmp_e->next();
|
||||
@ -1212,11 +1386,8 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to load the classfile from either:
|
||||
// - [-Xpatch:dir]; exploded build | modules
|
||||
// or
|
||||
// - [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
while ((e != NULL) && (e != last_e)) {
|
||||
e = _first_append_entry;
|
||||
while (e != NULL) {
|
||||
stream = e->open_stream(file_name, CHECK_NULL);
|
||||
if (!context.check(stream, classpath_index)) {
|
||||
return NULL;
|
||||
@ -1386,10 +1557,23 @@ int ClassLoader::compute_Object_vtable() {
|
||||
}
|
||||
|
||||
|
||||
void classLoader_init() {
|
||||
void classLoader_init1() {
|
||||
ClassLoader::initialize();
|
||||
}
|
||||
|
||||
// Complete the ClassPathEntry setup for the boot loader
|
||||
void classLoader_init2() {
|
||||
// Setup the list of module/path pairs for -Xpatch processing
|
||||
// This must be done after the SymbolTable is created in order
|
||||
// to use fast_compare on module names instead of a string compare.
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
ClassLoader::setup_xpatch_entries();
|
||||
}
|
||||
|
||||
// Determine if this is an exploded build
|
||||
ClassLoader::set_has_jimage();
|
||||
}
|
||||
|
||||
|
||||
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
|
||||
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
|
||||
@ -1433,17 +1617,19 @@ void ClassLoader::create_javabase() {
|
||||
}
|
||||
ModuleEntryTable::set_javabase_module(jb_module);
|
||||
}
|
||||
}
|
||||
|
||||
// When looking for the jimage file, only
|
||||
// search the boot loader's module path which
|
||||
// can consist of [-Xpatch]; exploded build | modules
|
||||
// Do not search the boot loader's append path.
|
||||
void ClassLoader::set_has_jimage() {
|
||||
// Determine if this is an exploded build. When looking for
|
||||
// the jimage file, only search the piece of the boot
|
||||
// loader's boot class path which contains [exploded build | jimage].
|
||||
// Do not search the boot loader's xpatch entries or append path.
|
||||
ClassPathEntry* e = _first_entry;
|
||||
ClassPathEntry* last_e = _first_append_entry;
|
||||
while ((e != NULL) && (e != last_e)) {
|
||||
JImageFile *jimage = e->jimage();
|
||||
if (jimage != NULL && e->is_jrt()) {
|
||||
set_has_jimage(true);
|
||||
_has_jimage = true;
|
||||
#if INCLUDE_CDS
|
||||
ClassLoader::initialize_module_loader_map(jimage);
|
||||
#endif
|
||||
|
@ -142,13 +142,30 @@ public:
|
||||
JImageFile* jimage() const { return _jimage; }
|
||||
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
||||
~ClassPathImageEntry();
|
||||
void name_to_package(const char* name, char* package, int length);
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
|
||||
// Debugging
|
||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||
};
|
||||
|
||||
// ModuleClassPathList contains a linked list of ClassPathEntry's
|
||||
// that have been specified for a specific module. Currently,
|
||||
// the only way to specify a module/path pair is via the -Xpatch
|
||||
// command line option.
|
||||
class ModuleClassPathList : public CHeapObj<mtClass> {
|
||||
private:
|
||||
Symbol* _module_name;
|
||||
// First and last entries of class path entries for a specific module
|
||||
ClassPathEntry* _module_first_entry;
|
||||
ClassPathEntry* _module_last_entry;
|
||||
public:
|
||||
Symbol* module_name() const { return _module_name; }
|
||||
ClassPathEntry* module_first_entry() const { return _module_first_entry; }
|
||||
ModuleClassPathList(Symbol* module_name);
|
||||
~ModuleClassPathList();
|
||||
void add_to_list(ClassPathEntry* new_entry);
|
||||
};
|
||||
|
||||
class SharedPathsMiscInfo;
|
||||
|
||||
class ClassLoader: AllStatic {
|
||||
@ -195,21 +212,31 @@ class ClassLoader: AllStatic {
|
||||
static PerfCounter* _isUnsyncloadClass;
|
||||
static PerfCounter* _load_instance_class_failCounter;
|
||||
|
||||
// First entry in linked list of ClassPathEntry instances.
|
||||
// This consists of entries made up by:
|
||||
// - boot loader modules
|
||||
// [-Xpatch]; exploded build | modules;
|
||||
// - boot loader append path
|
||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
// The boot class path consists of 3 ordered pieces:
|
||||
// 1. the module/path pairs specified to -Xpatch
|
||||
// -Xpatch:<module>=<file>(<pathsep><file>)*
|
||||
// 2. the base piece
|
||||
// [exploded build | jimage]
|
||||
// 3. boot loader append path
|
||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
//
|
||||
// The boot loader must obey this order when attempting
|
||||
// to load a class.
|
||||
|
||||
// Contains the module/path pairs specified to -Xpatch
|
||||
static GrowableArray<ModuleClassPathList*>* _xpatch_entries;
|
||||
|
||||
// Contains the ClassPathEntry instances that include
|
||||
// both the base piece and the boot loader append path.
|
||||
static ClassPathEntry* _first_entry;
|
||||
// Last entry in linked list of ClassPathEntry instances
|
||||
static ClassPathEntry* _last_entry;
|
||||
static int _num_entries;
|
||||
|
||||
// Pointer into the linked list of ClassPathEntry instances.
|
||||
// Marks the start of:
|
||||
// - the boot loader's append path
|
||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
// within the linked list of ClassPathEntry instances.
|
||||
static ClassPathEntry* _first_append_entry;
|
||||
|
||||
static const char* _shared_archive;
|
||||
@ -325,11 +352,11 @@ class ClassLoader: AllStatic {
|
||||
return _load_instance_class_failCounter;
|
||||
}
|
||||
|
||||
// Sets _has_jimage to TRUE if "modules" jimage file exists
|
||||
static void set_has_jimage(bool val) {
|
||||
_has_jimage = val;
|
||||
}
|
||||
// Set up the module/path pairs as specified to -Xpatch
|
||||
static void setup_xpatch_entries();
|
||||
|
||||
// Sets _has_jimage to TRUE if "modules" jimage file exists
|
||||
static void set_has_jimage();
|
||||
static bool has_jimage() { return _has_jimage; }
|
||||
|
||||
// Create the ModuleEntry for java.base
|
||||
@ -416,6 +443,9 @@ class ClassLoader: AllStatic {
|
||||
|
||||
static bool string_ends_with(const char* str, const char* str_to_find);
|
||||
|
||||
// obtain package name from a fully qualified class name
|
||||
static const char* package_from_name(const char* class_name);
|
||||
|
||||
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
|
||||
|
||||
// Debugging
|
||||
|
@ -133,68 +133,31 @@ static PackageEntry* get_package_entry_by_name(Symbol* package,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if -Xpatch:<dirs> was specified. If so, prepend each <dir>/module_name,
|
||||
// if it exists, to bootpath so boot loader can find the class files. Also, if
|
||||
// using exploded modules, append <java.home>/modules/module_name, if it exists,
|
||||
// to bootpath so that its class files can be found by the boot loader.
|
||||
static void add_to_boot_loader_list(char *module_name, TRAPS) {
|
||||
// java.base should be handled by argument parsing.
|
||||
// If using exploded build, append <java.home>/modules/module_name, if it exists,
|
||||
// to the system boot class path in order for the boot loader to locate class files.
|
||||
static void add_to_exploded_build_list(char *module_name, TRAPS) {
|
||||
assert(!ClassLoader::has_jimage(), "Exploded build not applicable");
|
||||
// java.base is handled by os::set_boot_path
|
||||
assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
|
||||
|
||||
char file_sep = os::file_separator()[0];
|
||||
size_t module_len = strlen(module_name);
|
||||
|
||||
// If -Xpatch is set then add <patch-dir>/module_name paths.
|
||||
char** patch_dirs = Arguments::patch_dirs();
|
||||
if (patch_dirs != NULL) {
|
||||
int dir_count = Arguments::patch_dirs_count();
|
||||
for (int x = 0; x < dir_count; x++) {
|
||||
// Really shouldn't be NULL, but check can't hurt
|
||||
if (patch_dirs[x] != NULL) {
|
||||
size_t len = strlen(patch_dirs[x]);
|
||||
if (len != 0) { // Ignore empty strings.
|
||||
len = len + module_len + 2;
|
||||
char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
||||
jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
|
||||
|
||||
// See if Xpatch module path exists.
|
||||
struct stat st;
|
||||
if ((os::stat(prefix_path, &st) != 0)) {
|
||||
FREE_C_HEAP_ARRAY(char, prefix_path);
|
||||
} else {
|
||||
{
|
||||
HandleMark hm;
|
||||
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
|
||||
ObjectLocker ol(loader_lock, THREAD);
|
||||
ClassLoader::prepend_to_list(prefix_path);
|
||||
}
|
||||
log_info(class, load)("opened: -Xpatch %s", prefix_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If "modules" jimage does not exist then assume exploded form
|
||||
// ${java.home}/modules/<module-name>
|
||||
char* path = NULL;
|
||||
if (!ClassLoader::has_jimage()) {
|
||||
const char* home = Arguments::get_java_home();
|
||||
size_t len = strlen(home) + module_len + 32;
|
||||
path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
||||
jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
|
||||
struct stat st;
|
||||
// See if exploded module path exists.
|
||||
if ((os::stat(path, &st) != 0)) {
|
||||
FREE_C_HEAP_ARRAY(char, path);
|
||||
path = NULL;
|
||||
}
|
||||
const char* home = Arguments::get_java_home();
|
||||
size_t len = strlen(home) + module_len + 32;
|
||||
char* path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
||||
jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
|
||||
struct stat st;
|
||||
// See if exploded module path exists
|
||||
if ((os::stat(path, &st) != 0)) {
|
||||
FREE_C_HEAP_ARRAY(char, path);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
if (path != NULL) {
|
||||
HandleMark hm;
|
||||
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
|
||||
ObjectLocker ol(loader_lock, THREAD);
|
||||
|
||||
log_info(class, load)("opened: %s", path);
|
||||
ClassLoader::add_to_list(path);
|
||||
}
|
||||
@ -498,13 +461,12 @@ void Modules::define_module(jobject module, jstring version,
|
||||
}
|
||||
}
|
||||
|
||||
if (loader == NULL && !Universe::is_module_initialized()) {
|
||||
// Now that the module is defined, if it is in the bootloader, make sure that
|
||||
// its classes can be found. Check if -Xpatch:<path> was specified. If
|
||||
// so prepend <path>/module_name, if it exists, to bootpath. Also, if using
|
||||
// exploded modules, prepend <java.home>/modules/module_name, if it exists,
|
||||
// to bootpath.
|
||||
add_to_boot_loader_list(module_name, CHECK);
|
||||
// If the module is defined to the boot loader and an exploded build is being
|
||||
// used, prepend <java.home>/modules/modules_name, if it exists, to the system boot class path.
|
||||
if (loader == NULL &&
|
||||
!Universe::is_module_initialized() &&
|
||||
!ClassLoader::has_jimage()) {
|
||||
add_to_exploded_build_list(module_name, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,20 +578,6 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||
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:
|
||||
@ -632,8 +618,6 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||
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:
|
||||
|
@ -1231,43 +1231,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") \
|
||||
|
@ -590,8 +590,6 @@ void G1DefaultPolicy::record_collection_pause_end(double pause_time_ms, size_t c
|
||||
bool last_pause_included_initial_mark = false;
|
||||
bool update_stats = !_g1->evacuation_failed();
|
||||
|
||||
NOT_PRODUCT(_short_lived_surv_rate_group->print());
|
||||
|
||||
record_pause(young_gc_pause_kind(), end_time_sec - pause_time_ms / 1000.0, end_time_sec);
|
||||
|
||||
last_pause_included_initial_mark = collector_state()->during_initial_mark_pause();
|
||||
|
@ -144,10 +144,6 @@ void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
|
||||
_sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime;
|
||||
}
|
||||
|
||||
static size_t round_to_K(size_t value) {
|
||||
return value / K;
|
||||
}
|
||||
|
||||
class RegionTypeCounter VALUE_OBJ_CLASS_SPEC {
|
||||
private:
|
||||
const char* _name;
|
||||
@ -198,8 +194,10 @@ public:
|
||||
size_t code_root_elems() const { return _code_root_elems; }
|
||||
|
||||
void print_rs_mem_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "%s (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
byte_size_in_proper_unit(rs_mem_size()),
|
||||
proper_unit_for_byte_size(rs_mem_size()),
|
||||
rs_mem_size_percent_of(total), amount(), _name);
|
||||
}
|
||||
|
||||
void print_cards_occupied_info_on(outputStream * out, size_t total) {
|
||||
@ -208,8 +206,10 @@ public:
|
||||
}
|
||||
|
||||
void print_code_root_mem_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "%s (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
byte_size_in_proper_unit(code_root_mem_size()),
|
||||
proper_unit_for_byte_size(code_root_mem_size()),
|
||||
code_root_mem_size_percent_of(total), amount(), _name);
|
||||
}
|
||||
|
||||
void print_code_root_elems_info_on(outputStream * out, size_t total) {
|
||||
@ -291,17 +291,22 @@ public:
|
||||
RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, NULL };
|
||||
|
||||
out->print_cr(" Current rem set statistics");
|
||||
out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "K."
|
||||
" Max = " SIZE_FORMAT "K.",
|
||||
round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
|
||||
out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "%s."
|
||||
" Max = " SIZE_FORMAT "%s.",
|
||||
byte_size_in_proper_unit(total_rs_mem_sz()),
|
||||
proper_unit_for_byte_size(total_rs_mem_sz()),
|
||||
byte_size_in_proper_unit(max_rs_mem_sz()),
|
||||
proper_unit_for_byte_size(max_rs_mem_sz()));
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
|
||||
}
|
||||
|
||||
out->print_cr(" Static structures = " SIZE_FORMAT "K,"
|
||||
" free_lists = " SIZE_FORMAT "K.",
|
||||
round_to_K(HeapRegionRemSet::static_mem_size()),
|
||||
round_to_K(HeapRegionRemSet::fl_mem_size()));
|
||||
out->print_cr(" Static structures = " SIZE_FORMAT "%s,"
|
||||
" free_lists = " SIZE_FORMAT "%s.",
|
||||
byte_size_in_proper_unit(HeapRegionRemSet::static_mem_size()),
|
||||
proper_unit_for_byte_size(HeapRegionRemSet::static_mem_size()),
|
||||
byte_size_in_proper_unit(HeapRegionRemSet::fl_mem_size()),
|
||||
proper_unit_for_byte_size(HeapRegionRemSet::fl_mem_size()));
|
||||
|
||||
out->print_cr(" " SIZE_FORMAT " occupied cards represented.",
|
||||
total_cards_occupied());
|
||||
@ -312,17 +317,20 @@ public:
|
||||
// Largest sized rem set region statistics
|
||||
HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
|
||||
out->print_cr(" Region with largest rem set = " HR_FORMAT ", "
|
||||
"size = " SIZE_FORMAT "K, occupied = " SIZE_FORMAT "K.",
|
||||
"size = " SIZE_FORMAT "%s, occupied = " SIZE_FORMAT "%s.",
|
||||
HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
|
||||
round_to_K(rem_set->mem_size()),
|
||||
round_to_K(rem_set->occupied()));
|
||||
|
||||
byte_size_in_proper_unit(rem_set->mem_size()),
|
||||
proper_unit_for_byte_size(rem_set->mem_size()),
|
||||
byte_size_in_proper_unit(rem_set->occupied()),
|
||||
proper_unit_for_byte_size(rem_set->occupied()));
|
||||
// Strong code root statistics
|
||||
HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
|
||||
out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "K."
|
||||
" Max = " SIZE_FORMAT "K.",
|
||||
round_to_K(total_code_root_mem_sz()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
|
||||
out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "%s."
|
||||
" Max = " SIZE_FORMAT "%s.",
|
||||
byte_size_in_proper_unit(total_code_root_mem_sz()),
|
||||
proper_unit_for_byte_size(total_code_root_mem_sz()),
|
||||
byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()),
|
||||
proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size()));
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
|
||||
}
|
||||
@ -334,10 +342,11 @@ public:
|
||||
}
|
||||
|
||||
out->print_cr(" Region with largest amount of code roots = " HR_FORMAT ", "
|
||||
"size = " SIZE_FORMAT "K, num_elems = " SIZE_FORMAT ".",
|
||||
"size = " SIZE_FORMAT "%s, num_elems = " SIZE_FORMAT ".",
|
||||
HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
|
||||
byte_size_in_proper_unit(max_code_root_rem_set->strong_code_roots_mem_size()),
|
||||
proper_unit_for_byte_size(max_code_root_rem_set->strong_code_roots_mem_size()),
|
||||
max_code_root_rem_set->strong_code_roots_list_length());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -379,7 +379,7 @@ print_initial_summary_data(ParallelCompactData& summary_data,
|
||||
}
|
||||
|
||||
void ParallelCompact_test() {
|
||||
if (!UseParallelGC) {
|
||||
if (!UseParallelOldGC) {
|
||||
return;
|
||||
}
|
||||
// Check that print_generic_summary_data() does not print the
|
||||
|
@ -881,7 +881,7 @@ bool FileMapInfo::FileMapHeader::validate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Arguments::patch_dirs() != NULL) {
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
|
||||
return false;
|
||||
}
|
||||
|
@ -409,22 +409,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
|
||||
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:
|
||||
|
@ -93,7 +93,7 @@ class LibraryCallKit : public GraphKit {
|
||||
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 @@ class LibraryCallKit : public GraphKit {
|
||||
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 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
// 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 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
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::_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_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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::_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 @@ bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) {
|
||||
|
||||
//----------------------------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 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
|
||||
}
|
||||
|
||||
|
||||
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 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
|
||||
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 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||
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 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||
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 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||
// 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;
|
||||
}
|
||||
|
@ -131,38 +131,137 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
|
||||
}
|
||||
|
||||
|
||||
///// Data in the Java heap.
|
||||
///// Data read/writes on the Java heap and in native (off-heap) memory
|
||||
|
||||
#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)
|
||||
/**
|
||||
* 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 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)
|
||||
// Resolves and returns the address of the memory access
|
||||
void* addr() {
|
||||
return index_oop_from_field_offset_long(JNIHandles::resolve(_obj), _offset);
|
||||
}
|
||||
|
||||
#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)
|
||||
template <typename T>
|
||||
T normalize(T x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
#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));
|
||||
jboolean normalize(jboolean x) {
|
||||
return x & 1;
|
||||
}
|
||||
|
||||
#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));
|
||||
/**
|
||||
* Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
|
||||
*/
|
||||
class GuardUnsafeAccess {
|
||||
JavaThread* _thread;
|
||||
bool _active;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
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 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj,
|
||||
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 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobj
|
||||
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_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject
|
||||
|
||||
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 @@ UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) {
|
||||
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_GETSETOOP(jdouble, Double);
|
||||
#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 @@ UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
|
||||
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_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, job
|
||||
} 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_CompareAndSwapObject(JNIEnv *env, jobject unsafe,
|
||||
|
||||
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 @@ UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleAr
|
||||
|
||||
#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 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||
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 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||
#undef DAC_Args
|
||||
|
||||
#undef DECLARE_GETPUTOOP
|
||||
#undef DECLARE_GETPUTNATIVE
|
||||
|
||||
|
||||
// This function is exported, used by NativeLookup.
|
||||
|
@ -84,8 +84,6 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG;
|
||||
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
|
||||
int Arguments::_sun_java_launcher_pid = -1;
|
||||
bool Arguments::_sun_java_launcher_is_altjvm = false;
|
||||
int Arguments::_patch_dirs_count = 0;
|
||||
char** Arguments::_patch_dirs = NULL;
|
||||
int Arguments::_bootclassloader_append_index = -1;
|
||||
|
||||
// These parameters are reset in method parse_vm_init_args()
|
||||
@ -112,6 +110,7 @@ SystemProperty *Arguments::_java_home = NULL;
|
||||
SystemProperty *Arguments::_java_class_path = NULL;
|
||||
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
|
||||
|
||||
GrowableArray<ModuleXPatchPath*> *Arguments::_xpatchprefix = NULL;
|
||||
PathString *Arguments::_system_boot_class_path = NULL;
|
||||
|
||||
char* Arguments::_ext_dirs = NULL;
|
||||
@ -580,204 +579,6 @@ static bool verify_special_jvm_flags() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Constructs the system boot class path from the following components, in order:
|
||||
//
|
||||
// prefix // from -Xpatch:...
|
||||
// base // from os::get_system_properties()
|
||||
// suffix // from -Xbootclasspath/a:...
|
||||
//
|
||||
// This could be AllStatic, but it isn't needed after argument processing is
|
||||
// complete. After argument processing, the combined components are copied
|
||||
// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
|
||||
class ArgumentBootClassPath: public StackObj {
|
||||
public:
|
||||
ArgumentBootClassPath(const char* base);
|
||||
~ArgumentBootClassPath();
|
||||
|
||||
inline void set_base(const char* base);
|
||||
inline void add_prefix(const char* prefix);
|
||||
inline void add_suffix_to_prefix(const char* suffix);
|
||||
inline void add_suffix(const char* suffix);
|
||||
inline void reset_path(const char* base);
|
||||
|
||||
inline const char* get_base() const { return _items[_bcp_base]; }
|
||||
inline const char* get_prefix() const { return _items[_bcp_prefix]; }
|
||||
inline const char* get_suffix() const { return _items[_bcp_suffix]; }
|
||||
|
||||
// Combine all the components into a single c-heap-allocated string; caller
|
||||
// must free the string if/when no longer needed.
|
||||
char* combined_path();
|
||||
|
||||
private:
|
||||
// Utility routines.
|
||||
static char* add_to_path(const char* path, const char* str, bool prepend);
|
||||
static char* add_jars_to_path(char* path, const char* directory);
|
||||
|
||||
inline void reset_item_at(int index);
|
||||
|
||||
// Array indices for the items that make up the sysclasspath. All except the
|
||||
// base are allocated in the C heap and freed by this class.
|
||||
enum {
|
||||
_bcp_prefix, // was -Xpatch:...
|
||||
_bcp_base, // the default system boot class path
|
||||
_bcp_suffix, // from -Xbootclasspath/a:...
|
||||
_bcp_nitems // the number of items, must be last.
|
||||
};
|
||||
|
||||
const char* _items[_bcp_nitems];
|
||||
};
|
||||
|
||||
ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
|
||||
memset(_items, 0, sizeof(_items));
|
||||
_items[_bcp_base] = base;
|
||||
}
|
||||
|
||||
ArgumentBootClassPath::~ArgumentBootClassPath() {
|
||||
// Free everything except the base.
|
||||
for (int i = 0; i < _bcp_nitems; ++i) {
|
||||
if (i != _bcp_base) reset_item_at(i);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::set_base(const char* base) {
|
||||
_items[_bcp_base] = base;
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
|
||||
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
|
||||
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
|
||||
_items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::reset_item_at(int index) {
|
||||
assert(index < _bcp_nitems && index != _bcp_base, "just checking");
|
||||
if (_items[index] != NULL) {
|
||||
FREE_C_HEAP_ARRAY(char, _items[index]);
|
||||
_items[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ArgumentBootClassPath::reset_path(const char* base) {
|
||||
// Clear the prefix and suffix.
|
||||
reset_item_at(_bcp_prefix);
|
||||
reset_item_at(_bcp_suffix);
|
||||
set_base(base);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Combine the bootclasspath elements, some of which may be null, into a single
|
||||
// c-heap-allocated string.
|
||||
char* ArgumentBootClassPath::combined_path() {
|
||||
assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
|
||||
|
||||
size_t lengths[_bcp_nitems];
|
||||
size_t total_len = 0;
|
||||
|
||||
const char separator = *os::path_separator();
|
||||
|
||||
// Get the lengths.
|
||||
int i;
|
||||
for (i = 0; i < _bcp_nitems; ++i) {
|
||||
if (i == _bcp_suffix) {
|
||||
// Record index of boot loader's append path.
|
||||
Arguments::set_bootclassloader_append_index((int)total_len);
|
||||
}
|
||||
if (_items[i] != NULL) {
|
||||
lengths[i] = strlen(_items[i]);
|
||||
// Include space for the separator char (or a NULL for the last item).
|
||||
total_len += lengths[i] + 1;
|
||||
}
|
||||
}
|
||||
assert(total_len > 0, "empty sysclasspath not allowed");
|
||||
|
||||
// Copy the _items to a single string.
|
||||
char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments);
|
||||
char* cp_tmp = cp;
|
||||
for (i = 0; i < _bcp_nitems; ++i) {
|
||||
if (_items[i] != NULL) {
|
||||
memcpy(cp_tmp, _items[i], lengths[i]);
|
||||
cp_tmp += lengths[i];
|
||||
*cp_tmp++ = separator;
|
||||
}
|
||||
}
|
||||
*--cp_tmp = '\0'; // Replace the extra separator.
|
||||
return cp;
|
||||
}
|
||||
|
||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
||||
char*
|
||||
ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
|
||||
char *cp;
|
||||
|
||||
assert(str != NULL, "just checking");
|
||||
if (path == NULL) {
|
||||
size_t len = strlen(str) + 1;
|
||||
cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
||||
memcpy(cp, str, len); // copy the trailing null
|
||||
} else {
|
||||
const char separator = *os::path_separator();
|
||||
size_t old_len = strlen(path);
|
||||
size_t str_len = strlen(str);
|
||||
size_t len = old_len + str_len + 2;
|
||||
|
||||
if (prepend) {
|
||||
cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
||||
char* cp_tmp = cp;
|
||||
memcpy(cp_tmp, str, str_len);
|
||||
cp_tmp += str_len;
|
||||
*cp_tmp = separator;
|
||||
memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null
|
||||
FREE_C_HEAP_ARRAY(char, path);
|
||||
} else {
|
||||
cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments);
|
||||
char* cp_tmp = cp + old_len;
|
||||
*cp_tmp = separator;
|
||||
memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
// Scan the directory and append any jar or zip files found to path.
|
||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
||||
char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
|
||||
DIR* dir = os::opendir(directory);
|
||||
if (dir == NULL) return path;
|
||||
|
||||
char dir_sep[2] = { '\0', '\0' };
|
||||
size_t directory_len = strlen(directory);
|
||||
const char fileSep = *os::file_separator();
|
||||
if (directory[directory_len - 1] != fileSep) dir_sep[0] = fileSep;
|
||||
|
||||
/* Scan the directory for jars/zips, appending them to path. */
|
||||
struct dirent *entry;
|
||||
char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments);
|
||||
while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
|
||||
const char* name = entry->d_name;
|
||||
const char* ext = name + strlen(name) - 4;
|
||||
bool isJarOrZip = ext > name &&
|
||||
(os::file_name_strcmp(ext, ".jar") == 0 ||
|
||||
os::file_name_strcmp(ext, ".zip") == 0);
|
||||
if (isJarOrZip) {
|
||||
char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments);
|
||||
sprintf(jarpath, "%s%s%s", directory, dir_sep, name);
|
||||
path = add_to_path(path, jarpath, false);
|
||||
FREE_C_HEAP_ARRAY(char, jarpath);
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, dbuf);
|
||||
os::closedir(dir);
|
||||
return path;
|
||||
}
|
||||
|
||||
// Parses a size specification string.
|
||||
bool Arguments::atojulong(const char *s, julong* result) {
|
||||
julong n = 0;
|
||||
@ -2724,9 +2525,7 @@ Arguments::ArgsRange Arguments::parse_memory_size(const char* s,
|
||||
jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
const JavaVMInitArgs *java_options_args,
|
||||
const JavaVMInitArgs *cmd_line_args) {
|
||||
// For components of the system classpath.
|
||||
ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
|
||||
bool bcp_assembly_required = false;
|
||||
bool xpatch_javabase = false;
|
||||
|
||||
// Save default settings for some mode flags
|
||||
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
||||
@ -2743,29 +2542,26 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
|
||||
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
||||
// variable (if present).
|
||||
jint result = parse_each_vm_init_arg(
|
||||
java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
||||
jint result = parse_each_vm_init_arg(java_tool_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse args structure generated from the command line flags.
|
||||
result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
|
||||
Flag::COMMAND_LINE);
|
||||
result = parse_each_vm_init_arg(cmd_line_args, &xpatch_javabase, Flag::COMMAND_LINE);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse args structure generated from the _JAVA_OPTIONS environment
|
||||
// variable (if present) (mimics classic VM)
|
||||
result = parse_each_vm_init_arg(
|
||||
java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
||||
result = parse_each_vm_init_arg(java_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Do final processing now that all arguments have been parsed
|
||||
result = finalize_vm_init_args(&bcp, bcp_assembly_required);
|
||||
result = finalize_vm_init_args();
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -2818,10 +2614,7 @@ bool valid_jdwp_agent(char *name, bool is_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
ArgumentBootClassPath* bcp_p,
|
||||
bool* bcp_assembly_required_p,
|
||||
Flag::Flags origin) {
|
||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin) {
|
||||
// For match_option to return remaining or value part of option string
|
||||
const char* tail;
|
||||
|
||||
@ -2877,8 +2670,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_EINVAL;
|
||||
// -bootclasspath/a:
|
||||
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
|
||||
bcp_p->add_suffix(tail);
|
||||
*bcp_assembly_required_p = true;
|
||||
Arguments::set_bootclassloader_append_index((int)strlen(Arguments::get_sysclasspath())+1);
|
||||
Arguments::append_sysclasspath(tail);
|
||||
// -bootclasspath/p:
|
||||
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
|
||||
jio_fprintf(defaultStream::output_stream(),
|
||||
@ -2938,9 +2731,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
if (tail != NULL) {
|
||||
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
|
||||
add_init_agent("instrument", options, false);
|
||||
// java agents need module java.instrument. Also -addmods ALL-SYSTEM because
|
||||
// the java agent is in the unmamed module of the application class loader
|
||||
if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
|
||||
// java agents need module java.instrument
|
||||
if (!Arguments::append_to_addmods_property("java.instrument")) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
}
|
||||
@ -3218,37 +3010,30 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_ERR;
|
||||
#endif
|
||||
}
|
||||
if (match_option(option, "-Djdk.launcher.patch.0=", &tail)) {
|
||||
// -Xpatch
|
||||
int dir_count;
|
||||
char** patch_dirs = os::split_path(tail, &dir_count);
|
||||
if (patch_dirs == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(),
|
||||
"Bad value for -Xpatch.\n");
|
||||
if (match_option(option, "-Djdk.launcher.patch.", &tail)) {
|
||||
// -Djdk.launcher.patch.#=<module>=<file>(<pathsep><file>)*
|
||||
// The number, #, specified will be increasing with each -Xpatch
|
||||
// specified on the command line.
|
||||
// Pick up module name, following the -D property's equal sign.
|
||||
const char* property_equal = strchr(tail, '=');
|
||||
if (property_equal == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(), "Missing '=' in -Xpatch specification\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
set_patch_dirs(patch_dirs);
|
||||
set_patch_dirs_count(dir_count);
|
||||
|
||||
// Create a path for each patch dir consisting of dir/java.base.
|
||||
char file_sep = os::file_separator()[0];
|
||||
for (int x = 0; x < dir_count; x++) {
|
||||
// Really shouldn't be NULL, but check can't hurt
|
||||
if (patch_dirs[x] != NULL) {
|
||||
size_t len = strlen(patch_dirs[x]);
|
||||
if (len != 0) { // Ignore empty strings.
|
||||
len += 11; // file_sep + "java.base" + null terminator.
|
||||
char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
||||
jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
|
||||
|
||||
// See if Xpatch module path exists.
|
||||
struct stat st;
|
||||
if ((os::stat(dir, &st) == 0)) {
|
||||
bcp_p->add_prefix(dir);
|
||||
*bcp_assembly_required_p = true;
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, dir);
|
||||
}
|
||||
} else {
|
||||
// Find the equal sign between the module name and the path specification
|
||||
const char* module_equal = strchr(property_equal + 1, '=');
|
||||
if (module_equal == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(), "Bad value for -Xpatch, no module name specified\n");
|
||||
return JNI_ERR;
|
||||
} else {
|
||||
// Pick out the module name, in between the two equal signs
|
||||
size_t module_len = module_equal - property_equal - 1;
|
||||
char* module_name = NEW_C_HEAP_ARRAY(char, module_len+1, mtArguments);
|
||||
memcpy(module_name, property_equal + 1, module_len);
|
||||
*(module_name + module_len) = '\0';
|
||||
// The path piece begins one past the module_equal sign
|
||||
Arguments::add_xpatchprefix(module_name, module_equal + 1, xpatch_javabase);
|
||||
FREE_C_HEAP_ARRAY(char, module_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3511,6 +3296,27 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
void Arguments::add_xpatchprefix(const char* module_name, const char* path, bool* xpatch_javabase) {
|
||||
// For java.base check for duplicate -Xpatch options being specified on the command line.
|
||||
// This check is only required for java.base, all other duplicate module specifications
|
||||
// will be checked during module system initialization. The module system initialization
|
||||
// will throw an ExceptionInInitializerError if this situation occurs.
|
||||
if (strcmp(module_name, "java.base") == 0) {
|
||||
if (*xpatch_javabase) {
|
||||
vm_exit_during_initialization("Cannot specify java.base more than once to -Xpatch");
|
||||
} else {
|
||||
*xpatch_javabase = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create GrowableArray lazily, only if -Xpatch has been specified
|
||||
if (_xpatchprefix == NULL) {
|
||||
_xpatchprefix = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<ModuleXPatchPath*>(10, true);
|
||||
}
|
||||
|
||||
_xpatchprefix->push(new ModuleXPatchPath(module_name, path));
|
||||
}
|
||||
|
||||
// Set property jdk.boot.class.path.append to the contents of the bootclasspath
|
||||
// that follows either the jimage file or exploded module directories. The
|
||||
// property will contain -Xbootclasspath/a and/or jvmti appended additions.
|
||||
@ -3609,7 +3415,7 @@ static int check_non_empty_dirs(const char* path) {
|
||||
return nonEmptyDirs;
|
||||
}
|
||||
|
||||
jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
|
||||
jint Arguments::finalize_vm_init_args() {
|
||||
// check if the default lib/endorsed directory exists; if so, error
|
||||
char path[JVM_MAXPATHLEN];
|
||||
const char* fileSep = os::file_separator();
|
||||
@ -3645,17 +3451,7 @@ jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_ass
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
if (bcp_assembly_required) {
|
||||
// Assemble the bootclasspath elements into the final path.
|
||||
char *combined_path = bcp_p->combined_path();
|
||||
Arguments::set_sysclasspath(combined_path);
|
||||
FREE_C_HEAP_ARRAY(char, combined_path);
|
||||
} else {
|
||||
// At this point in sysclasspath processing anything
|
||||
// added would be considered in the boot loader's append path.
|
||||
// Record this index, including +1 for the file separator character.
|
||||
Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
|
||||
}
|
||||
Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
|
||||
|
||||
// This must be done after all arguments have been processed.
|
||||
// java_compiler() true means set to "NONE" or empty.
|
||||
@ -3704,6 +3500,12 @@ jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_ass
|
||||
UNSUPPORTED_OPTION(TieredCompilation);
|
||||
#endif
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (EnableJVMCI && !append_to_addmods_property("jdk.vm.ci")) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we are running in a headless jre, force java.awt.headless property
|
||||
// to be true unless the property has already been set.
|
||||
// Also allow the OS environment variable JAVA_AWT_HEADLESS to set headless state.
|
||||
@ -4005,7 +3807,7 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
|
||||
|
||||
void Arguments::set_shared_spaces_flags() {
|
||||
if (DumpSharedSpaces) {
|
||||
if (Arguments::patch_dirs() != NULL) {
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
vm_exit_during_initialization(
|
||||
"Cannot use the following option when dumping the shared archive", "-Xpatch");
|
||||
}
|
||||
|
@ -41,17 +41,15 @@ extern "C" {
|
||||
typedef jint (JNICALL *vfprintf_hook_t)(FILE *fp, const char *format, va_list args) ATTRIBUTE_PRINTF(2, 0);
|
||||
}
|
||||
|
||||
// Forward declarations
|
||||
class ArgumentBootClassPath;
|
||||
|
||||
// PathString is used as the underlying value container for a
|
||||
// SystemProperty and for the string that represents the system
|
||||
// boot class path, Arguments::_system_boot_class_path.
|
||||
// PathString is used as:
|
||||
// - the underlying value for a SystemProperty
|
||||
// - the path portion of an -Xpatch module/path pair
|
||||
// - the string that represents the system boot class path, Arguments::_system_boot_class_path.
|
||||
class PathString : public CHeapObj<mtArguments> {
|
||||
protected:
|
||||
char* _value;
|
||||
char* _value;
|
||||
public:
|
||||
char* value() const { return _value; }
|
||||
char* value() const { return _value; }
|
||||
|
||||
bool set_value(const char *value) {
|
||||
if (_value != NULL) {
|
||||
@ -92,7 +90,6 @@ class PathString : public CHeapObj<mtArguments> {
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor
|
||||
PathString(const char* value) {
|
||||
if (value == NULL) {
|
||||
_value = NULL;
|
||||
@ -101,6 +98,43 @@ class PathString : public CHeapObj<mtArguments> {
|
||||
strcpy(_value, value);
|
||||
}
|
||||
}
|
||||
|
||||
~PathString() {
|
||||
if (_value != NULL) {
|
||||
FreeHeap(_value);
|
||||
_value = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ModuleXPatchPath records the module/path pair as specified to -Xpatch.
|
||||
class ModuleXPatchPath : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
char* _module_name;
|
||||
PathString* _path;
|
||||
public:
|
||||
ModuleXPatchPath(const char* module_name, const char* path) {
|
||||
assert(module_name != NULL && path != NULL, "Invalid module name or path value");
|
||||
size_t len = strlen(module_name) + 1;
|
||||
_module_name = AllocateHeap(len, mtInternal);
|
||||
strncpy(_module_name, module_name, len); // copy the trailing null
|
||||
_path = new PathString(path);
|
||||
}
|
||||
|
||||
~ModuleXPatchPath() {
|
||||
if (_module_name != NULL) {
|
||||
FreeHeap(_module_name);
|
||||
_module_name = NULL;
|
||||
}
|
||||
if (_path != NULL) {
|
||||
delete _path;
|
||||
_path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_path(const char* path) { _path->set_value(path); }
|
||||
inline const char* module_name() const { return _module_name; }
|
||||
inline char* path_string() const { return _path->value(); }
|
||||
};
|
||||
|
||||
// Element describing System and User (-Dkey=value flags) defined property.
|
||||
@ -114,7 +148,7 @@ class SystemProperty : public PathString {
|
||||
SystemProperty* _next;
|
||||
bool _internal;
|
||||
bool _writeable;
|
||||
bool writeable() { return _writeable; }
|
||||
bool writeable() { return _writeable; }
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
@ -314,10 +348,19 @@ class Arguments : AllStatic {
|
||||
static SystemProperty *_java_class_path;
|
||||
static SystemProperty *_jdk_boot_class_path_append;
|
||||
|
||||
// -Xpatch:module=<file>(<pathsep><file>)*
|
||||
// Each element contains the associated module name, path
|
||||
// string pair as specified to -Xpatch.
|
||||
static GrowableArray<ModuleXPatchPath*>* _xpatchprefix;
|
||||
|
||||
// The constructed value of the system class path after
|
||||
// argument processing and JVMTI OnLoad additions via
|
||||
// calls to AddToBootstrapClassLoaderSearch. This is the
|
||||
// final form before ClassLoader::setup_bootstrap_search().
|
||||
// Note: since -Xpatch is a module name/path pair, the system
|
||||
// boot class path string no longer contains the "prefix" to
|
||||
// the boot class path base piece as it did when
|
||||
// -Xbootclasspath/p was supported.
|
||||
static PathString *_system_boot_class_path;
|
||||
|
||||
// temporary: to emit warning if the default ext dirs are not empty.
|
||||
@ -373,12 +416,6 @@ class Arguments : AllStatic {
|
||||
// mark the boot loader's append path observability boundary.
|
||||
static int _bootclassloader_append_index;
|
||||
|
||||
// -Xpatch flag
|
||||
static char** _patch_dirs;
|
||||
static int _patch_dirs_count;
|
||||
static void set_patch_dirs(char** dirs) { _patch_dirs = dirs; }
|
||||
static void set_patch_dirs_count(int count) { _patch_dirs_count = count; }
|
||||
|
||||
// -Xdebug flag
|
||||
static bool _xdebug_mode;
|
||||
static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
|
||||
@ -465,8 +502,8 @@ class Arguments : AllStatic {
|
||||
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
const JavaVMInitArgs *java_options_args,
|
||||
const JavaVMInitArgs *cmd_line_args);
|
||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, ArgumentBootClassPath* bcp_p, bool* bcp_assembly_required_p, Flag::Flags origin);
|
||||
static jint finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required);
|
||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin);
|
||||
static jint finalize_vm_init_args();
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
|
||||
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
|
||||
@ -637,13 +674,12 @@ class Arguments : AllStatic {
|
||||
return _bootclassloader_append_index;
|
||||
}
|
||||
static void set_bootclassloader_append_index(int value) {
|
||||
_bootclassloader_append_index = value;
|
||||
// Set only if the index has not been set yet
|
||||
if (_bootclassloader_append_index == -1) {
|
||||
_bootclassloader_append_index = value;
|
||||
}
|
||||
}
|
||||
|
||||
// -Xpatch
|
||||
static char** patch_dirs() { return _patch_dirs; }
|
||||
static int patch_dirs_count() { return _patch_dirs_count; }
|
||||
|
||||
// -Xrun
|
||||
static AgentLibrary* libraries() { return _libraryList.first(); }
|
||||
static bool init_libraries_at_startup() { return !_libraryList.is_empty(); }
|
||||
@ -701,8 +737,8 @@ class Arguments : AllStatic {
|
||||
static void set_library_path(const char *value) { _java_library_path->set_value(value); }
|
||||
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
|
||||
|
||||
// Set up of the underlying system boot class path
|
||||
static void set_jdkbootclasspath_append();
|
||||
// Set up the underlying pieces of the system boot class path
|
||||
static void add_xpatchprefix(const char *module_name, const char *path, bool* xpatch_javabase);
|
||||
static void set_sysclasspath(const char *value) {
|
||||
_system_boot_class_path->set_value(value);
|
||||
set_jdkbootclasspath_append();
|
||||
@ -711,11 +747,15 @@ class Arguments : AllStatic {
|
||||
_system_boot_class_path->append_value(value);
|
||||
set_jdkbootclasspath_append();
|
||||
}
|
||||
static void set_jdkbootclasspath_append();
|
||||
|
||||
static char* get_java_home() { return _java_home->value(); }
|
||||
static char* get_dll_dir() { return _sun_boot_library_path->value(); }
|
||||
static GrowableArray<ModuleXPatchPath*>* get_xpatchprefix() { return _xpatchprefix; }
|
||||
static char* get_sysclasspath() { return _system_boot_class_path->value(); }
|
||||
static char* get_ext_dirs() { return _ext_dirs; }
|
||||
static char* get_jdk_boot_class_path_append() { return _jdk_boot_class_path_append->value(); }
|
||||
|
||||
static char* get_java_home() { return _java_home->value(); }
|
||||
static char* get_dll_dir() { return _sun_boot_library_path->value(); }
|
||||
static char* get_ext_dirs() { return _ext_dirs; }
|
||||
static char* get_appclasspath() { return _java_class_path->value(); }
|
||||
static void fix_appclasspath();
|
||||
|
||||
|
@ -52,7 +52,8 @@ void SuspendibleThreadSet_init() NOT_ALL_GCS_RETURN;
|
||||
// Initialization done by Java thread in init_globals()
|
||||
void management_init();
|
||||
void bytecodes_init();
|
||||
void classLoader_init();
|
||||
void classLoader_init1();
|
||||
void classLoader_init2(); // note: ClassLoader need 2-phase init
|
||||
void compilationPolicy_init();
|
||||
void codeCache_init();
|
||||
void VM_Version_init();
|
||||
@ -102,7 +103,7 @@ jint init_globals() {
|
||||
HandleMark hm;
|
||||
management_init();
|
||||
bytecodes_init();
|
||||
classLoader_init();
|
||||
classLoader_init1();
|
||||
compilationPolicy_init();
|
||||
codeCache_init();
|
||||
CodeCacheExtensions::initialize();
|
||||
@ -116,6 +117,7 @@ jint init_globals() {
|
||||
if (status != JNI_OK)
|
||||
return status;
|
||||
|
||||
classLoader_init2(); // after SymbolTable creation, set up -Xpatch entries
|
||||
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Universe);
|
||||
interpreter_init(); // before any methods loaded
|
||||
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Interpreter);
|
||||
|
@ -1762,6 +1762,21 @@ methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, TRAPS) {
|
||||
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,
|
||||
|
@ -522,6 +522,8 @@ class SharedRuntime: AllStatic {
|
||||
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
|
||||
|
@ -55,7 +55,6 @@ address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
|
||||
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;
|
||||
|
@ -111,7 +111,6 @@ class StubRoutines: AllStatic {
|
||||
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 @@ class StubRoutines: AllStatic {
|
||||
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; }
|
||||
|
@ -36,9 +36,12 @@ groups=TEST.groups [closed/TEST.groups]
|
||||
requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java
|
||||
requires.properties=sun.arch.data.model
|
||||
|
||||
# Tests using jtreg 4.2 b01 features
|
||||
requiredVersion=4.2 b01
|
||||
# Tests using jtreg 4.2 b02 features
|
||||
requiredVersion=4.2 b02
|
||||
|
||||
# Path to libraries in the topmost test directory. This is needed so @library
|
||||
# does not need ../../ notation to reach them
|
||||
external.lib.roots = ../../
|
||||
|
||||
# Use new form of -Xpatch
|
||||
useNewXpatch=true
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
|
@ -40,6 +40,7 @@
|
||||
* -XX:CompileCommand=dontinline,UnsafeGetConstantField.checkGetAddress()
|
||||
* -XX:CompileCommand=dontinline,*.test*
|
||||
* -XX:+UseUnalignedAccesses
|
||||
* -XaddReads:java.base=ALL-UNNAMED
|
||||
* compiler.unsafe.UnsafeGetConstantField
|
||||
*
|
||||
* @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions
|
||||
@ -49,6 +50,7 @@
|
||||
* -XX:CompileCommand=dontinline,*.test*
|
||||
* -XX:CompileCommand=inline,*Unsafe.get*
|
||||
* -XX:-UseUnalignedAccesses
|
||||
* -XaddReads:java.base=ALL-UNNAMED
|
||||
* compiler.unsafe.UnsafeGetConstantField
|
||||
*/
|
||||
package compiler.unsafe;
|
||||
|
@ -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
|
||||
@ -48,7 +48,7 @@ public class BootstrapRedefine {
|
||||
"-Xmodule:java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods", "-version");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base", "-version");
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("Incompatible definition of java.lang.Object")
|
||||
.shouldHaveExitValue(1);
|
||||
|
@ -120,9 +120,9 @@ public class GetSysPkgTest {
|
||||
getPkg("java/nio/charset", "jrt:/java.base");
|
||||
|
||||
// Test a package in a module not owned by boot loader.
|
||||
Class clss = Class.forName("javax.activation.DataHandler");
|
||||
Class clss = Class.forName("jdk.nio.zipfs.ZipPath");
|
||||
if (clss == null)
|
||||
throw new RuntimeException("Could not find class javax.activation.DataHandler");
|
||||
throw new RuntimeException("Could not find class jdk.nio.zipfs.ZipPath");
|
||||
getPkg("javax/activation", null); // Not owned by boot loader
|
||||
|
||||
// Test a package not in jimage file.
|
||||
|
@ -210,9 +210,9 @@ public class DiffCL_Umod {
|
||||
// now use the same loader to load class p1.c1Loose
|
||||
Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1Loose");
|
||||
|
||||
// change m1 to be a loose module
|
||||
// change m1 to read all unnamed modules
|
||||
Module m1 = layer.findModule("m1").get();
|
||||
jdk.internal.module.Modules.addReads(m1, null);
|
||||
jdk.internal.module.Modules.addReadsAllUnnamed(m1);
|
||||
|
||||
try {
|
||||
p1_c1_class.newInstance();
|
||||
|
@ -201,9 +201,9 @@ public class Umod {
|
||||
// now use the same loader to load class p1.c1Loose
|
||||
Class p1_c1_class = loader.loadClass("p1.c1Loose");
|
||||
|
||||
// change m1 to be a loose module
|
||||
// change m1 to read all unnamed modules
|
||||
Module m1 = layer.findModule("m1").get();
|
||||
jdk.internal.module.Modules.addReads(m1, null);
|
||||
jdk.internal.module.Modules.addReadsAllUnnamed(m1);
|
||||
|
||||
try {
|
||||
p1_c1_class.newInstance();
|
||||
|
@ -49,26 +49,27 @@ public class JVMAddReadsModule {
|
||||
assertNotNull(to_module, "Module should not be null");
|
||||
ModuleHelper.DefineModule(to_module, "9.0", "to_module/here", new String[] { "yourpackage" });
|
||||
|
||||
// Null from_module argument, expect an NPE
|
||||
// Null from_module argument, expect NPE
|
||||
try {
|
||||
ModuleHelper.AddReadsModule(null, to_module);
|
||||
throw new RuntimeException("Failed to get the expected NPE");
|
||||
} catch(NullPointerException e) {
|
||||
} catch (NullPointerException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Null to_module argument, do not expect an NPE
|
||||
// Null to_module argument, expect NPE
|
||||
try {
|
||||
ModuleHelper.AddReadsModule(from_module, null);
|
||||
} catch(NullPointerException e) {
|
||||
throw new RuntimeException("Unexpected NPE was thrown");
|
||||
} catch (NullPointerException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
// Null from_module and to_module arguments, expect an NPE
|
||||
// Null from_module and to_module arguments, expect NPE
|
||||
try {
|
||||
ModuleHelper.AddReadsModule(null, null);
|
||||
throw new RuntimeException("Failed to get the expected NPE");
|
||||
} catch(NullPointerException e) {
|
||||
} catch (NullPointerException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
@ -83,7 +83,7 @@ public class XpatchVisibility {
|
||||
"p2" + File.separator + "Vis2_B.class"));
|
||||
|
||||
new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:mods2",
|
||||
"-Xpatch:java.base=mods2/java.base",
|
||||
"-XaddExports:java.base/p2=ALL-UNNAMED",
|
||||
"Vis2_A")
|
||||
.start()).shouldHaveExitValue(0);
|
||||
|
96
hotspot/test/runtime/modules/Xpatch/BasicJarBuilder.java
Normal file
96
hotspot/test/runtime/modules/Xpatch/BasicJarBuilder.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @summary Simple jar builder
|
||||
* Input: jarName className1 className2 ...
|
||||
* do not specify extensions, just the names
|
||||
* E.g. prot_domain ProtDomainA ProtDomainB
|
||||
* Output: A jar containing compiled classes, placed in a test classes folder
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import sun.tools.jar.Main;
|
||||
|
||||
// Using JarBuilder requires that all to-be-jarred classes should be placed
|
||||
// in the current working directory, aka "."
|
||||
public class BasicJarBuilder {
|
||||
private static final String classDir = System.getProperty("test.classes");
|
||||
|
||||
public static void build(boolean classesInWorkDir, String jarName,
|
||||
String ...classNames) throws Exception {
|
||||
|
||||
if (classesInWorkDir) {
|
||||
createSimpleJar(".", classDir + File.separator + jarName + ".jar", classNames);
|
||||
} else {
|
||||
build(jarName, classNames);
|
||||
}
|
||||
}
|
||||
|
||||
public static void build(String jarName, String ...classNames) throws Exception {
|
||||
createSimpleJar(classDir, classDir + File.separator + jarName + ".jar",
|
||||
classNames);
|
||||
}
|
||||
|
||||
private static void createSimpleJar(String jarclassDir, String jarName,
|
||||
String[] classNames) throws Exception {
|
||||
ArrayList<String> args = new ArrayList<String>();
|
||||
args.add("cf");
|
||||
args.add(jarName);
|
||||
addClassArgs(args, jarclassDir, classNames);
|
||||
createJar(args);
|
||||
}
|
||||
|
||||
private static void addClassArgs(ArrayList<String> args, String jarclassDir,
|
||||
String[] classNames) {
|
||||
|
||||
for (String name : classNames) {
|
||||
args.add("-C");
|
||||
args.add(jarclassDir);
|
||||
args.add(name + ".class");
|
||||
}
|
||||
}
|
||||
|
||||
private static void createJar(ArrayList<String> args) {
|
||||
Main jarTool = new Main(System.out, System.err, "jar");
|
||||
if (!jarTool.run(args.toArray(new String[1]))) {
|
||||
throw new RuntimeException("jar operation failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Get full path to the test jar
|
||||
public static String getTestJar(String jar) {
|
||||
File dir = new File(System.getProperty("test.classes", "."));
|
||||
File jarFile = new File(dir, jar);
|
||||
if (!jarFile.exists()) {
|
||||
throw new RuntimeException("Cannot find " + jarFile.getPath());
|
||||
}
|
||||
if (!jarFile.isFile()) {
|
||||
throw new RuntimeException("Not a regular file: " + jarFile.getPath());
|
||||
}
|
||||
return jarFile.getPath();
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -58,7 +58,8 @@ public class Xpatch2Dirs {
|
||||
"mods2/java.desktop");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:mods" + File.pathSeparator + "mods2",
|
||||
"-Xpatch:java.naming=mods/java.naming",
|
||||
"-Xpatch:java.desktop=mods2/java.desktop",
|
||||
"Xpatch2DirsMain", "javax.naming.spi.NamingManager", "java.beans.Encoder");
|
||||
|
||||
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
|
||||
|
45
hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java
Normal file
45
hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary VM exit initialization results if java.base is specificed more than once to Xpatch.
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchDupJavaBase {
|
||||
// The VM should exit initialization if java.base is specified
|
||||
// more than once to -Xpatch.
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:java.base=javabase_dir",
|
||||
"-Xpatch:java.base=javabase_dir",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Cannot specify java.base more than once to -Xpatch");
|
||||
output.shouldHaveExitValue(1);
|
||||
}
|
||||
}
|
||||
|
47
hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java
Normal file
47
hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Module system initialization exception results if a module is specificed twice to Xpatch.
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchDupModule {
|
||||
|
||||
// The module system initialization should generate an ExceptionInInitializerError
|
||||
// if -Xpatch is specified with the same module more than once.
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:module1=module1_dir",
|
||||
"-Xpatch:module1=module1_dir",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("java.lang.ExceptionInInitializerError");
|
||||
output.shouldHaveExitValue(1);
|
||||
}
|
||||
}
|
||||
|
56
hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java
Normal file
56
hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8130399
|
||||
* @summary Make sure -Xpatch works for java.base.
|
||||
* @library /testlibrary
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchJavaBase
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchJavaBase {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String source = "package java.lang; " +
|
||||
"public class NewClass { " +
|
||||
" static { " +
|
||||
" System.out.println(\"I pass!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("java/lang/NewClass",
|
||||
InMemoryJavaCompiler.compile("java.lang.NewClass", source, "-Xmodule:java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base",
|
||||
"XpatchMain", "java.lang.NewClass");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass!")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -47,7 +47,7 @@ public class XpatchTest {
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
|
||||
"XpatchMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
|
83
hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java
Normal file
83
hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Make sure -Xpatch works when a jar file is specified for a module
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build BasicJarBuilder
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchTestJar
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTestJar {
|
||||
private static String moduleJar;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Create a class file in the module java.naming. This class file
|
||||
// will be put in the javanaming.jar file.
|
||||
String source = "package javax.naming.spi; " +
|
||||
"public class NamingManager { " +
|
||||
" static { " +
|
||||
" System.out.println(\"I pass!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.naming".
|
||||
BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
|
||||
moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
|
||||
|
||||
// Just to make sure we are not fooled by the class file being on the
|
||||
// class path where all the test classes are stored, write the NamingManager.class
|
||||
// file out again with output that does not contain what OutputAnalyzer
|
||||
// expects. This will provide confidence that the contents of the class
|
||||
// is truly coming from the jar file and not the class file.
|
||||
source = "package javax.naming.spi; " +
|
||||
"public class NamingManager { " +
|
||||
" static { " +
|
||||
" System.out.println(\"Fail!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Supply -Xpatch with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" + moduleJar,
|
||||
"XpatchMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass!")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
105
hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java
Normal file
105
hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Make sure -Xpatch works when a jar file and a directory is specified for a module
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build BasicJarBuilder
|
||||
* @compile Xpatch2DirsMain.java
|
||||
* @run main XpatchTestJarDir
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTestJarDir {
|
||||
private static String moduleJar;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Create a class file in the module java.naming. This class file
|
||||
// will be put in the javanaming.jar file.
|
||||
String source = "package javax.naming.spi; " +
|
||||
"public class NamingManager1 { " +
|
||||
" static { " +
|
||||
" System.out.println(\"I pass one!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.naming".
|
||||
BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager1");
|
||||
moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
|
||||
|
||||
// Just to make sure we are not fooled by the class file being on the
|
||||
// class path where all the test classes are stored, write the NamingManager.class
|
||||
// file out again with output that does not contain what OutputAnalyzer
|
||||
// expects. This will provide confidence that the contents of the class
|
||||
// is truly coming from the jar file and not the class file.
|
||||
source = "package javax.naming.spi; " +
|
||||
"public class NamingManager1 { " +
|
||||
" static { " +
|
||||
" System.out.println(\"Fail!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Create a second class file in the module java.naming. This class file
|
||||
// will be put in the mods/java.naming directory.
|
||||
source = "package javax.naming.spi; " +
|
||||
"public class NamingManager2 { " +
|
||||
" static { " +
|
||||
" System.out.println(\"I pass two!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager2",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "-Xmodule:java.naming"),
|
||||
(System.getProperty("test.classes") + "/mods/java.naming"));
|
||||
|
||||
|
||||
// Supply -Xpatch with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" +
|
||||
moduleJar +
|
||||
File.pathSeparator +
|
||||
System.getProperty("test.classes") + "/mods/java.naming",
|
||||
"Xpatch2DirsMain",
|
||||
"javax.naming.spi.NamingManager1",
|
||||
"javax.naming.spi.NamingManager2");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass one!")
|
||||
.shouldContain("I pass two!")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8069469
|
||||
* @summary Make sure -XX:+TraceClassLoading works properly with "modules" jimage,
|
||||
* @summary Make sure -Xlog:classload=info works properly with "modules" jimage,
|
||||
-Xpatch, and with -Xbootclasspath/a
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
@ -45,24 +45,23 @@ public class XpatchTraceCL {
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
// Test -XX:+TraceClassLoading output for -Xpatch
|
||||
// Test -Xlog:classload=info output for -Xpatch
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
|
||||
"-XX:+TraceClassLoading", "XpatchMain", "javax.naming.spi.NamingManager");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
|
||||
"-Xlog:class+load=info", "XpatchMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
// "modules" jimage case.
|
||||
output.shouldContain("[class,load] java.lang.Thread source: jrt:/java.base");
|
||||
// -Xpatch case.
|
||||
output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods" +
|
||||
File.separator + "java.naming");
|
||||
output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods/java.naming");
|
||||
// -cp case.
|
||||
output.shouldContain("[class,load] XpatchMain source: file");
|
||||
|
||||
// Test -XX:+TraceClassLoading output for -Xbootclasspath/a
|
||||
// Test -Xlog:classload=info output for -Xbootclasspath/a
|
||||
source = "package XpatchTraceCL_pkg; " +
|
||||
"public class ItIsI { " +
|
||||
" static { " +
|
||||
@ -75,7 +74,7 @@ public class XpatchTraceCL {
|
||||
"xbcp");
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:xbcp",
|
||||
"-XX:+TraceClassLoading", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
|
||||
"-Xlog:class+load=info", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
// -Xbootclasspath/a case.
|
||||
output.shouldContain("[class,load] XpatchTraceCL_pkg.ItIsI source: xbcp");
|
||||
|
@ -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
|
||||
@ -35,7 +35,7 @@ public class XpatchCDS {
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
System.out.println("Test that -Xpatch and -Xshare:dump are incompatibable");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:.", "-Xshare:dump");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming", "-Xshare:dump");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Cannot use the following option when dumping the shared archive: -Xpatch");
|
||||
|
||||
@ -52,7 +52,7 @@ public class XpatchCDS {
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=" + filename,
|
||||
"-Xshare:on",
|
||||
"-Xpatch:.",
|
||||
"-Xpatch:java.naming=mods/java.naming",
|
||||
"-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("The shared archive file cannot be used with -Xpatch");
|
||||
|
@ -94,22 +94,6 @@ public final class ProcessTools {
|
||||
return ProcessHandle.current().getPid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string containing input arguments passed to the VM
|
||||
*
|
||||
* @return arguments
|
||||
*/
|
||||
public static String getVmInputArguments() {
|
||||
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
|
||||
|
||||
List<String> args = runtime.getInputArguments();
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String arg : args)
|
||||
result.append(arg).append(' ');
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of strings containing input arguments passed to the VM
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user