This commit is contained in:
Vladimir Kozlov 2013-08-01 17:25:10 -07:00
commit f4c4fd7903
1070 changed files with 73926 additions and 38905 deletions

View file

@ -240,10 +240,10 @@ inline ConstantPoolCache** frame::interpreter_frame_cache_addr() const {
#endif // CC_INTERP
inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
// note: adjust this code if the link argument in StubGenerator::call_stub() changes!
const Argument link = Argument(0, false);
return (JavaCallWrapper*)sp()[link.as_in().as_register()->sp_offset_in_saved_window()];
return (JavaCallWrapper**)&sp()[link.as_in().as_register()->sp_offset_in_saved_window()];
}

View file

@ -410,6 +410,51 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// o0 = adr
// o1 = errValue
//
// result:
// o0 = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
__ align(CodeEntryAlignment);
*entry = __ pc();
__ mov(O0, G1); // g1 = o0
__ mov(O1, O0); // o0 = o1
// Load *adr into c_rarg1, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ ldsw(G1, 0, O0); // o0 = [g1]
break;
case 8:
// int64_t
__ ldx(G1, 0, O0); // o0 = [g1]
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
// By convention with the trap handler we ensure there is a non-CTI
// instruction in the trap shadow.
__ nop();
__ retl();
__ delayed()->nop();
}
//------------------------------------------------------------------------------------------------------------------------
// Continuation point for throwing of implicit exceptions that are not handled in
@ -3315,6 +3360,14 @@ class StubGenerator: public StubCodeGenerator {
// Don't initialize the platform math functions since sparc
// doesn't have intrinsics for these operations.
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}

View file

@ -272,11 +272,10 @@ inline jint frame::interpreter_frame_expression_stack_direction() { return -1; }
// Entry frames
inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
return (JavaCallWrapper*)at(entry_frame_call_wrapper_offset);
inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
return (JavaCallWrapper**)addr_at(entry_frame_call_wrapper_offset);
}
// Compiled frames
inline int frame::local_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors) {

View file

@ -2766,6 +2766,39 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
__ movl(rax, Address(rsp, 0x8));
__ movl(rcx, Address(rsp, 0x4));
// Load *adr into eax, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ movl(rax, Address(rcx, 0));
break;
case 8:
// int64_t
Unimplemented();
break;
default:
ShouldNotReachHere();
}
// Return errValue or *adr.
*continuation_pc = __ pc();
__ ret(0);
}
public:
// Information about frame layout at time of blocking runtime call.
@ -2978,6 +3011,14 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt();
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
StubRoutines::_safefetchN_entry = StubRoutines::_safefetch32_entry;
StubRoutines::_safefetchN_fault_pc = StubRoutines::_safefetch32_fault_pc;
StubRoutines::_safefetchN_continuation_pc = StubRoutines::_safefetch32_continuation_pc;
}

View file

@ -279,7 +279,7 @@ class StubGenerator: public StubCodeGenerator {
__ stmxcsr(mxcsr_save);
__ movl(rax, mxcsr_save);
__ andl(rax, MXCSR_MASK); // Only check control and mask bits
ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std());
ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std());
__ cmp32(rax, mxcsr_std);
__ jcc(Assembler::equal, skip_ldmx);
__ ldmxcsr(mxcsr_std);
@ -729,17 +729,18 @@ class StubGenerator: public StubCodeGenerator {
if (CheckJNICalls) {
Label ok_ret;
ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std());
__ push(rax);
__ subptr(rsp, wordSize); // allocate a temp location
__ stmxcsr(mxcsr_save);
__ movl(rax, mxcsr_save);
__ andl(rax, MXCSR_MASK); // Only check control and mask bits
__ cmpl(rax, *(int *)(StubRoutines::x86::mxcsr_std()));
__ cmp32(rax, mxcsr_std);
__ jcc(Assembler::equal, ok_ret);
__ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall");
__ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std()));
__ ldmxcsr(mxcsr_std);
__ bind(ok_ret);
__ addptr(rsp, wordSize);
@ -3357,7 +3358,45 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
// safefetch signatures:
// int SafeFetch32(int* adr, int errValue);
// intptr_t SafeFetchN (intptr_t* adr, intptr_t errValue);
//
// arguments:
// c_rarg0 = adr
// c_rarg1 = errValue
//
// result:
// PPC_RET = *adr or errValue
StubCodeMark mark(this, "StubRoutines", name);
// Entry point, pc or function descriptor.
*entry = __ pc();
// Load *adr into c_rarg1, may fault.
*fault_pc = __ pc();
switch (size) {
case 4:
// int32_t
__ movl(c_rarg1, Address(c_rarg0, 0));
break;
case 8:
// int64_t
__ movq(c_rarg1, Address(c_rarg0, 0));
break;
default:
ShouldNotReachHere();
}
// return errValue or *adr
*continuation_pc = __ pc();
__ movq(rax, c_rarg1);
__ ret(0);
}
// This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time
// to hide instruction latency
@ -3729,12 +3768,35 @@ class StubGenerator: public StubCodeGenerator {
return stub->entry_point();
}
void create_control_words() {
// Round to nearest, 53-bit mode, exceptions masked
StubRoutines::_fpu_cntrl_wrd_std = 0x027F;
// Round to zero, 53-bit mode, exception mased
StubRoutines::_fpu_cntrl_wrd_trunc = 0x0D7F;
// Round to nearest, 24-bit mode, exceptions masked
StubRoutines::_fpu_cntrl_wrd_24 = 0x007F;
// Round to nearest, 64-bit mode, exceptions masked
StubRoutines::_fpu_cntrl_wrd_64 = 0x037F;
// Round to nearest, 64-bit mode, exceptions masked
StubRoutines::_mxcsr_std = 0x1F80;
// Note: the following two constants are 80-bit values
// layout is critical for correct loading by FPU.
// Bias for strict fp multiply/divide
StubRoutines::_fpu_subnormal_bias1[0]= 0x00000000; // 2^(-15360) == 0x03ff 8000 0000 0000 0000
StubRoutines::_fpu_subnormal_bias1[1]= 0x80000000;
StubRoutines::_fpu_subnormal_bias1[2]= 0x03ff;
// Un-Bias for strict fp multiply/divide
StubRoutines::_fpu_subnormal_bias2[0]= 0x00000000; // 2^(+15360) == 0x7bff 8000 0000 0000 0000
StubRoutines::_fpu_subnormal_bias2[1]= 0x80000000;
StubRoutines::_fpu_subnormal_bias2[2]= 0x7bff;
}
// Initialization
void generate_initial() {
// Generates all stubs and initializes the entry points
// This platform-specific stub is needed by generate_call_stub()
StubRoutines::x86::_mxcsr_std = generate_fp_mask("mxcsr_std", 0x0000000000001F80);
// This platform-specific settings are needed by generate_call_stub()
create_control_words();
// entry points that exist in all platforms Note: This is code
// that could be shared among different platforms - however the
@ -3833,6 +3895,14 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
}
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
&StubRoutines::_safefetch32_continuation_pc);
generate_safefetch("SafeFetchN", sizeof(intptr_t), &StubRoutines::_safefetchN_entry,
&StubRoutines::_safefetchN_fault_pc,
&StubRoutines::_safefetchN_continuation_pc);
}
public:

View file

@ -42,4 +42,3 @@ address StubRoutines::x86::_float_sign_mask = NULL;
address StubRoutines::x86::_float_sign_flip = NULL;
address StubRoutines::x86::_double_sign_mask = NULL;
address StubRoutines::x86::_double_sign_flip = NULL;
address StubRoutines::x86::_mxcsr_std = NULL;

View file

@ -52,7 +52,6 @@ class x86 {
static address _float_sign_flip;
static address _double_sign_mask;
static address _double_sign_flip;
static address _mxcsr_std;
public:
@ -106,11 +105,6 @@ class x86 {
return _double_sign_flip;
}
static address mxcsr_std()
{
return _mxcsr_std;
}
# include "stubRoutines_x86.hpp"
};

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -437,6 +437,30 @@ AttachOperation* AttachListener::dequeue() {
return op;
}
// Performs initialization at vm startup
// For BSD we remove any stale .java_pid file which could cause
// an attaching process to think we are ready to receive on the
// domain socket before we are properly initialized
void AttachListener::vm_start() {
char fn[UNIX_PATH_MAX];
struct stat64 st;
int ret;
int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
debug_only(warning("failed to remove stale attach pid file at %s", fn));
}
}
}
int AttachListener::pd_init() {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -432,6 +432,30 @@ AttachOperation* AttachListener::dequeue() {
return op;
}
// Performs initialization at vm startup
// For Linux we remove any stale .java_pid file which could cause
// an attaching process to think we are ready to receive on the
// domain socket before we are properly initialized
void AttachListener::vm_start() {
char fn[UNIX_PATH_MAX];
struct stat64 st;
int ret;
int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
debug_only(warning("failed to remove stale attach pid file at %s", fn));
}
}
}
int AttachListener::pd_init() {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2013, 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
@ -107,7 +107,7 @@ static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0;
sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
@ -116,7 +116,7 @@ static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
signal_unlock();
return oldhandler;
} else if (jvm_signal_installing) {
} else if (sig < MAXSIGNUM && jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. jvm uses sigaction().
* Leave the piece here just in case. */
@ -165,7 +165,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0;
sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
@ -178,7 +178,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
signal_unlock();
return 0;
} else if (jvm_signal_installing) {
} else if (sig < MAXSIGNUM && jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. */
res = call_os_sigaction(sig, act, &oldAct);

View file

@ -259,3 +259,52 @@ const char* os::get_current_directory(char *buf, size_t buflen) {
FILE* os::open(int fd, const char* mode) {
return ::fdopen(fd, mode);
}
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
}
/*
* See the caveats for this class in os_posix.hpp
* Protects the callback call so that SIGSEGV / SIGBUS jumps back into this
* method and returns false. If none of the signals are raised, returns true.
* The callback is supposed to provide the method that should be protected.
*/
bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"crash_protection already set?");
if (sigsetjmp(_jmpbuf, 1) == 0) {
// make sure we can see in the signal handler that we have crash protection
// installed
WatcherThread::watcher_thread()->set_crash_protection(this);
cb.call();
// and clear the crash protection
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return true;
}
// this happens when we siglongjmp() back
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return false;
}
void os::WatcherThreadCrashProtection::restore() {
assert(WatcherThread::watcher_thread()->has_crash_protection(),
"must have crash protection");
siglongjmp(_jmpbuf, 1);
}
void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
Thread* thread) {
if (thread != NULL &&
thread->is_Watcher_thread() &&
WatcherThread::watcher_thread()->has_crash_protection()) {
if (sig == SIGSEGV || sig == SIGBUS) {
WatcherThread::watcher_thread()->crash_protection()->restore();
}
}
}

