提交 b2f75e8c 编写于 作者: I iveresov

7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer

Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
上级 a177158b
...@@ -2419,11 +2419,8 @@ void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias, ...@@ -2419,11 +2419,8 @@ void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias,
void LIR_Assembler::setup_md_access(ciMethod* method, int bci, void LIR_Assembler::setup_md_access(ciMethod* method, int bci,
ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) { ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) {
md = method->method_data(); md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
data = md->bci_to_data(bci); data = md->bci_to_data(bci);
assert(data != NULL, "need data for checkcast"); assert(data != NULL, "need data for checkcast");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
...@@ -2821,11 +2818,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ...@@ -2821,11 +2818,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
int bci = op->profiled_bci(); int bci = op->profiled_bci();
// Update counter for all call types // Update counter for all call types
ciMethodData* md = method->method_data(); ciMethodData* md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
ciProfileData* data = md->bci_to_data(bci); ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls"); assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
......
...@@ -1716,11 +1716,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L ...@@ -1716,11 +1716,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
ciMethod* method = op->profiled_method(); ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method"); assert(method != NULL, "Should have method");
int bci = op->profiled_bci(); int bci = op->profiled_bci();
md = method->method_data(); md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
data = md->bci_to_data(bci); data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check"); assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
...@@ -1879,11 +1876,8 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { ...@@ -1879,11 +1876,8 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
ciMethod* method = op->profiled_method(); ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method"); assert(method != NULL, "Should have method");
int bci = op->profiled_bci(); int bci = op->profiled_bci();
md = method->method_data(); md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
data = md->bci_to_data(bci); data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check"); assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
...@@ -3373,11 +3367,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { ...@@ -3373,11 +3367,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
int bci = op->profiled_bci(); int bci = op->profiled_bci();
// Update counter for all call types // Update counter for all call types
ciMethodData* md = method->method_data(); ciMethodData* md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
ciProfileData* data = md->bci_to_data(bci); ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls"); assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
......
...@@ -298,8 +298,8 @@ int Compilation::compile_java_method() { ...@@ -298,8 +298,8 @@ int Compilation::compile_java_method() {
CHECK_BAILOUT_(no_frame_size); CHECK_BAILOUT_(no_frame_size);
if (is_profiling()) { if (is_profiling() && !method()->ensure_method_data()) {
method()->build_method_data(); BAILOUT_("mdo allocation failed", no_frame_size);
} }
{ {
...@@ -484,11 +484,11 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho ...@@ -484,11 +484,11 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
if (is_profiling()) { if (is_profiling()) {
// Compilation failed, create MDO, which would signal the interpreter // Compilation failed, create MDO, which would signal the interpreter
// to start profiling on its own. // to start profiling on its own.
_method->build_method_data(); _method->ensure_method_data();
} }
} else if (is_profiling() && _would_profile) { } else if (is_profiling() && _would_profile) {
ciMethodData *md = method->method_data(); ciMethodData *md = method->method_data_or_null();
assert (md != NULL, "Should have MDO"); assert(md != NULL, "Sanity");
md->set_would_profile(_would_profile); md->set_would_profile(_would_profile);
} }
} }
......
...@@ -3377,6 +3377,9 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { ...@@ -3377,6 +3377,9 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
INLINE_BAILOUT("total inlining greater than DesiredMethodLimit"); INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
} }
if (is_profiling() && !callee->ensure_method_data()) {
INLINE_BAILOUT("mdo allocation failed");
}
#ifndef PRODUCT #ifndef PRODUCT
// printing // printing
if (PrintInlining) { if (PrintInlining) {
......
...@@ -504,7 +504,12 @@ ComputeLinearScanOrder::ComputeLinearScanOrder(Compilation* c, BlockBegin* start ...@@ -504,7 +504,12 @@ ComputeLinearScanOrder::ComputeLinearScanOrder(Compilation* c, BlockBegin* start
count_edges(start_block, NULL); count_edges(start_block, NULL);
if (compilation()->is_profiling()) { if (compilation()->is_profiling()) {
compilation()->method()->method_data()->set_compilation_stats(_num_loops, _num_blocks); ciMethod *method = compilation()->method();
if (!method->is_accessor()) {
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
md->set_compilation_stats(_num_loops, _num_blocks);
}
} }
if (_num_loops > 0) { if (_num_loops > 0) {
......
...@@ -836,11 +836,8 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { ...@@ -836,11 +836,8 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) {
if (if_instr->should_profile()) { if (if_instr->should_profile()) {
ciMethod* method = if_instr->profiled_method(); ciMethod* method = if_instr->profiled_method();
assert(method != NULL, "method should be set if branch is profiled"); assert(method != NULL, "method should be set if branch is profiled");
ciMethodData* md = method->method_data(); ciMethodData* md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
ciProfileData* data = md->bci_to_data(if_instr->profiled_bci()); ciProfileData* data = md->bci_to_data(if_instr->profiled_bci());
assert(data != NULL, "must have profiling data"); assert(data != NULL, "must have profiling data");
assert(data->is_BranchData(), "need BranchData for two-way branches"); assert(data->is_BranchData(), "need BranchData for two-way branches");
...@@ -2219,11 +2216,8 @@ void LIRGenerator::do_Goto(Goto* x) { ...@@ -2219,11 +2216,8 @@ void LIRGenerator::do_Goto(Goto* x) {
if (x->should_profile()) { if (x->should_profile()) {
ciMethod* method = x->profiled_method(); ciMethod* method = x->profiled_method();
assert(method != NULL, "method should be set if branch is profiled"); assert(method != NULL, "method should be set if branch is profiled");
ciMethodData* md = method->method_data(); ciMethodData* md = method->method_data_or_null();
if (md == NULL) { assert(md != NULL, "Sanity");
bailout("out of memory building methodDataOop");
return;
}
ciProfileData* data = md->bci_to_data(x->profiled_bci()); ciProfileData* data = md->bci_to_data(x->profiled_bci());
assert(data != NULL, "must have profiling data"); assert(data != NULL, "must have profiling data");
int offset; int offset;
...@@ -2723,7 +2717,9 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, ...@@ -2723,7 +2717,9 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info,
} else if (level == CompLevel_full_profile) { } else if (level == CompLevel_full_profile) {
offset = in_bytes(backedge ? methodDataOopDesc::backedge_counter_offset() : offset = in_bytes(backedge ? methodDataOopDesc::backedge_counter_offset() :
methodDataOopDesc::invocation_counter_offset()); methodDataOopDesc::invocation_counter_offset());
__ oop2reg(method->method_data()->constant_encoding(), counter_holder); ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
__ oop2reg(md->constant_encoding(), counter_holder);
meth = new_register(T_OBJECT); meth = new_register(T_OBJECT);
__ oop2reg(method->constant_encoding(), meth); __ oop2reg(method->constant_encoding(), meth);
} else { } else {
......
...@@ -797,12 +797,13 @@ ciInstance* ciMethod::method_handle_type() { ...@@ -797,12 +797,13 @@ ciInstance* ciMethod::method_handle_type() {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::build_method_data // ciMethod::ensure_method_data
// //
// Generate new methodDataOop objects at compile time. // Generate new methodDataOop objects at compile time.
void ciMethod::build_method_data(methodHandle h_m) { // Return true if allocation was successful or no MDO is required.
bool ciMethod::ensure_method_data(methodHandle h_m) {
EXCEPTION_CONTEXT; EXCEPTION_CONTEXT;
if (is_native() || is_abstract() || h_m()->is_accessor()) return; if (is_native() || is_abstract() || h_m()->is_accessor()) return true;
if (h_m()->method_data() == NULL) { if (h_m()->method_data() == NULL) {
methodOopDesc::build_interpreter_method_data(h_m, THREAD); methodOopDesc::build_interpreter_method_data(h_m, THREAD);
if (HAS_PENDING_EXCEPTION) { if (HAS_PENDING_EXCEPTION) {
...@@ -812,18 +813,22 @@ void ciMethod::build_method_data(methodHandle h_m) { ...@@ -812,18 +813,22 @@ void ciMethod::build_method_data(methodHandle h_m) {
if (h_m()->method_data() != NULL) { if (h_m()->method_data() != NULL) {
_method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data(); _method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
_method_data->load_data(); _method_data->load_data();
return true;
} else { } else {
_method_data = CURRENT_ENV->get_empty_methodData(); _method_data = CURRENT_ENV->get_empty_methodData();
return false;
} }
} }
// public, retroactive version // public, retroactive version
void ciMethod::build_method_data() { bool ciMethod::ensure_method_data() {
bool result = true;
if (_method_data == NULL || _method_data->is_empty()) { if (_method_data == NULL || _method_data->is_empty()) {
GUARDED_VM_ENTRY({ GUARDED_VM_ENTRY({
build_method_data(get_methodOop()); result = ensure_method_data(get_methodOop());
}); });
} }
return result;
} }
...@@ -839,11 +844,6 @@ ciMethodData* ciMethod::method_data() { ...@@ -839,11 +844,6 @@ ciMethodData* ciMethod::method_data() {
Thread* my_thread = JavaThread::current(); Thread* my_thread = JavaThread::current();
methodHandle h_m(my_thread, get_methodOop()); methodHandle h_m(my_thread, get_methodOop());
// Create an MDO for the inlinee
if (TieredCompilation && is_c1_compile(env->comp_level())) {
build_method_data(h_m);
}
if (h_m()->method_data() != NULL) { if (h_m()->method_data() != NULL) {
_method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data(); _method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
_method_data->load_data(); _method_data->load_data();
...@@ -854,6 +854,15 @@ ciMethodData* ciMethod::method_data() { ...@@ -854,6 +854,15 @@ ciMethodData* ciMethod::method_data() {
} }
// ------------------------------------------------------------------
// ciMethod::method_data_or_null
// Returns a pointer to ciMethodData if MDO exists on the VM side,
// NULL otherwise.
ciMethodData* ciMethod::method_data_or_null() {
ciMethodData *md = method_data();
if (md->is_empty()) return NULL;
return md;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::will_link // ciMethod::will_link
......
...@@ -106,7 +106,7 @@ class ciMethod : public ciObject { ...@@ -106,7 +106,7 @@ class ciMethod : public ciObject {
void check_is_loaded() const { assert(is_loaded(), "not loaded"); } void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
void build_method_data(methodHandle h_m); bool ensure_method_data(methodHandle h_m);
void code_at_put(int bci, Bytecodes::Code code) { void code_at_put(int bci, Bytecodes::Code code) {
Bytecodes::check(code); Bytecodes::check(code);
...@@ -121,6 +121,7 @@ class ciMethod : public ciObject { ...@@ -121,6 +121,7 @@ class ciMethod : public ciObject {
ciSymbol* name() const { return _name; } ciSymbol* name() const { return _name; }
ciInstanceKlass* holder() const { return _holder; } ciInstanceKlass* holder() const { return _holder; }
ciMethodData* method_data(); ciMethodData* method_data();
ciMethodData* method_data_or_null();
// Signature information. // Signature information.
ciSignature* signature() const { return _signature; } ciSignature* signature() const { return _signature; }
...@@ -230,7 +231,7 @@ class ciMethod : public ciObject { ...@@ -230,7 +231,7 @@ class ciMethod : public ciObject {
bool has_unloaded_classes_in_signature(); bool has_unloaded_classes_in_signature();
bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const; bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const;
bool check_call(int refinfo_index, bool is_static) const; bool check_call(int refinfo_index, bool is_static) const;
void build_method_data(); // make sure it exists in the VM also bool ensure_method_data(); // make sure it exists in the VM also
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
// JSR 292 support // JSR 292 support
......
...@@ -553,7 +553,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -553,7 +553,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
if (ProfileTraps) { if (ProfileTraps) {
// Make sure the method being compiled gets its own MDO, // Make sure the method being compiled gets its own MDO,
// so we can at least track the decompile_count(). // so we can at least track the decompile_count().
method()->build_method_data(); method()->ensure_method_data();
} }
Init(::AliasLevel); Init(::AliasLevel);
......
...@@ -1841,7 +1841,7 @@ void GraphKit::uncommon_trap(int trap_request, ...@@ -1841,7 +1841,7 @@ void GraphKit::uncommon_trap(int trap_request,
// Note: If ProfileTraps is true, and if a deopt. actually // Note: If ProfileTraps is true, and if a deopt. actually
// occurs here, the runtime will make sure an MDO exists. There is // occurs here, the runtime will make sure an MDO exists. There is
// no need to call method()->build_method_data() at this point. // no need to call method()->ensure_method_data() at this point.
#ifdef ASSERT #ifdef ASSERT
if (!must_throw) { if (!must_throw) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册