6788527: Server vm intermittently fails with assertion "live value must not be garbage" with fastdebug bits
Cache Jvmti and DTrace flags used by Compiler. Reviewed-by: never
This commit is contained in:
parent
b5cff6a1a0
commit
34ee921399
@ -378,7 +378,7 @@ void LIR_Assembler::emit_exception_handler() {
|
||||
compilation()->offsets()->set_value(CodeOffsets::Exceptions, code_offset());
|
||||
|
||||
|
||||
if (compilation()->has_exception_handlers() || JvmtiExport::can_post_exceptions()) {
|
||||
if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_exceptions()) {
|
||||
__ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
|
||||
__ delayed()->nop();
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ void C1_MacroAssembler::initialize_object(
|
||||
initialize_body(base, index);
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == O0, "must be");
|
||||
call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
|
||||
relocInfo::runtime_call_type);
|
||||
@ -355,7 +355,7 @@ void C1_MacroAssembler::allocate_array(
|
||||
sub(arr_size, hdr_size * wordSize, index); // compute index = number of words to clear
|
||||
initialize_body(base, index);
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == O0, "must be");
|
||||
call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
|
||||
relocInfo::runtime_call_type);
|
||||
|
@ -439,7 +439,7 @@ void LIR_Assembler::emit_exception_handler() {
|
||||
|
||||
// if the method does not have an exception handler, then there is
|
||||
// no reason to search for one
|
||||
if (compilation()->has_exception_handlers() || JvmtiExport::can_post_exceptions()) {
|
||||
if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_exceptions()) {
|
||||
// the exception oop and pc are in rax, and rdx
|
||||
// no other registers need to be preserved, so invalidate them
|
||||
__ invalidate_registers(false, true, true, false, true, true);
|
||||
|
@ -258,7 +258,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
|
||||
}
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == rax, "must be");
|
||||
call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
|
||||
}
|
||||
@ -291,7 +291,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
|
||||
const Register len_zero = len;
|
||||
initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == rax, "must be");
|
||||
call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ void Compilation::compile_method() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (_env->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
// We can assert evol_method because method->can_be_compiled is true.
|
||||
dependency_recorder()->assert_evol_method(method());
|
||||
}
|
||||
@ -435,7 +435,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||
assert(_arena == NULL, "shouldn't only one instance of Compilation in existence at a time");
|
||||
_arena = Thread::current()->resource_area();
|
||||
_compilation = this;
|
||||
_needs_debug_information = JvmtiExport::can_examine_or_deopt_anywhere() ||
|
||||
_needs_debug_information = _env->jvmti_can_examine_or_deopt_anywhere() ||
|
||||
JavaMonitorsInStackTrace || AlwaysEmitDebugInfo || DeoptimizeALot;
|
||||
_exception_info_list = new ExceptionInfoList();
|
||||
_implicit_exception_table.set_size(0);
|
||||
|
@ -1662,7 +1662,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
// Register dependence if JVMTI has either breakpoint
|
||||
// setting or hotswapping of methods capabilities since they may
|
||||
// cause deoptimization.
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
dependency_recorder()->assert_evol_method(inline_target);
|
||||
}
|
||||
return;
|
||||
@ -2863,7 +2863,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
|
||||
start_block->merge(_initial_state);
|
||||
|
||||
BlockBegin* sync_handler = NULL;
|
||||
if (method()->is_synchronized() || DTraceMethodProbes) {
|
||||
if (method()->is_synchronized() || _compilation->env()->dtrace_method_probes()) {
|
||||
// setup an exception handler to do the unlocking and/or notification
|
||||
sync_handler = new BlockBegin(-1);
|
||||
sync_handler->set(BlockBegin::exception_entry_flag);
|
||||
|
@ -1064,7 +1064,7 @@ void LIRGenerator::do_IfInstanceOf(IfInstanceOf* x) {
|
||||
|
||||
|
||||
void LIRGenerator::do_Return(Return* x) {
|
||||
if (DTraceMethodProbes) {
|
||||
if (compilation()->env()->dtrace_method_probes()) {
|
||||
BasicTypeList signature;
|
||||
signature.append(T_INT); // thread
|
||||
signature.append(T_OBJECT); // methodOop
|
||||
@ -1769,7 +1769,7 @@ void LIRGenerator::do_Throw(Throw* x) {
|
||||
__ null_check(exception_opr, new CodeEmitInfo(info, true));
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_post_exceptions() &&
|
||||
if (compilation()->env()->jvmti_can_post_exceptions() &&
|
||||
!block()->is_set(BlockBegin::default_exception_handler_flag)) {
|
||||
// we need to go through the exception lookup path to get JVMTI
|
||||
// notification done
|
||||
@ -1779,7 +1779,7 @@ void LIRGenerator::do_Throw(Throw* x) {
|
||||
assert(!block()->is_set(BlockBegin::default_exception_handler_flag) || unwind,
|
||||
"should be no more handlers to dispatch to");
|
||||
|
||||
if (DTraceMethodProbes &&
|
||||
if (compilation()->env()->dtrace_method_probes() &&
|
||||
block()->is_set(BlockBegin::default_exception_handler_flag)) {
|
||||
// notify that this frame is unwinding
|
||||
BasicTypeList signature;
|
||||
@ -2204,7 +2204,7 @@ void LIRGenerator::do_Base(Base* x) {
|
||||
java_index += type2size[t];
|
||||
}
|
||||
|
||||
if (DTraceMethodProbes) {
|
||||
if (compilation()->env()->dtrace_method_probes()) {
|
||||
BasicTypeList signature;
|
||||
signature.append(T_INT); // thread
|
||||
signature.append(T_OBJECT); // methodOop
|
||||
|
@ -170,6 +170,34 @@ ciEnv::~ciEnv() {
|
||||
current_thread->set_env(NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Cache Jvmti state
|
||||
void ciEnv::cache_jvmti_state() {
|
||||
VM_ENTRY_MARK;
|
||||
// Get Jvmti capabilities under lock to get consistant values.
|
||||
MutexLocker mu(JvmtiThreadState_lock);
|
||||
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
|
||||
_jvmti_can_examine_or_deopt_anywhere = JvmtiExport::can_examine_or_deopt_anywhere();
|
||||
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
|
||||
_jvmti_can_post_exceptions = JvmtiExport::can_post_exceptions();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Cache DTrace flags
|
||||
void ciEnv::cache_dtrace_flags() {
|
||||
// Need lock?
|
||||
_dtrace_extended_probes = ExtendedDTraceProbes;
|
||||
if (_dtrace_extended_probes) {
|
||||
_dtrace_monitor_probes = true;
|
||||
_dtrace_method_probes = true;
|
||||
_dtrace_alloc_probes = true;
|
||||
} else {
|
||||
_dtrace_monitor_probes = DTraceMonitorProbes;
|
||||
_dtrace_method_probes = DTraceMethodProbes;
|
||||
_dtrace_alloc_probes = DTraceAllocProbes;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// helper for lazy exception creation
|
||||
ciInstance* ciEnv::get_or_create_exception(jobject& handle, symbolHandle name) {
|
||||
@ -810,16 +838,39 @@ void ciEnv::register_method(ciMethod* target,
|
||||
// and invalidating our dependencies until we install this method.
|
||||
MutexLocker ml(Compile_lock);
|
||||
|
||||
if (log() != NULL) {
|
||||
// Log the dependencies which this compilation declares.
|
||||
dependencies()->log_all_dependencies();
|
||||
// Change in Jvmti state may invalidate compilation.
|
||||
if (!failing() &&
|
||||
( (!jvmti_can_hotswap_or_post_breakpoint() &&
|
||||
JvmtiExport::can_hotswap_or_post_breakpoint()) ||
|
||||
(!jvmti_can_examine_or_deopt_anywhere() &&
|
||||
JvmtiExport::can_examine_or_deopt_anywhere()) ||
|
||||
(!jvmti_can_access_local_variables() &&
|
||||
JvmtiExport::can_access_local_variables()) ||
|
||||
(!jvmti_can_post_exceptions() &&
|
||||
JvmtiExport::can_post_exceptions()) )) {
|
||||
record_failure("Jvmti state change invalidated dependencies");
|
||||
}
|
||||
|
||||
// Encode the dependencies now, so we can check them right away.
|
||||
dependencies()->encode_content_bytes();
|
||||
// Change in DTrace flags may invalidate compilation.
|
||||
if (!failing() &&
|
||||
( (!dtrace_extended_probes() && ExtendedDTraceProbes) ||
|
||||
(!dtrace_method_probes() && DTraceMethodProbes) ||
|
||||
(!dtrace_alloc_probes() && DTraceAllocProbes) )) {
|
||||
record_failure("DTrace flags change invalidated dependencies");
|
||||
}
|
||||
|
||||
// Check for {class loads, evolution, breakpoints} during compilation
|
||||
check_for_system_dictionary_modification(target);
|
||||
if (!failing()) {
|
||||
if (log() != NULL) {
|
||||
// Log the dependencies which this compilation declares.
|
||||
dependencies()->log_all_dependencies();
|
||||
}
|
||||
|
||||
// Encode the dependencies now, so we can check them right away.
|
||||
dependencies()->encode_content_bytes();
|
||||
|
||||
// Check for {class loads, evolution, breakpoints} during compilation
|
||||
check_for_system_dictionary_modification(target);
|
||||
}
|
||||
|
||||
methodHandle method(THREAD, target->get_methodOop());
|
||||
|
||||
|
@ -53,6 +53,18 @@ private:
|
||||
char* _name_buffer;
|
||||
int _name_buffer_len;
|
||||
|
||||
// Cache Jvmti state
|
||||
bool _jvmti_can_hotswap_or_post_breakpoint;
|
||||
bool _jvmti_can_examine_or_deopt_anywhere;
|
||||
bool _jvmti_can_access_local_variables;
|
||||
bool _jvmti_can_post_exceptions;
|
||||
|
||||
// Cache DTrace flags
|
||||
bool _dtrace_extended_probes;
|
||||
bool _dtrace_monitor_probes;
|
||||
bool _dtrace_method_probes;
|
||||
bool _dtrace_alloc_probes;
|
||||
|
||||
// Distinguished instances of certain ciObjects..
|
||||
static ciObject* _null_object_instance;
|
||||
static ciMethodKlass* _method_klass_instance;
|
||||
@ -236,6 +248,20 @@ public:
|
||||
bool break_at_compile() { return _break_at_compile; }
|
||||
void set_break_at_compile(bool z) { _break_at_compile = z; }
|
||||
|
||||
// Cache Jvmti state
|
||||
void cache_jvmti_state();
|
||||
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
|
||||
bool jvmti_can_examine_or_deopt_anywhere() const { return _jvmti_can_examine_or_deopt_anywhere; }
|
||||
bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables; }
|
||||
bool jvmti_can_post_exceptions() const { return _jvmti_can_post_exceptions; }
|
||||
|
||||
// Cache DTrace flags
|
||||
void cache_dtrace_flags();
|
||||
bool dtrace_extended_probes() const { return _dtrace_extended_probes; }
|
||||
bool dtrace_monitor_probes() const { return _dtrace_monitor_probes; }
|
||||
bool dtrace_method_probes() const { return _dtrace_method_probes; }
|
||||
bool dtrace_alloc_probes() const { return _dtrace_alloc_probes; }
|
||||
|
||||
// The compiler task which has created this env.
|
||||
// May be useful to find out compile_id, comp_level, etc.
|
||||
CompileTask* task() { return _task; }
|
||||
|
@ -60,7 +60,8 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
_flow = NULL;
|
||||
#endif // COMPILER2
|
||||
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint() && _is_compilable) {
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
if (env->jvmti_can_hotswap_or_post_breakpoint() && _is_compilable) {
|
||||
// 6328518 check hotswap conditions under the right lock.
|
||||
MutexLocker locker(Compile_lock);
|
||||
if (Dependencies::check_evol_method(h_m()) != NULL) {
|
||||
@ -84,7 +85,6 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
if (_can_be_statically_bound && h_m()->is_abstract())
|
||||
_can_be_statically_bound = false;
|
||||
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
// generating _signature may allow GC and therefore move m.
|
||||
// These fields are always filled in.
|
||||
_name = env->get_object(h_m()->name())->as_symbol();
|
||||
@ -337,7 +337,7 @@ MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
|
||||
_liveness->compute_liveness();
|
||||
}
|
||||
MethodLivenessResult result = _liveness->get_liveness_at(bci);
|
||||
if (JvmtiExport::can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
||||
if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
||||
// Keep all locals live for the user's edification and amusement.
|
||||
result.at_put_range(0, result.size(), true);
|
||||
}
|
||||
|
@ -1530,6 +1530,12 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
assert(thread->env() == &ci_env, "set by ci_env");
|
||||
// The thread-env() field is cleared in ~CompileTaskWrapper.
|
||||
|
||||
// Cache Jvmti state
|
||||
ci_env.cache_jvmti_state();
|
||||
|
||||
// Cache DTrace flags
|
||||
ci_env.cache_dtrace_flags();
|
||||
|
||||
ciMethod* target = ci_env.get_method_from_handle(target_handle);
|
||||
|
||||
TraceTime t1("compilation", &time);
|
||||
|
@ -47,7 +47,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
|
||||
CallGenerator* cg;
|
||||
|
||||
// Dtrace currently doesn't work unless all calls are vanilla
|
||||
if (DTraceMethodProbes) {
|
||||
if (env()->dtrace_method_probes()) {
|
||||
allow_inline = false;
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ Bytecodes::Code GraphKit::java_bc() const {
|
||||
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
|
||||
bool must_throw = true;
|
||||
|
||||
if (JvmtiExport::can_post_exceptions()) {
|
||||
if (env()->jvmti_can_post_exceptions()) {
|
||||
// Do not try anything fancy if we're notifying the VM on every throw.
|
||||
// Cf. case Bytecodes::_athrow in parse2.cpp.
|
||||
uncommon_trap(reason, Deoptimization::Action_none,
|
||||
@ -769,7 +769,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) {
|
||||
}
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_examine_or_deopt_anywhere()) {
|
||||
if (env()->jvmti_can_examine_or_deopt_anywhere()) {
|
||||
// At any safepoint, this method can get breakpointed, which would
|
||||
// then require an immediate deoptimization.
|
||||
full_info = true;
|
||||
|
@ -988,7 +988,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
initial_slow_test = BoolNode::make_predicate(initial_slow_test, &_igvn);
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes ||
|
||||
if (C->env()->dtrace_alloc_probes() ||
|
||||
!UseTLAB && (!Universe::heap()->supports_inline_contig_alloc() ||
|
||||
(UseConcMarkSweepGC && CMSIncrementalMode))) {
|
||||
// Force slow-path allocation
|
||||
@ -1150,7 +1150,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
fast_oop_ctrl, fast_oop_rawmem, fast_oop,
|
||||
klass_node, length, size_in_bytes);
|
||||
|
||||
if (ExtendedDTraceProbes) {
|
||||
if (C->env()->dtrace_extended_probes()) {
|
||||
// Slow-path call
|
||||
int size = TypeFunc::Parms + 2;
|
||||
CallLeafNode *call = new (C, size) CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(),
|
||||
|
@ -439,7 +439,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
|
||||
// Always register dependence if JVMTI is enabled, because
|
||||
// either breakpoint setting or hotswapping of methods may
|
||||
// cause deoptimization.
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (C->env()->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
C->dependencies()->assert_evol_method(method());
|
||||
}
|
||||
|
||||
@ -953,7 +953,7 @@ void Parse::do_exits() {
|
||||
bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
|
||||
|
||||
// record exit from a method if compiled while Dtrace is turned on.
|
||||
if (do_synch || DTraceMethodProbes) {
|
||||
if (do_synch || C->env()->dtrace_method_probes()) {
|
||||
// First move the exception list out of _exits:
|
||||
GraphKit kit(_exits.transfer_exceptions_into_jvms());
|
||||
SafePointNode* normal_map = kit.map(); // keep this guy safe
|
||||
@ -975,7 +975,7 @@ void Parse::do_exits() {
|
||||
// Unlock!
|
||||
kit.shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
|
||||
}
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
kit.make_dtrace_method_exit(method());
|
||||
}
|
||||
// Done with exception-path processing.
|
||||
@ -1074,7 +1074,7 @@ void Parse::do_method_entry() {
|
||||
|
||||
NOT_PRODUCT( count_compiled_calls(true/*at_method_entry*/, false/*is_inline*/); )
|
||||
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
make_dtrace_method_entry(method());
|
||||
}
|
||||
|
||||
@ -1960,7 +1960,7 @@ void Parse::return_current(Node* value) {
|
||||
if (method()->is_synchronized() && GenerateSynchronizationCode) {
|
||||
shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
|
||||
}
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
make_dtrace_method_exit(method());
|
||||
}
|
||||
SafePointNode* exit_return = _exits.map();
|
||||
|
@ -2052,7 +2052,7 @@ void Parse::do_one_bytecode() {
|
||||
// null exception oop throws NULL pointer exception
|
||||
do_null_check(peek(), T_OBJECT);
|
||||
if (stopped()) return;
|
||||
if (JvmtiExport::can_post_exceptions()) {
|
||||
if (env()->jvmti_can_post_exceptions()) {
|
||||
// "Full-speed throwing" is not necessary here,
|
||||
// since we're notifying the VM on every throw.
|
||||
uncommon_trap(Deoptimization::Reason_unhandled,
|
||||
|
Loading…
Reference in New Issue
Block a user