View file

@ -37,5 +37,24 @@ protected:
};
/*
* Crash protection for the watcher thread. Wrap the callback
* with a sigsetjmp and in case of a SIGSEGV/SIGBUS we siglongjmp
* back.
* To be able to use this - don't take locks, don't rely on destructors,
* don't make OS library calls, don't allocate memory, don't print,
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
class WatcherThreadCrashProtection : public StackObj {
public:
WatcherThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
static void check_crash_protection(int signal, Thread* thread);
private:
void restore();
sigjmp_buf _jmpbuf;
};
#endif

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -576,6 +576,30 @@ AttachOperation* AttachListener::dequeue() {
return op;
}
// Performs initialization at vm startup
// For Solaris we remove any stale .java_pid file which could cause
// an attaching process to think we are ready to receive a door_call
// before we are properly initialized
void AttachListener::vm_start() {
char fn[PATH_MAX+1];
struct stat64 st;
int ret;
int n = snprintf(fn, sizeof(fn), "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < sizeof(fn), "java_pid file name buffer overflow");
RESTARTABLE(::stat64(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
debug_only(warning("failed to remove stale attach pid file at %s", fn));
}
}
}
int AttachListener::pd_init() {
JavaThread* thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -358,6 +358,10 @@ AttachOperation* AttachListener::dequeue() {
return op;
}
void AttachListener::vm_start() {
// nothing to do
}
int AttachListener::pd_init() {
return Win32AttachListener::init();
}

View file

@ -2323,6 +2323,11 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
#endif
Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady
// Handle SafeFetch32 and SafeFetchN exceptions.
if (StubRoutines::is_safefetch_fault(pc)) {
return Handle_Exception(exceptionInfo, StubRoutines::continuation_for_safefetch_fault(pc));
}
#ifndef _WIN64
// Execution protection violation - win32 running on AMD64 only
// Handled first to avoid misdiagnosis as a "normal" access violation;
@ -4684,6 +4689,34 @@ void os::pause() {
}
}
os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() {
assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread");
}
/*
* See the caveats for this class in os_windows.hpp
* Protects the callback call so that raised OS EXCEPTIONS causes a jump back
* into this method and returns false. If no OS EXCEPTION was raised, returns
* true.
* The callback is supposed to provide the method that should be protected.
*/
bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"crash_protection already set?");
bool success = true;
__try {
WatcherThread::watcher_thread()->set_crash_protection(this);
cb.call();
} __except(EXCEPTION_EXECUTE_HANDLER) {
// only for protection, nothing to do
success = false;
}
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return success;
}
// An Event wraps a win32 "CreateEvent" kernel handle.
//
// We have a number of choices regarding "CreateEvent" win32 handle leakage:

View file

@ -102,6 +102,20 @@ class win32 {
static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
};
/*
* Crash protection for the watcher thread. Wrap the callback
* with a __try { call() }
* To be able to use this - don't take locks, don't rely on destructors,
* don't make OS library calls, don't allocate memory, don't print,
* don't call code that could leave the heap / memory in an inconsistent state,
* or anything else where we are not in control if we suddenly jump out.
*/
class WatcherThreadCrashProtection : public StackObj {
public:
WatcherThreadCrashProtection();
bool call(os::CrashProtectionCallback& cb);
};
class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4] ; // increase odds that _Event is sole occupant of cache line

View file

@ -63,24 +63,6 @@ SYMBOL(fixcw):
popl %eax
ret
.globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume)
.globl SYMBOL(SafeFetchN)
## TODO: avoid exposing Fetch32PFI and Fetch32Resume.
## Instead, the signal handler would call a new SafeFetchTriage(FaultingEIP)
## routine to vet the address. If the address is the faulting LD then
## SafeFetchTriage() would return the resume-at EIP, otherwise null.
ELF_TYPE(SafeFetch32,@function)
.p2align 4,,15
SYMBOL(SafeFetch32):
SYMBOL(SafeFetchN):
movl 0x8(%esp), %eax
movl 0x4(%esp), %ecx
SYMBOL(Fetch32PFI):
movl (%ecx), %eax
SYMBOL(Fetch32Resume):
ret
.globl SYMBOL(SpinPause)
ELF_TYPE(SpinPause,@function)
.p2align 4,,15

View file

@ -46,28 +46,6 @@
.text
.globl SYMBOL(SafeFetch32), SYMBOL(Fetch32PFI), SYMBOL(Fetch32Resume)
.p2align 4,,15
ELF_TYPE(SafeFetch32,@function)
// Prototype: int SafeFetch32 (int * Adr, int ErrValue)
SYMBOL(SafeFetch32):
movl %esi, %eax
SYMBOL(Fetch32PFI):
movl (%rdi), %eax
SYMBOL(Fetch32Resume):
ret
.globl SYMBOL(SafeFetchN), SYMBOL(FetchNPFI), SYMBOL(FetchNResume)
.p2align 4,,15
ELF_TYPE(SafeFetchN,@function)
// Prototype: intptr_t SafeFetchN (intptr_t * Adr, intptr_t ErrValue)
SYMBOL(SafeFetchN):
movq %rsi, %rax
SYMBOL(FetchNPFI):
movq (%rdi), %rax
SYMBOL(FetchNResume):
ret
.globl SYMBOL(SpinPause)
.p2align 4,,15
ELF_TYPE(SpinPause,@function)

View file

@ -72,7 +72,7 @@ inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); }
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
@ -87,7 +87,7 @@ inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; }
@ -190,7 +190,7 @@ inline void OrderAccess::release_store_fence(volatile juint* p, juint v)
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jdouble_cast(v)); }
inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) {
#ifdef AMD64

View file

@ -385,13 +385,6 @@ enum {
trap_page_fault = 0xE
};
extern "C" void Fetch32PFI () ;
extern "C" void Fetch32Resume () ;
#ifdef AMD64
extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ;
#endif // AMD64
extern "C" JNIEXPORT int
JVM_handle_bsd_signal(int sig,
siginfo_t* info,
@ -401,6 +394,10 @@ JVM_handle_bsd_signal(int sig,
Thread* t = ThreadLocalStorage::get_thread_slow();
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
@ -454,16 +451,10 @@ JVM_handle_bsd_signal(int sig,
if (info != NULL && uc != NULL && thread != NULL) {
pc = (address) os::Bsd::ucontext_get_pc(uc);
if (pc == (address) Fetch32PFI) {
uc->context_pc = intptr_t(Fetch32Resume) ;
return 1 ;
if (StubRoutines::is_safefetch_fault(pc)) {
uc->context_pc = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
}
#ifdef AMD64
if (pc == (address) FetchNPFI) {
uc->context_pc = intptr_t (FetchNResume) ;
return 1 ;
}
#endif // AMD64
// Handle ALL stack overflow variations here
if (sig == SIGSEGV || sig == SIGBUS) {

View file

@ -21,42 +21,6 @@
# questions.
#
# Prototype: int SafeFetch32 (int * adr, int ErrValue)
# The "ld" at Fetch32 is potentially faulting instruction.
# If the instruction traps the trap handler will arrange
# for control to resume at Fetch32Resume.
# By convention with the trap handler we ensure there is a non-CTI
# instruction in the trap shadow.
.globl SafeFetch32, Fetch32PFI, Fetch32Resume
.globl SafeFetchN
.align 32
.type SafeFetch32,@function
SafeFetch32:
mov %o0, %g1
mov %o1, %o0
Fetch32PFI:
# <-- Potentially faulting instruction
ld [%g1], %o0
Fetch32Resume:
nop
retl
nop
.globl SafeFetchN, FetchNPFI, FetchNResume
.type SafeFetchN,@function
.align 32
SafeFetchN:
mov %o0, %g1
mov %o1, %o0
FetchNPFI:
ldn [%g1], %o0
FetchNResume:
nop
retl
nop
# Possibilities:
# -- membar
# -- CAS (SP + BIAS, G0, G0)

View file

@ -366,18 +366,9 @@ intptr_t* os::Linux::ucontext_get_fp(ucontext_t *uc) {
// Utility functions
extern "C" void Fetch32PFI();
extern "C" void Fetch32Resume();
extern "C" void FetchNPFI();
extern "C" void FetchNResume();
inline static bool checkPrefetch(sigcontext* uc, address pc) {
if (pc == (address) Fetch32PFI) {
set_cont_address(uc, address(Fetch32Resume));
return true;
}
if (pc == (address) FetchNPFI) {
set_cont_address(uc, address(FetchNResume));
if (StubRoutines::is_safefetch_fault(pc)) {
set_cont_address(uc, address(StubRoutines::continuation_for_safefetch_fault(pc)));
return true;
}
return false;
@ -553,6 +544,10 @@ JVM_handle_linux_signal(int sig,
Thread* t = ThreadLocalStorage::get_thread_slow();
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
// Note: it's not uncommon that JNI code uses signal/sigset to install

View file

@ -42,24 +42,6 @@
.text
.globl SafeFetch32, Fetch32PFI, Fetch32Resume
.globl SafeFetchN
## TODO: avoid exposing Fetch32PFI and Fetch32Resume.
## Instead, the signal handler would call a new SafeFetchTriage(FaultingEIP)
## routine to vet the address. If the address is the faulting LD then
## SafeFetchTriage() would return the resume-at EIP, otherwise null.
.type SafeFetch32,@function
.p2align 4,,15
SafeFetch32:
SafeFetchN:
movl 0x8(%esp), %eax
movl 0x4(%esp), %ecx
Fetch32PFI:
movl (%ecx), %eax
Fetch32Resume:
ret
.globl SpinPause
.type SpinPause,@function
.p2align 4,,15

View file

@ -38,28 +38,6 @@
.text
.globl SafeFetch32, Fetch32PFI, Fetch32Resume
.align 16
.type SafeFetch32,@function
// Prototype: int SafeFetch32 (int * Adr, int ErrValue)
SafeFetch32:
movl %esi, %eax
Fetch32PFI:
movl (%rdi), %eax
Fetch32Resume:
ret
.globl SafeFetchN, FetchNPFI, FetchNResume
.align 16
.type SafeFetchN,@function
// Prototype: intptr_t SafeFetchN (intptr_t * Adr, intptr_t ErrValue)
SafeFetchN:
movq %rsi, %rax
FetchNPFI:
movq (%rdi), %rax
FetchNResume:
ret
.globl SpinPause
.align 16
.type SpinPause,@function

View file

@ -72,7 +72,7 @@ inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); }
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
@ -87,7 +87,7 @@ inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong *)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; }
@ -129,7 +129,7 @@ inline void OrderAccess::store_fence(jushort* p, jushort v) { store_fence((j
inline void OrderAccess::store_fence(juint* p, juint v) { store_fence((jint*)p, (jint)v); }
inline void OrderAccess::store_fence(julong* p, julong v) { store_fence((jlong*)p, (jlong)v); }
inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); }
inline void OrderAccess::store_fence(jdouble* p, jdouble v) { store_fence((jlong*)p, jlong_cast(v)); }
inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) {
#ifdef AMD64
@ -190,7 +190,7 @@ inline void OrderAccess::release_store_fence(volatile juint* p, juint v)
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) {
#ifdef AMD64

View file

@ -209,13 +209,6 @@ enum {
trap_page_fault = 0xE
};
extern "C" void Fetch32PFI () ;
extern "C" void Fetch32Resume () ;
#ifdef AMD64
extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ;
#endif // AMD64
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
@ -225,6 +218,10 @@ JVM_handle_linux_signal(int sig,
Thread* t = ThreadLocalStorage::get_thread_slow();
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
@ -278,16 +275,10 @@ JVM_handle_linux_signal(int sig,
if (info != NULL && uc != NULL && thread != NULL) {
pc = (address) os::Linux::ucontext_get_pc(uc);
if (pc == (address) Fetch32PFI) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ;
return 1 ;
if (StubRoutines::is_safefetch_fault(pc)) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
}
#ifdef AMD64
if (pc == (address) FetchNPFI) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t (FetchNResume) ;
return 1 ;
}
#endif // AMD64
#ifndef AMD64
// Halt if SI_KERNEL before more crashes get misdiagnosed as Java bugs

View file

@ -303,11 +303,6 @@ bool os::is_allocatable(size_t bytes) {
#endif
}
extern "C" void Fetch32PFI () ;
extern "C" void Fetch32Resume () ;
extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ;
extern "C" JNIEXPORT int
JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
int abort_if_unrecognized) {
@ -315,6 +310,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
Thread* t = ThreadLocalStorage::get_thread_slow();
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
if(sig == SIGPIPE || sig == SIGXFSZ) {
@ -379,17 +378,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
npc = (address) uc->uc_mcontext.gregs[REG_nPC];
// SafeFetch() support
// Implemented with either a fixed set of addresses such
// as Fetch32*, or with Thread._OnTrap.
if (uc->uc_mcontext.gregs[REG_PC] == intptr_t(Fetch32PFI)) {
uc->uc_mcontext.gregs [REG_PC] = intptr_t(Fetch32Resume) ;
uc->uc_mcontext.gregs [REG_nPC] = intptr_t(Fetch32Resume) + 4 ;
return true ;
}
if (uc->uc_mcontext.gregs[REG_PC] == intptr_t(FetchNPFI)) {
uc->uc_mcontext.gregs [REG_PC] = intptr_t(FetchNResume) ;
uc->uc_mcontext.gregs [REG_nPC] = intptr_t(FetchNResume) + 4 ;
return true ;
if (StubRoutines::is_safefetch_fault(pc)) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
uc->uc_mcontext.gregs[REG_nPC] = uc->uc_mcontext.gregs[REG_PC] + 4;
return 1;
}
// Handle ALL stack overflow variations here

View file

@ -21,47 +21,6 @@
!! questions.
!!
!! Prototype: int SafeFetch32 (int * adr, int ErrValue)
!! The "ld" at Fetch32 is potentially faulting instruction.
!! If the instruction traps the trap handler will arrange
!! for control to resume at Fetch32Resume.
!! By convention with the trap handler we ensure there is a non-CTI
!! instruction in the trap shadow.
!!
!! The reader might be tempted to move this service to .il.
!! Don't. Sun's CC back-end reads and optimize code emitted
!! by the .il "call", in some cases optimizing the code, completely eliding it,
!! or by moving the code from the "call site".
!! ASM better know we may use G6 for our own purposes
.register %g6, #ignore
.globl SafeFetch32
.align 32
.global Fetch32PFI, Fetch32Resume
SafeFetch32:
mov %o0, %g1
mov %o1, %o0
Fetch32PFI:
ld [%g1], %o0 !! <-- Potentially faulting instruction
Fetch32Resume:
nop
retl
nop
.globl SafeFetchN
.align 32
.globl FetchNPFI, FetchNResume
SafeFetchN:
mov %o0, %g1
mov %o1, %o0
FetchNPFI:
ldn [%g1], %o0
FetchNResume:
nop
retl
nop
!! Possibilities:
!! -- membar
!! -- CAS (SP + BIAS, G0, G0)

View file

@ -88,7 +88,7 @@ inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); }
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
@ -103,7 +103,7 @@ inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; }
@ -129,9 +129,9 @@ inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v)
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store((jlong *)p, (jlong)v); fence(); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); }
inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); }

View file

@ -352,13 +352,6 @@ bool os::is_allocatable(size_t bytes) {
}
extern "C" void Fetch32PFI () ;
extern "C" void Fetch32Resume () ;
#ifdef AMD64
extern "C" void FetchNPFI () ;
extern "C" void FetchNResume () ;
#endif // AMD64
extern "C" JNIEXPORT int
JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
int abort_if_unrecognized) {
@ -374,6 +367,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady
// Must do this before SignalHandlerMark, if crash protection installed we will longjmp away
// (no destructors can be run)
os::WatcherThreadCrashProtection::check_crash_protection(sig, t);
SignalHandlerMark shm(t);
if(sig == SIGPIPE || sig == SIGXFSZ) {
@ -436,17 +433,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
// factor me: getPCfromContext
pc = (address) uc->uc_mcontext.gregs[REG_PC];
// SafeFetch32() support
if (pc == (address) Fetch32PFI) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ;
return true ;
if (StubRoutines::is_safefetch_fault(pc)) {
uc->uc_mcontext.gregs[REG_PC] = intptr_t(StubRoutines::continuation_for_safefetch_fault(pc));
return true;
}
#ifdef AMD64
if (pc == (address) FetchNPFI) {
uc->uc_mcontext.gregs [REG_PC] = intptr_t(FetchNResume) ;
return true ;
}
#endif // AMD64
// Handle ALL stack overflow variations here
if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {

View file

@ -54,20 +54,6 @@ fixcw:
popl %eax
ret
.align 16
.globl SafeFetch32
.globl SafeFetchN
.globl Fetch32PFI, Fetch32Resume
SafeFetch32:
SafeFetchN:
movl 0x8(%esp), %eax
movl 0x4(%esp), %ecx
Fetch32PFI:
movl (%ecx), %eax
Fetch32Resume:
ret
.align 16
.globl SpinPause
SpinPause:

View file

@ -21,54 +21,34 @@
/ questions.
/
.globl fs_load
.globl fs_thread
.globl fs_load
.globl fs_thread
// NOTE WELL! The _Copy functions are called directly
// from server-compiler-generated code via CallLeafNoFP,
// which means that they *must* either not use floating
// point or use it in the same manner as does the server
// compiler.
// from server-compiler-generated code via CallLeafNoFP,
// which means that they *must* either not use floating
// point or use it in the same manner as does the server
// compiler.
.globl _Copy_arrayof_conjoint_bytes
.globl _Copy_conjoint_jshorts_atomic
.globl _Copy_arrayof_conjoint_jshorts
.globl _Copy_arrayof_conjoint_jshorts
.globl _Copy_conjoint_jints_atomic
.globl _Copy_arrayof_conjoint_jints
.globl _Copy_conjoint_jlongs_atomic
.globl _Copy_conjoint_jlongs_atomic
.globl _Copy_arrayof_conjoint_jlongs
.section .text,"ax"
.section .text,"ax"
/ Fast thread accessors, used by threadLS_solaris_amd64.cpp
.align 16
.align 16
fs_load:
movq %fs:(%rdi),%rax
ret
.align 16
fs_thread:
movq %fs:0x0,%rax
ret
.globl SafeFetch32, Fetch32PFI, Fetch32Resume
.align 16
// Prototype: int SafeFetch32 (int * Adr, int ErrValue)
SafeFetch32:
movl %esi, %eax
Fetch32PFI:
movl (%rdi), %eax
Fetch32Resume:
movq %fs:(%rdi),%rax
ret
.globl SafeFetchN, FetchNPFI, FetchNResume
.align 16
// Prototype: intptr_t SafeFetchN (intptr_t * Adr, intptr_t ErrValue)
SafeFetchN:
movq %rsi, %rax
FetchNPFI:
movq (%rdi), %rax
FetchNResume:
.align 16
fs_thread:
movq %fs:0x0,%rax
ret
.globl SpinPause
@ -78,7 +58,7 @@ SpinPause:
nop
movq $1, %rax
ret
/ Support for void Copy::arrayof_conjoint_bytes(void* from,
/ void* to,
@ -340,7 +320,7 @@ aci_CopyLeft:
addq $4,%rdx
jg 1b
ret
/ Support for void Copy::arrayof_conjoint_jlongs(jlong* from,
/ jlong* to,
/ size_t count)

View file

@ -71,7 +71,7 @@ inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return jdouble_cast(Atomic::load((volatile jlong*)p)); }
inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; }
inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; }
@ -86,7 +86,7 @@ inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { release_store((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; }
inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; }
@ -195,7 +195,7 @@ inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v)
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { release_store_fence((volatile jint*)p, (jint)v); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store_fence((volatile jlong*)p, (jlong)v); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); }
inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) {
#ifdef AMD64

View file

@ -518,24 +518,6 @@ void os::print_register_info(outputStream *st, void *context) {
st->cr();
}
extern "C" int SafeFetch32 (int * adr, int Err) {
int rv = Err ;
_try {
rv = *((volatile int *) adr) ;
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return rv ;
}
extern "C" intptr_t SafeFetchN (intptr_t * adr, intptr_t Err) {
intptr_t rv = Err ;
_try {
rv = *((volatile intptr_t *) adr) ;
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
return rv ;
}
extern "C" int SpinPause () {
#ifdef AMD64
return 0 ;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,10 +29,15 @@
#ifdef AMD64
typedef unsigned char UBYTE;
#if _MSC_VER < 1700
/* Not needed for VS2012 compiler, comes from winnt.h. */
#define UNW_FLAG_EHANDLER 0x01
#define UNW_FLAG_UHANDLER 0x02
#define UNW_FLAG_CHAININFO 0x04
#endif
// This structure is used to define an UNWIND_INFO that
// only has an ExceptionHandler. There are no UnwindCodes
// declared.
@ -59,6 +64,9 @@ typedef struct _RUNTIME_FUNCTION {
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
*/
#if _MSC_VER < 1700
/* Not needed for VS2012 compiler, comes from winnt.h. */
typedef struct _DISPATCHER_CONTEXT {
ULONG64 ControlPc;
ULONG64 ImageBase;
@ -71,6 +79,8 @@ typedef struct _DISPATCHER_CONTEXT {
PVOID HandlerData;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
#endif
#if _MSC_VER < 1500
/* Not needed for VS2008 compiler, comes from winnt.h. */

View file

@ -138,6 +138,16 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
return false;
}
// return true if all argument elements of vars are returned
bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i) && !_arg_returned.test(i)) {
return false;
}
}
return true;
}
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
@ -166,6 +176,11 @@ void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) {
if (vars.contains_unknown() || vars.contains_vars()) {
_return_allocated = false;
}
if (_return_local && vars.contains_vars() && !returns_all(vars)) {
// Return result should be invalidated if args in new
// state are not recorded in return state.
_return_local = false;
}
}
}

View file

@ -80,6 +80,7 @@ class BCEscapeAnalyzer : public ResourceObj {
void set_returned(ArgumentMap vars);
bool is_argument(ArgumentMap vars);
bool is_arg_stack(ArgumentMap vars);
bool returns_all(ArgumentMap vars);
void clear_bits(ArgumentMap vars, VectorSet &bs);
void set_method_escape(ArgumentMap vars);
void set_global_escape(ArgumentMap vars, bool merge = false);

View file

@ -3647,8 +3647,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// If RedefineClasses() was used before the retransformable
// agent attached, then the cached class bytes may not be the
// original class bytes.
unsigned char *cached_class_file_bytes = NULL;
jint cached_class_file_length;
JvmtiCachedClassFileData *cached_class_file = NULL;
Handle class_loader(THREAD, loader_data->class_loader());
bool has_default_methods = false;
ResourceMark rm(THREAD);
@ -3680,10 +3679,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
if (h_class_being_redefined != NULL) {
instanceKlassHandle ikh_class_being_redefined =
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
cached_class_file_bytes =
ikh_class_being_redefined->get_cached_class_file_bytes();
cached_class_file_length =
ikh_class_being_redefined->get_cached_class_file_len();
cached_class_file = ikh_class_being_redefined->get_cached_class_file();
}
}
@ -3691,9 +3687,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
unsigned char* end_ptr = cfs->buffer() + cfs->length();
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
&ptr, &end_ptr,
&cached_class_file_bytes,
&cached_class_file_length);
&ptr, &end_ptr, &cached_class_file);
if (ptr != cfs->buffer()) {
// JVMTI agent has modified class file data.
@ -4011,10 +4005,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
}
if (cached_class_file_bytes != NULL) {
if (cached_class_file != NULL) {
// JVMTI: we have an InstanceKlass now, tell it about the cached bytes
this_klass->set_cached_class_file(cached_class_file_bytes,
cached_class_file_length);
this_klass->set_cached_class_file(cached_class_file);
}
// Fill in field values obtained by parse_classfile_attributes

View file

@ -53,8 +53,6 @@
template(java_lang_Object, "java/lang/Object") \
template(java_lang_Class, "java/lang/Class") \
template(java_lang_String, "java/lang/String") \
template(java_lang_StringValue, "java/lang/StringValue") \
template(java_lang_StringCache, "java/lang/StringValue$StringCache") \
template(java_lang_Thread, "java/lang/Thread") \
template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \
template(java_lang_Cloneable, "java/lang/Cloneable") \
@ -106,7 +104,6 @@
template(java_util_Vector, "java/util/Vector") \
template(java_util_AbstractList, "java/util/AbstractList") \
template(java_util_Hashtable, "java/util/Hashtable") \
template(java_util_HashMap, "java/util/HashMap") \
template(java_lang_Compiler, "java/lang/Compiler") \
template(sun_misc_Signal, "sun/misc/Signal") \
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
@ -367,8 +364,6 @@
template(offset_name, "offset") \
template(count_name, "count") \
template(hash_name, "hash") \
template(frontCacheEnabled_name, "frontCacheEnabled") \
template(stringCacheEnabled_name, "stringCacheEnabled") \
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
template(bitCount_name, "bitCount") \

View file

@ -873,7 +873,7 @@ bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc
size_t alloc_byte_size = alloc_word_size * HeapWordSize;
if ((cur_used_bytes + alloc_byte_size) > marking_initiating_used_threshold) {
if (gcs_are_young()) {
if (gcs_are_young() && !_last_young_gc) {
ergo_verbose5(ErgoConcCycles,
"request concurrent cycle initiation",
ergo_format_reason("occupancy higher than threshold")
@ -931,7 +931,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, Evacua
last_pause_included_initial_mark = during_initial_mark_pause();
if (last_pause_included_initial_mark) {
record_concurrent_mark_init_end(0.0);
} else if (!_last_young_gc && need_to_start_conc_mark("end of GC")) {
} else if (need_to_start_conc_mark("end of GC")) {
// Note: this might have already been set, if during the last
// pause we decided to start a cycle but at the beginning of
// this pause we decided to postpone it. That's OK.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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,6 +83,10 @@ protected:
Chunk *_chunk; // saved arena chunk
char *_hwm, *_max;
size_t _size_in_bytes;
#ifdef ASSERT
Thread* _thread;
ResourceMark* _previous_resource_mark;
#endif //ASSERT
void initialize(Thread *thread) {
_area = thread->resource_area();
@ -92,6 +96,11 @@ protected:
_size_in_bytes = _area->size_in_bytes();
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
#ifdef ASSERT
_thread = thread;
_previous_resource_mark = thread->current_resource_mark();
thread->set_current_resource_mark(this);
#endif // ASSERT
}
public:
@ -111,6 +120,17 @@ protected:
_size_in_bytes = r->_size_in_bytes;
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
#ifdef ASSERT
Thread* thread = ThreadLocalStorage::thread();
if (thread != NULL) {
_thread = thread;
_previous_resource_mark = thread->current_resource_mark();
thread->set_current_resource_mark(this);
} else {
_thread = NULL;
_previous_resource_mark = NULL;
}
#endif // ASSERT
}
void reset_to_mark() {
@ -137,6 +157,11 @@ protected:
assert( _area->_nesting > 0, "must stack allocate RMs" );
debug_only(_area->_nesting--;)
reset_to_mark();
#ifdef ASSERT
if (_thread != NULL) {
_thread->set_current_resource_mark(_previous_resource_mark);
}
#endif // ASSERT
}

View file

@ -140,8 +140,15 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
_f1 = f1;
}
void release_set_f1(Metadata* f1);
void set_f2(intx f2) { assert(_f2 == 0 || _f2 == f2, "illegal field change"); _f2 = f2; }
void set_f2_as_vfinal_method(Method* f2) { assert(_f2 == 0 || _f2 == (intptr_t) f2, "illegal field change"); assert(is_vfinal(), "flags must be set"); _f2 = (intptr_t) f2; }
void set_f2(intx f2) {
intx existing_f2 = _f2; // read once
assert(existing_f2 == 0 || existing_f2 == f2, "illegal field change");
_f2 = f2;
}
void set_f2_as_vfinal_method(Method* f2) {
assert(is_vfinal(), "flags must be set");
set_f2((intx)f2);
}
int make_flags(TosState state, int option_bits, int field_index_or_method_params);
void set_flags(intx flags) { _flags = flags; }
bool init_flags_atomic(intx flags);

View file

@ -48,6 +48,7 @@
#include "oops/symbol.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/methodComparator.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.inline.hpp"
@ -291,7 +292,7 @@ InstanceKlass::InstanceKlass(int vtable_len,
set_initial_method_idnum(0);
_dependencies = NULL;
set_jvmti_cached_class_field_map(NULL);
set_cached_class_file(NULL, 0);
set_cached_class_file(NULL);
set_initial_method_idnum(0);
set_minor_version(0);
set_major_version(0);
@ -2357,10 +2358,9 @@ void InstanceKlass::release_C_heap_structures() {
}
// deallocate the cached class file
if (_cached_class_file_bytes != NULL) {
os::free(_cached_class_file_bytes, mtClass);
_cached_class_file_bytes = NULL;
_cached_class_file_len = 0;
if (_cached_class_file != NULL) {
os::free(_cached_class_file, mtClass);
_cached_class_file = NULL;
}
// Decrement symbol reference counts associated with the unloaded class.
@ -3530,6 +3530,14 @@ Method* InstanceKlass::method_with_idnum(int idnum) {
return m;
}
jint InstanceKlass::get_cached_class_file_len() {
return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
}
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
// Construct a PreviousVersionNode entry for the array hung off
// the InstanceKlass.

View file

@ -133,6 +133,8 @@ class OopMapBlock VALUE_OBJ_CLASS_SPEC {
uint _count;
};
struct JvmtiCachedClassFileData;
class InstanceKlass: public Klass {
friend class VMStructs;
friend class ClassFileParser;
@ -249,8 +251,8 @@ class InstanceKlass: public Klass {
// InstanceKlass. See PreviousVersionWalker below.
GrowableArray<PreviousVersionNode *>* _previous_versions;
// JVMTI fields can be moved to their own structure - see 6315920
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
jint _cached_class_file_len; // JVMTI: length of above
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
@ -615,11 +617,12 @@ class InstanceKlass: public Klass {
static void purge_previous_versions(InstanceKlass* ik);
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
void set_cached_class_file(unsigned char *class_file_bytes,
jint class_file_len) { _cached_class_file_len = class_file_len;
_cached_class_file_bytes = class_file_bytes; }
jint get_cached_class_file_len() { return _cached_class_file_len; }
unsigned char * get_cached_class_file_bytes() { return _cached_class_file_bytes; }
void set_cached_class_file(JvmtiCachedClassFileData *data) {
_cached_class_file = data;
}
JvmtiCachedClassFileData * get_cached_class_file() { return _cached_class_file; }
jint get_cached_class_file_len();
unsigned char * get_cached_class_file_bytes();
// JVMTI: Support for caching of field indices, types, and offsets
void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {

View file

@ -1163,6 +1163,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
newm->constMethod()->set_constMethod_size(new_const_method_size);
newm->set_method_size(new_method_size);
assert(newm->code_size() == new_code_length, "check");
assert(newm->method_parameters_length() == method_parameters_len, "check");
assert(newm->checked_exceptions_length() == checked_exceptions_len, "check");
assert(newm->exception_table_length() == exception_table_len, "check");
assert(newm->localvariable_table_length() == localvariable_len, "check");
@ -1174,6 +1175,12 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
new_compressed_linenumber_table,
new_compressed_linenumber_size);
}
// Copy method_parameters
if (method_parameters_len > 0) {
memcpy(newm->method_parameters_start(),
m->method_parameters_start(),
method_parameters_len * sizeof(MethodParametersElement));
}
// Copy checked_exceptions
if (checked_exceptions_len > 0) {
memcpy(newm->checked_exceptions_start(),

View file

@ -297,15 +297,6 @@ bool InlineTree::should_not_inline(ciMethod *callee_method,
}
}
if (UseStringCache) {
// Do not inline StringCache::profile() method used only at the beginning.
if (callee_method->name() == ciSymbol::profile_name() &&
callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
set_msg("profiling method");
return true;
}
}
// use frequency-based objections only for non-trivial methods
if (callee_method->code_size() <= MaxTrivialSize) {
return false;

View file

@ -2308,26 +2308,26 @@ void Matcher::validate_null_checks( ) {
// atomic instruction acting as a store_load barrier without any
// intervening volatile load, and thus we don't need a barrier here.
// We retain the Node to act as a compiler ordering barrier.
bool Matcher::post_store_load_barrier(const Node *vmb) {
Compile *C = Compile::current();
assert( vmb->is_MemBar(), "" );
assert( vmb->Opcode() != Op_MemBarAcquire, "" );
const MemBarNode *mem = (const MemBarNode*)vmb;
bool Matcher::post_store_load_barrier(const Node* vmb) {
Compile* C = Compile::current();
assert(vmb->is_MemBar(), "");
assert(vmb->Opcode() != Op_MemBarAcquire, "");
const MemBarNode* membar = vmb->as_MemBar();
// Get the Proj node, ctrl, that can be used to iterate forward
Node *ctrl = NULL;
DUIterator_Fast imax, i = mem->fast_outs(imax);
while( true ) {
ctrl = mem->fast_out(i); // Throw out-of-bounds if proj not found
assert( ctrl->is_Proj(), "only projections here" );
ProjNode *proj = (ProjNode*)ctrl;
if( proj->_con == TypeFunc::Control &&
!C->node_arena()->contains(ctrl) ) // Unmatched old-space only
// Get the Ideal Proj node, ctrl, that can be used to iterate forward
Node* ctrl = NULL;
for (DUIterator_Fast imax, i = membar->fast_outs(imax); i < imax; i++) {
Node* p = membar->fast_out(i);
assert(p->is_Proj(), "only projections here");
if ((p->as_Proj()->_con == TypeFunc::Control) &&
!C->node_arena()->contains(p)) { // Unmatched old-space only
ctrl = p;
break;
i++;
}
}
assert((ctrl != NULL), "missing control projection");
for( DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++ ) {
for (DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++) {
Node *x = ctrl->fast_out(j);
int xop = x->Opcode();
@ -2339,37 +2339,36 @@ bool Matcher::post_store_load_barrier(const Node *vmb) {
// that a monitor exit operation contains a serializing instruction.
if (xop == Op_MemBarVolatile ||
xop == Op_FastLock ||
xop == Op_CompareAndSwapL ||
xop == Op_CompareAndSwapP ||
xop == Op_CompareAndSwapN ||
xop == Op_CompareAndSwapI)
xop == Op_CompareAndSwapI) {
return true;
}
// Op_FastLock previously appeared in the Op_* list above.
// With biased locking we're no longer guaranteed that a monitor
// enter operation contains a serializing instruction.
if ((xop == Op_FastLock) && !UseBiasedLocking) {
return true;
}
if (x->is_MemBar()) {
// We must retain this membar if there is an upcoming volatile
// load, which will be preceded by acquire membar.
if (xop == Op_MemBarAcquire)
// load, which will be followed by acquire membar.
if (xop == Op_MemBarAcquire) {
return false;
// For other kinds of barriers, check by pretending we
// are them, and seeing if we can be removed.
else
return post_store_load_barrier((const MemBarNode*)x);
} else {
// For other kinds of barriers, check by pretending we
// are them, and seeing if we can be removed.
return post_store_load_barrier(x->as_MemBar());
}
}
// Delicate code to detect case of an upcoming fastlock block
if( x->is_If() && x->req() > 1 &&
!C->node_arena()->contains(x) ) { // Unmatched old-space only
Node *iff = x;
Node *bol = iff->in(1);
// The iff might be some random subclass of If or bol might be Con-Top
if (!bol->is_Bool()) return false;
assert( bol->req() > 1, "" );
return (bol->in(1)->Opcode() == Op_FastUnlock);
}
// probably not necessary to check for these
if (x->is_Call() || x->is_SafePoint() || x->is_block_proj())
if (x->is_Call() || x->is_SafePoint() || x->is_block_proj()) {
return false;
}
}
return false;
}

View file

@ -294,25 +294,7 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
// If reference is volatile, prevent following volatiles ops from
// floating up before the volatile write.
if (is_vol) {
// First place the specific membar for THIS volatile index. This first
// membar is dependent on the store, keeping any other membars generated
// below from floating up past the store.
int adr_idx = C->get_alias_index(adr_type);
insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store);
// Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed
// volatile alias indices. Skip this if the membar is redundant.
if (adr_idx != Compile::AliasIdxBot) {
insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store);
}
// Finally, place alias-index-specific membars for each volatile index
// that isn't the adr_idx membar. Typically there's only 1 or 2.
for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) {
if (i != adr_idx && C->alias_type(i)->is_volatile()) {
insert_mem_bar_volatile(Op_MemBarVolatile, i, store);
}
}
insert_mem_bar(Op_MemBarVolatile); // Use fat membar
}
// If the field is final, the rules of Java say we are in <init> or <clinit>.

View file

@ -31,6 +31,7 @@
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "prims/forte.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/thread.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframeArray.hpp"
@ -308,10 +309,14 @@ static bool find_initial_Java_frame(JavaThread* thread,
for (loop_count = 0; loop_count < loop_max; loop_count++) {
if (candidate.is_first_frame()) {
if (candidate.is_entry_frame()) {
// jcw is NULL if the java call wrapper couldn't be found
JavaCallWrapper *jcw = candidate.entry_frame_call_wrapper_if_safe(thread);
// If initial frame is frame from StubGenerator and there is no
// previous anchor, there are no java frames associated with a method
return false;
if (jcw == NULL || jcw->is_first_frame()) {
return false;
}
}
if (candidate.is_interpreted_frame()) {

View file

@ -126,6 +126,7 @@ static const char * fatal_wrong_class_or_method = "Wrong object class or methodI
static const char * fatal_non_weak_method = "non-weak methodID passed to JNI call";
static const char * fatal_unknown_array_object = "Unknown array object passed to JNI array operations";
static const char * fatal_object_array_expected = "Object array expected but not received for JNI array operation";
static const char * fatal_prim_type_array_expected = "Primitive type array expected but not received for JNI array operation";
static const char * fatal_non_array = "Non-array passed to JNI array operations";
static const char * fatal_element_type_mismatch = "Array element type mismatch in JNI";
static const char * fatal_should_be_static = "Non-static field ID passed to JNI";
@ -278,30 +279,49 @@ checkString(JavaThread* thr, jstring js)
ReportJNIFatalError(thr, fatal_non_string);
}
static inline void
checkArray(JavaThread* thr, jarray jArray, int elementType)
static inline arrayOop
check_is_array(JavaThread* thr, jarray jArray)
{
ASSERT_OOPS_ALLOWED;
arrayOop aOop;
aOop = (arrayOop)jniCheck::validate_object(thr, jArray);
if (aOop == NULL || !aOop->is_array())
if (aOop == NULL || !aOop->is_array()) {
ReportJNIFatalError(thr, fatal_non_array);
}
return aOop;
}
if (elementType != -1) {
if (aOop->is_typeArray()) {
BasicType array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
if (array_type != elementType)
ReportJNIFatalError(thr, fatal_element_type_mismatch);
} else if (aOop->is_objArray()) {
if ( T_OBJECT != elementType)
ReportJNIFatalError(thr, fatal_object_array_expected);
} else {
ReportJNIFatalError(thr, fatal_unknown_array_object);
}
static inline arrayOop
check_is_primitive_array(JavaThread* thr, jarray jArray) {
arrayOop aOop = check_is_array(thr, jArray);
if (!aOop->is_typeArray()) {
ReportJNIFatalError(thr, fatal_prim_type_array_expected);
}
return aOop;
}
static inline void
check_primitive_array_type(JavaThread* thr, jarray jArray, BasicType elementType)
{
BasicType array_type;
arrayOop aOop;
aOop = check_is_primitive_array(thr, jArray);
array_type = TypeArrayKlass::cast(aOop->klass())->element_type();
if (array_type != elementType) {
ReportJNIFatalError(thr, fatal_element_type_mismatch);
}
}
static inline void
check_is_obj_array(JavaThread* thr, jarray jArray) {
arrayOop aOop = check_is_array(thr, jArray);
if (!aOop->is_objArray()) {
ReportJNIFatalError(thr, fatal_object_array_expected);
}
}
oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
if (JNIHandles::is_frame_handle(thr, obj) ||
@ -1417,7 +1437,7 @@ JNI_ENTRY_CHECKED(jsize,
jarray array))
functionEnter(thr);
IN_VM(
checkArray(thr, array, -1);
check_is_array(thr, array);
)
jsize result = UNCHECKED()->GetArrayLength(env,array);
functionExit(env);
@ -1441,7 +1461,7 @@ JNI_ENTRY_CHECKED(jobject,
jsize index))
functionEnter(thr);
IN_VM(
checkArray(thr, array, T_OBJECT);
check_is_obj_array(thr, array);
)
jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index);
functionExit(env);
@ -1455,7 +1475,7 @@ JNI_ENTRY_CHECKED(void,
jobject val))
functionEnter(thr);
IN_VM(
checkArray(thr, array, T_OBJECT);
check_is_obj_array(thr, array);
)
UNCHECKED()->SetObjectArrayElement(env,array,index,val);
functionExit(env);
@ -1487,7 +1507,7 @@ JNI_ENTRY_CHECKED(ElementType *, \
jboolean *isCopy)) \
functionEnter(thr); \
IN_VM( \
checkArray(thr, array, ElementTag); \
check_primitive_array_type(thr, array, ElementTag); \
) \
ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
array, \
@ -1513,7 +1533,7 @@ JNI_ENTRY_CHECKED(void, \
jint mode)) \
functionEnterExceptionAllowed(thr); \
IN_VM( \
checkArray(thr, array, ElementTag); \
check_primitive_array_type(thr, array, ElementTag); \
ASSERT_OOPS_ALLOWED; \
typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
/* cannot check validity of copy, unless every request is logged by
@ -1543,7 +1563,7 @@ JNI_ENTRY_CHECKED(void, \
ElementType *buf)) \
functionEnter(thr); \
IN_VM( \
checkArray(thr, array, ElementTag); \
check_primitive_array_type(thr, array, ElementTag); \
) \
UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \
functionExit(env); \
@ -1567,7 +1587,7 @@ JNI_ENTRY_CHECKED(void, \
const ElementType *buf)) \
functionEnter(thr); \
IN_VM( \
checkArray(thr, array, ElementTag); \
check_primitive_array_type(thr, array, ElementTag); \
) \
UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \
functionExit(env); \
@ -1669,7 +1689,7 @@ JNI_ENTRY_CHECKED(void *,
jboolean *isCopy))
functionEnterCritical(thr);
IN_VM(
checkArray(thr, array, -1);
check_is_primitive_array(thr, array);
)
void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
functionExit(env);
@ -1683,7 +1703,7 @@ JNI_ENTRY_CHECKED(void,
jint mode))
functionEnterCriticalExceptionAllowed(thr);
IN_VM(
checkArray(thr, array, -1);
check_is_primitive_array(thr, array);
)
/* The Hotspot JNI code does not use the parameters, so just check the
* array parameter as a minor sanity check

View file

@ -41,6 +41,7 @@
#include "prims/jvmtiRawMonitor.hpp"
#include "prims/jvmtiTagMap.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.hpp"
#include "runtime/interfaceSupport.hpp"
@ -516,8 +517,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
jint _curr_len;
unsigned char * _curr_data;
JvmtiEnv * _curr_env;
jint * _cached_length_ptr;
unsigned char ** _cached_data_ptr;
JvmtiCachedClassFileData ** _cached_class_file_ptr;
JvmtiThreadState * _state;
KlassHandle * _h_class_being_redefined;
JvmtiClassLoadKind _load_kind;
@ -526,8 +526,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
Handle h_protection_domain,
unsigned char **data_ptr, unsigned char **end_ptr,
unsigned char **cached_data_ptr,
jint *cached_length_ptr) {
JvmtiCachedClassFileData **cache_ptr) {
_h_name = h_name;
_class_loader = class_loader;
_h_protection_domain = h_protection_domain;
@ -537,8 +536,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
_curr_len = *end_ptr - *data_ptr;
_curr_data = *data_ptr;
_curr_env = NULL;
_cached_length_ptr = cached_length_ptr;
_cached_data_ptr = cached_data_ptr;
_cached_class_file_ptr = cache_ptr;
_state = _thread->jvmti_thread_state();
if (_state != NULL) {
@ -615,15 +613,20 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
}
if (new_data != NULL) {
// this agent has modified class data.
if (caching_needed && *_cached_data_ptr == NULL) {
if (caching_needed && *_cached_class_file_ptr == NULL) {
// data has been changed by the new retransformable agent
// and it hasn't already been cached, cache it
*_cached_data_ptr = (unsigned char *)os::malloc(_curr_len, mtInternal);
if (*_cached_data_ptr == NULL) {
vm_exit_out_of_memory(_curr_len, OOM_MALLOC_ERROR, "unable to allocate cached copy of original class bytes");
JvmtiCachedClassFileData *p;
p = (JvmtiCachedClassFileData *)os::malloc(
offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal);
if (p == NULL) {
vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len,
OOM_MALLOC_ERROR,
"unable to allocate cached copy of original class bytes");
}
memcpy(*_cached_data_ptr, _curr_data, _curr_len);
*_cached_length_ptr = _curr_len;
p->length = _curr_len;
memcpy(p->data, _curr_data, _curr_len);
*_cached_class_file_ptr = p;
}
if (_curr_data != *_data_ptr) {
@ -662,13 +665,11 @@ void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
Handle h_protection_domain,
unsigned char **data_ptr,
unsigned char **end_ptr,
unsigned char **cached_data_ptr,
jint *cached_length_ptr) {
JvmtiCachedClassFileData **cache_ptr) {
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
h_protection_domain,
data_ptr, end_ptr,
cached_data_ptr,
cached_length_ptr);
cache_ptr);
poster.post();
}

View file

@ -323,8 +323,7 @@ class JvmtiExport : public AllStatic {
static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
Handle h_protection_domain,
unsigned char **data_ptr, unsigned char **end_ptr,
unsigned char **cached_data_ptr,
jint *cached_length_ptr) NOT_JVMTI_RETURN;
JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN;
static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN;
static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN;
static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN;

View file

@ -3342,9 +3342,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// should get cleared in the_class too.
if (the_class->get_cached_class_file_bytes() == 0) {
// the_class doesn't have a cache yet so copy it
the_class->set_cached_class_file(
scratch_class->get_cached_class_file_bytes(),
scratch_class->get_cached_class_file_len());
the_class->set_cached_class_file(scratch_class->get_cached_class_file());
}
#ifndef PRODUCT
else {
@ -3357,7 +3355,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// NULL out in scratch class to not delete twice. The class to be redefined
// always owns these bytes.
scratch_class->set_cached_class_file(NULL, 0);
scratch_class->set_cached_class_file(NULL);
// Replace inner_classes
Array<u2>* old_inner_classes = the_class->inner_classes();

View file

@ -331,6 +331,11 @@
// coordinate a cleanup of these constants with Runtime.
//
struct JvmtiCachedClassFileData {
jint length;
unsigned char data[1];
};
class VM_RedefineClasses: public VM_Operation {
private:
// These static fields are needed by ClassLoaderDataGraph::classes_do()
@ -509,5 +514,12 @@ class VM_RedefineClasses: public VM_Operation {
// Modifiable test must be shared between IsModifiableClass query
// and redefine implementation
static bool is_modifiable_class(oop klass_mirror);
static jint get_cached_class_file_len(JvmtiCachedClassFileData *cache) {
return cache == NULL ? 0 : cache->length;
}
static unsigned char * get_cached_class_file_bytes(JvmtiCachedClassFileData *cache) {
return cache == NULL ? NULL : cache->data;
}
};
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP

View file

@ -263,6 +263,7 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
{ "UseISM", JDK_Version::jdk(8), JDK_Version::jdk(9) },
{ "UsePermISM", JDK_Version::jdk(8), JDK_Version::jdk(9) },
{ "UseMPSS", JDK_Version::jdk(8), JDK_Version::jdk(9) },
{ "UseStringCache", JDK_Version::jdk(8), JDK_Version::jdk(9) },
#ifdef PRODUCT
{ "DesiredMethodLimit",
JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },

View file

@ -221,9 +221,20 @@ bool frame::is_first_java_frame() const {
bool frame::entry_frame_is_first() const {
return entry_frame_call_wrapper()->anchor()->last_Java_sp() == NULL;
return entry_frame_call_wrapper()->is_first_frame();
}
JavaCallWrapper* frame::entry_frame_call_wrapper_if_safe(JavaThread* thread) const {
JavaCallWrapper** jcw = entry_frame_call_wrapper_addr();
address addr = (address) jcw;
// addr must be within the usable part of the stack
if (thread->is_in_usable_stack(addr)) {
return *jcw;
}
return NULL;
}
bool frame::should_be_deoptimized() const {
if (_deopt_state == is_deoptimized ||

View file

@ -356,7 +356,9 @@ class frame VALUE_OBJ_CLASS_SPEC {
public:
// Entry frames
JavaCallWrapper* entry_frame_call_wrapper() const;
JavaCallWrapper* entry_frame_call_wrapper() const { return *entry_frame_call_wrapper_addr(); }
JavaCallWrapper* entry_frame_call_wrapper_if_safe(JavaThread* thread) const;
JavaCallWrapper** entry_frame_call_wrapper_addr() const;
intptr_t* entry_frame_argument_at(int offset) const;
// tells whether there is another chunk of Delta stack above

View file

@ -2588,9 +2588,6 @@ class CommandLineFlags {
product(bool, AggressiveOpts, false, \
"Enable aggressive optimizations - see arguments.cpp") \
\
product(bool, UseStringCache, false, \
"Enable String cache capabilities on String.java") \
\
/* statistics */ \
develop(bool, CountCompiledCalls, false, \
"counts method invocations") \

View file

@ -80,6 +80,8 @@ class JavaCallWrapper: StackObj {
oop receiver() { return _receiver; }
void oops_do(OopClosure* f);
bool is_first_frame() const { return _anchor.last_Java_sp() == NULL; }
};

View file

@ -1370,6 +1370,10 @@ void Monitor::check_prelock_state(Thread *thread) {
debug_only(if (rank() != Mutex::special) \
thread->check_for_valid_safepoint_state(false);)
}
if (thread->is_Watcher_thread()) {
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"locking not allowed when crash protection is set");
}
}
void Monitor::check_block_state(Thread *thread) {

View file

@ -595,6 +595,22 @@ void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
#ifdef ASSERT
// checking for the WatcherThread and crash_protection first
// since os::malloc can be called when the libjvm.{dll,so} is
// first loaded and we don't have a thread yet.
// try to find the thread after we see that the watcher thread
// exists and has crash protection.
WatcherThread *wt = WatcherThread::watcher_thread();
if (wt != NULL && wt->has_crash_protection()) {
Thread* thread = ThreadLocalStorage::get_thread_slow();
if (thread == wt) {
assert(!wt->has_crash_protection(),
"Can't malloc with crash protection from WatcherThread");
}
}
#endif
if (size == 0) {
// return a valid pointer if size is zero
// if NULL is returned the calling functions assume out of memory.

View file

@ -32,15 +32,18 @@
#include "utilities/top.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "jvm_linux.h"
# include <setjmp.h>
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "jvm_solaris.h"
# include <setjmp.h>
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "jvm_bsd.h"
# include <setjmp.h>
#endif
// os defines the interface to operating system; this includes traditional
@ -730,6 +733,10 @@ class os: AllStatic {
#include "runtime/os_ext.hpp"
public:
class CrashProtectionCallback : public StackObj {
public:
virtual void call() = 0;
};
// Platform dependent stuff
#ifdef TARGET_OS_FAMILY_linux
@ -908,6 +915,7 @@ class os: AllStatic {
char pathSep);
static bool set_boot_path(char fileSep, char pathSep);
static char** split_path(const char* path, int* n);
};
// Note that "PAUSE" is almost always used with synchronization
@ -915,8 +923,6 @@ class os: AllStatic {
// of the global SpinPause() with C linkage.
// It'd also be eligible for inlining on many platforms.
extern "C" int SpinPause () ;
extern "C" int SafeFetch32 (int * adr, int errValue) ;
extern "C" intptr_t SafeFetchN (intptr_t * adr, intptr_t errValue) ;
extern "C" int SpinPause();
#endif // SHARE_VM_RUNTIME_OS_HPP

View file

@ -136,6 +136,13 @@ double (* StubRoutines::_intrinsic_sin )(double) = NULL;
double (* StubRoutines::_intrinsic_cos )(double) = NULL;
double (* StubRoutines::_intrinsic_tan )(double) = NULL;
address StubRoutines::_safefetch32_entry = NULL;
address StubRoutines::_safefetch32_fault_pc = NULL;
address StubRoutines::_safefetch32_continuation_pc = NULL;
address StubRoutines::_safefetchN_entry = NULL;
address StubRoutines::_safefetchN_fault_pc = NULL;
address StubRoutines::_safefetchN_continuation_pc = NULL;
// Initialization
//
// Note: to break cycle with universe initialization, stubs are generated in two phases.

View file

@ -224,6 +224,14 @@ class StubRoutines: AllStatic {
static double (*_intrinsic_cos)(double);
static double (*_intrinsic_tan)(double);
// Safefetch stubs.
static address _safefetch32_entry;
static address _safefetch32_fault_pc;
static address _safefetch32_continuation_pc;
static address _safefetchN_entry;
static address _safefetchN_fault_pc;
static address _safefetchN_continuation_pc;
public:
// Initialization/Testing
static void initialize1(); // must happen before universe::genesis
@ -384,6 +392,34 @@ class StubRoutines: AllStatic {
return _intrinsic_tan(d);
}
//
// Safefetch stub support
//
typedef int (*SafeFetch32Stub)(int* adr, int errValue);
typedef intptr_t (*SafeFetchNStub) (intptr_t* adr, intptr_t errValue);
static SafeFetch32Stub SafeFetch32_stub() { return CAST_TO_FN_PTR(SafeFetch32Stub, _safefetch32_entry); }
static SafeFetchNStub SafeFetchN_stub() { return CAST_TO_FN_PTR(SafeFetchNStub, _safefetchN_entry); }
static bool is_safefetch_fault(address pc) {
return pc != NULL &&
(pc == _safefetch32_fault_pc ||
pc == _safefetchN_fault_pc);
}
static address continuation_for_safefetch_fault(address pc) {
assert(_safefetch32_continuation_pc != NULL &&
_safefetchN_continuation_pc != NULL,
"not initialized");
if (pc == _safefetch32_fault_pc) return _safefetch32_continuation_pc;
if (pc == _safefetchN_fault_pc) return _safefetchN_continuation_pc;
ShouldNotReachHere();
return NULL;
}
//
// Default versions of the above arraycopy functions for platforms which do
// not have specialized versions
@ -403,4 +439,15 @@ class StubRoutines: AllStatic {
static void arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count);
};
// Safefetch allows to load a value from a location that's not known
// to be valid. If the load causes a fault, the error value is returned.
inline int SafeFetch32(int* adr, int errValue) {
assert(StubRoutines::SafeFetch32_stub(), "stub not yet generated");
return StubRoutines::SafeFetch32_stub()(adr, errValue);
}
inline intptr_t SafeFetchN(intptr_t* adr, intptr_t errValue) {
assert(StubRoutines::SafeFetchN_stub(), "stub not yet generated");
return StubRoutines::SafeFetchN_stub()(adr, errValue);
}
#endif // SHARE_VM_RUNTIME_STUBROUTINES_HPP

View file

@ -218,6 +218,7 @@ Thread::Thread() {
// allocated data structures
set_osthread(NULL);
set_resource_area(new (mtThread)ResourceArea());
DEBUG_ONLY(_current_resource_mark = NULL;)
set_handle_area(new (mtThread) HandleArea(NULL));
set_metadata_handles(new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(30, true));
set_active_handles(NULL);
@ -956,6 +957,14 @@ bool Thread::is_in_stack(address adr) const {
}
bool Thread::is_in_usable_stack(address adr) const {
size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0;
size_t usable_stack_size = _stack_size - stack_guard_size;
return ((adr < stack_base()) && (adr >= stack_base() - usable_stack_size));
}
// We had to move these methods here, because vm threads get into ObjectSynchronizer::enter
// However, there is a note in JavaThread::is_lock_owned() about the VM threads not being
// used for compilation in the future. If that change is made, the need for these methods
@ -1220,7 +1229,7 @@ WatcherThread* WatcherThread::_watcher_thread = NULL;
bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false;
WatcherThread::WatcherThread() : Thread() {
WatcherThread::WatcherThread() : Thread(), _crash_protection(NULL) {
assert(watcher_thread() == NULL, "we can only allocate one WatcherThread");
if (os::create_thread(this, os::watcher_thread)) {
_watcher_thread = this;
@ -3484,44 +3493,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
initialize_class(vmSymbols::java_lang_String(), CHECK_0);
if (AggressiveOpts) {
{
// Forcibly initialize java/util/HashMap and mutate the private
// static final "frontCacheEnabled" field before we start creating instances
#ifdef ASSERT
Klass* tmp_k = SystemDictionary::find(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
#endif
Klass* k_o = SystemDictionary::resolve_or_null(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
KlassHandle k = KlassHandle(THREAD, k_o);
guarantee(k.not_null(), "Must find java/util/HashMap");
instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
ik->initialize(CHECK_0);
fieldDescriptor fd;
// Possible we might not find this field; if so, don't break
if (ik->find_local_field(vmSymbols::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
k()->java_mirror()->bool_field_put(fd.offset(), true);
}
}
if (UseStringCache) {
// Forcibly initialize java/lang/StringValue and mutate the private
// static final "stringCacheEnabled" field before we start creating instances
Klass* k_o = SystemDictionary::resolve_or_null(vmSymbols::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
// Possible that StringValue isn't present: if so, silently don't break
if (k_o != NULL) {
KlassHandle k = KlassHandle(THREAD, k_o);
instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
ik->initialize(CHECK_0);
fieldDescriptor fd;
// Possible we might not find this field: if so, silently don't break
if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
k()->java_mirror()->bool_field_put(fd.offset(), true);
}
}
}
}
// Initialize java_lang.System (needed before creating the thread)
initialize_class(vmSymbols::java_lang_System(), CHECK_0);
initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0);
@ -3639,6 +3610,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// Start Attach Listener if +StartAttachListener or it can't be started lazily
if (!DisableAttachMechanism) {
AttachListener::vm_start();
if (StartAttachListener || AttachListener::init_at_startup()) {
AttachListener::init();
}

View file

@ -86,6 +86,8 @@ class GCTaskQueue;
class ThreadClosure;
class IdealGraphPrinter;
DEBUG_ONLY(class ResourceMark;)
class WorkerThread;
// Class hierarchy
@ -519,6 +521,9 @@ public:
// Check if address is in the stack of the thread (not just for locks).
// Warning: the method can only be used on the running thread
bool is_in_stack(address adr) const;
// Check if address is in the usable part of the stack (excludes protected
// guard pages)
bool is_in_usable_stack(address adr) const;
// Sets this thread as starting thread. Returns failure if thread
// creation fails due to lack of memory, too many threads etc.
@ -531,6 +536,8 @@ public:
// Thread local resource area for temporary allocation within the VM
ResourceArea* _resource_area;
DEBUG_ONLY(ResourceMark* _current_resource_mark;)
// Thread local handle area for allocation of handles within the VM
HandleArea* _handle_area;
GrowableArray<Metadata*>* _metadata_handles;
@ -585,6 +592,8 @@ public:
// Deadlock detection
bool allow_allocation() { return _allow_allocation_count == 0; }
ResourceMark* current_resource_mark() { return _current_resource_mark; }
void set_current_resource_mark(ResourceMark* rm) { _current_resource_mark = rm; }
#endif
void check_for_valid_safepoint_state(bool potential_vm_operation) PRODUCT_RETURN;
@ -724,6 +733,8 @@ class WatcherThread: public Thread {
static bool _startable;
volatile static bool _should_terminate; // updated without holding lock
os::WatcherThreadCrashProtection* _crash_protection;
public:
enum SomeConstants {
delay_interval = 10 // interrupt delay in milliseconds
@ -751,6 +762,14 @@ class WatcherThread: public Thread {
// Otherwise the first task to enroll will trigger the start
static void make_startable();
void set_crash_protection(os::WatcherThreadCrashProtection* crash_protection) {
assert(Thread::current()->is_Watcher_thread(), "Can only be set by WatcherThread");
_crash_protection = crash_protection;
}
bool has_crash_protection() const { return _crash_protection != NULL; }
os::WatcherThreadCrashProtection* crash_protection() const { return _crash_protection; }
private:
int sleep() const;
};

View file

@ -50,6 +50,7 @@ struct AttachOperationFunctionInfo {
class AttachListener: AllStatic {
public:
static void vm_start() NOT_SERVICES_RETURN;
static void init() NOT_SERVICES_RETURN;
static void abort() NOT_SERVICES_RETURN;

View file

@ -81,13 +81,13 @@ void MemTracker::init_tracking_options(const char* option_line) {
} else if (strcmp(option_line, "=detail") == 0) {
// detail relies on a stack-walking ability that may not
// be available depending on platform and/or compiler flags
if (PLATFORM_NMT_DETAIL_SUPPORTED) {
#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
_tracking_level = NMT_detail;
} else {
#else
jio_fprintf(defaultStream::error_stream(),
"NMT detail is not supported on this platform. Using NMT summary instead.");
"NMT detail is not supported on this platform. Using NMT summary instead.\n");
_tracking_level = NMT_summary;
}
#endif
} else if (strcmp(option_line, "=off") != 0) {
vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
}
@ -385,6 +385,7 @@ void MemTracker::enqueue_pending_recorder(MemRecorder* rec) {
#define SAFE_SEQUENCE_THRESHOLD 30
#define HIGH_GENERATION_THRESHOLD 60
#define MAX_RECORDER_THREAD_RATIO 30
#define MAX_RECORDER_PER_THREAD 100
void MemTracker::sync() {
assert(_tracking_level > NMT_off, "NMT is not enabled");
@ -437,6 +438,11 @@ void MemTracker::sync() {
// means that worker thread is lagging behind in processing them.
if (!AutoShutdownNMT) {
_slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count);
} else {
// If auto shutdown is on, enforce MAX_RECORDER_PER_THREAD threshold to prevent OOM
if (MemRecorder::_instance_count >= _thread_count * MAX_RECORDER_PER_THREAD) {
shutdown(NMT_out_of_memory);
}
}
// check _worker_thread with lock to avoid racing condition

View file

@ -63,5 +63,7 @@ typedef u8 stacktraceid;
typedef u8 methodid;
typedef u8 fieldid;
class TraceUnicodeString;
#endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP

View file

@ -55,18 +55,6 @@ Before we can use it we need also define a primary field data type:
type="u8" sizeop="sizeof(u1)"/>
Now we can use the content + data type in declaring event fields.
Remember however, that for us to be able to resolve the value later we must also add
creating the constant pool data in VM_JFRCheckpoint::write_checkpoint
...
//CGMODE
w->be_uint(CONTENT_TYPE_GCMODE);
w->be_uint(MM_GC_MODE_UNINITIALIZED);
for (i = 0; i < MM_GC_MODE_UNINITIALIZED; i++) {
w->uchar(i);
w->write_utf8(gcModeGetName(i));
}
-->
<types>
@ -81,10 +69,6 @@ creating the constant pool data in VM_JFRCheckpoint::write_checkpoint
<value type="OSTHREAD" field="thread" label="VM Thread"/>
</content_type>
<!-- The first argument ("JavaThread") is misleading, it's really a
java.lang.Thread id (long), but Mission Control depends on the name
being "JavaThread" so it shouldn't be changed.
-->
<content_type id="JavaThread" hr_name="Java thread"
type="U8" builtin_type="JAVALANGTHREAD">
<value type="OSTHREAD" field="thread" label="OS Thread ID"/>
@ -285,6 +269,10 @@ creating the constant pool data in VM_JFRCheckpoint::write_checkpoint
<primary_type symbol="UTF8" datatype="UTF8" contenttype="NONE"
type="const char *" sizeop="sizeof_utf(%)"/>
<!-- UTF-16 encoded (Unicode) string, max length maxjuint -->
<primary_type symbol="STRING" datatype="STRING" contenttype="NONE"
type="TraceUnicodeString*" sizeop="sizeof_unicode(%)"/>
<!-- Symbol* constant. Note that this may currently ONLY be used by
classes, methods fields. This restriction might be lifted. -->
<primary_type symbol="SYMBOL" datatype="U8" contenttype="SYMBOL"

View file

@ -1,28 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012, 2013, 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.
-->
<!--
Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

View file

@ -381,12 +381,12 @@ const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlass
#endif
/*
* If a platform does not support NMT_detail
* If a platform does not support native stack walking
* the platform specific globalDefinitions (above)
* can set PLATFORM_NMT_DETAIL_SUPPORTED to false
* can set PLATFORM_NATIVE_STACK_WALKING_SUPPORTED to 0
*/
#ifndef PLATFORM_NMT_DETAIL_SUPPORTED
#define PLATFORM_NMT_DETAIL_SUPPORTED true
#ifndef PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
#define PLATFORM_NATIVE_STACK_WALKING_SUPPORTED 1
#endif
// The byte alignment to be used by Arena::Amalloc. See bugid 4169348.

View file

@ -296,6 +296,7 @@ stringStream::stringStream(size_t initial_size) : outputStream() {
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
buffer_pos = 0;
buffer_fixed = false;
DEBUG_ONLY(rm = Thread::current()->current_resource_mark();)
}
// useful for output to fixed chunks of memory, such as performance counters
@ -321,6 +322,8 @@ void stringStream::write(const char* s, size_t len) {
end = buffer_length * 2;
}
char* oldbuf = buffer;
assert(rm == NULL || Thread::current()->current_resource_mark() == rm,
"stringStream is re-allocated with a different ResourceMark");
buffer = NEW_RESOURCE_ARRAY(char, end);
strncpy(buffer, oldbuf, buffer_pos);
buffer_length = end;

View file

@ -28,6 +28,8 @@
#include "memory/allocation.hpp"
#include "runtime/timer.hpp"
DEBUG_ONLY(class ResourceMark;)
// Output streams for printing
//
// Printing guidelines:
@ -177,6 +179,7 @@ class stringStream : public outputStream {
size_t buffer_pos;
size_t buffer_length;
bool buffer_fixed;
DEBUG_ONLY(ResourceMark* rm;)
public:
stringStream(size_t initial_bufsize = 256);
stringStream(char* fixed_buffer, size_t fixed_buffer_size);