src/share/vm/opto/callGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/opto/callGenerator.cpp
src/share/vm/opto/callGenerator.cpp
Print this page
rev 6442 : 8026796: Make replace_in_map() on parent maps generic
Summary: propagate node replacements along control flow edges to callers
Reviewed-by:
*** 61,76 ****
_expected_uses = expected_uses;
assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible");
}
virtual bool is_parse() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
int is_osr() { return _is_osr; }
};
! JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
Compile* C = Compile::current();
C->print_inlining_update(this);
if (is_osr()) {
// The JVMS for a OSR has a single argument (see its TypeFunc).
--- 61,76 ----
_expected_uses = expected_uses;
assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible");
}
virtual bool is_parse() const { return true; }
! virtual JVMState* generate(JVMState* jvms);
int is_osr() { return _is_osr; }
};
! JVMState* ParseGenerator::generate(JVMState* jvms) {
Compile* C = Compile::current();
C->print_inlining_update(this);
if (is_osr()) {
// The JVMS for a OSR has a single argument (see its TypeFunc).
*** 79,89 ****
if (C->failing()) {
return NULL; // bailing out of the compile; do not try to parse
}
! Parse parser(jvms, method(), _expected_uses, parent_parser);
// Grab signature for matching/allocation
#ifdef ASSERT
if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
assert(C->env()->system_dictionary_modification_counter_changed(),
--- 79,89 ----
if (C->failing()) {
return NULL; // bailing out of the compile; do not try to parse
}
! Parse parser(jvms, method(), _expected_uses);
// Grab signature for matching/allocation
#ifdef ASSERT
if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
assert(C->env()->system_dictionary_modification_counter_changed(),
*** 118,133 ****
DirectCallGenerator(ciMethod* method, bool separate_io_proj)
: CallGenerator(method),
_separate_io_proj(separate_io_proj)
{
}
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
CallStaticJavaNode* call_node() const { return _call_node; }
};
! JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
bool is_static = method()->is_static();
address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
: SharedRuntime::get_resolve_opt_virtual_call_stub();
--- 118,133 ----
DirectCallGenerator(ciMethod* method, bool separate_io_proj)
: CallGenerator(method),
_separate_io_proj(separate_io_proj)
{
}
! virtual JVMState* generate(JVMState* jvms);
CallStaticJavaNode* call_node() const { return _call_node; }
};
! JVMState* DirectCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
bool is_static = method()->is_static();
address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
: SharedRuntime::get_resolve_opt_virtual_call_stub();
*** 171,184 ****
{
assert(vtable_index == Method::invalid_vtable_index ||
vtable_index >= 0, "either invalid or usable");
}
virtual bool is_virtual() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
! JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
Node* receiver = kit.argument(0);
kit.C->print_inlining_update(this);
--- 171,184 ----
{
assert(vtable_index == Method::invalid_vtable_index ||
vtable_index >= 0, "either invalid or usable");
}
virtual bool is_virtual() const { return true; }
! virtual JVMState* generate(JVMState* jvms);
};
! JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
Node* receiver = kit.argument(0);
kit.C->print_inlining_update(this);
*** 281,291 ****
virtual bool is_late_inline() const { return true; }
// Convert the CallStaticJava into an inline
virtual void do_late_inline();
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->log_inline_id(this);
// Record that this call site should be revisited once the main
--- 281,291 ----
virtual bool is_late_inline() const { return true; }
// Convert the CallStaticJava into an inline
virtual void do_late_inline();
! virtual JVMState* generate(JVMState* jvms) {
Compile *C = Compile::current();
C->log_inline_id(this);
// Record that this call site should be revisited once the main
*** 296,306 ****
// Emit the CallStaticJava and request separate projections so
// that the late inlining logic can distinguish between fall
// through and exceptional uses of the memory and io projections
// as is done for allocations and macro expansion.
! return DirectCallGenerator::generate(jvms, parent_parser);
}
virtual void print_inlining_late(const char* msg) {
CallNode* call = call_node();
Compile* C = Compile::current();
--- 296,306 ----
// Emit the CallStaticJava and request separate projections so
// that the late inlining logic can distinguish between fall
// through and exceptional uses of the memory and io projections
// as is done for allocations and macro expansion.
! return DirectCallGenerator::generate(jvms);
}
virtual void print_inlining_late(const char* msg) {
CallNode* call = call_node();
Compile* C = Compile::current();
*** 397,407 ****
entry_nn->set_jvms(jvms);
C->set_default_node_notes(entry_nn);
}
// Now perform the inlining using the synthesized JVMState
! JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
if (new_jvms == NULL) return; // no change
if (C->failing()) return;
// Capture any exceptional control flow
GraphKit kit(new_jvms);
--- 397,407 ----
entry_nn->set_jvms(jvms);
C->set_default_node_notes(entry_nn);
}
// Now perform the inlining using the synthesized JVMState
! JVMState* new_jvms = _inline_cg->generate(jvms);
if (new_jvms == NULL) return; // no change
if (C->failing()) return;
// Capture any exceptional control flow
GraphKit kit(new_jvms);
*** 415,425 ****
C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
C->env()->notice_inlined_method(_inline_cg->method());
C->set_inlining_progress(true);
! kit.replace_call(call, result);
}
CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
return new LateInlineCallGenerator(method, inline_cg);
--- 415,425 ----
C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
C->env()->notice_inlined_method(_inline_cg->method());
C->set_inlining_progress(true);
! kit.replace_call(call, result, true);
}
CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
return new LateInlineCallGenerator(method, inline_cg);
*** 437,448 ****
LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) :
LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {}
virtual bool is_mh_late_inline() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
! JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
Compile* C = Compile::current();
if (_input_not_const) {
// inlining won't be possible so no need to enqueue right now.
call_node()->set_generator(this);
--- 437,448 ----
LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) :
LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {}
virtual bool is_mh_late_inline() const { return true; }
! virtual JVMState* generate(JVMState* jvms) {
! JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
Compile* C = Compile::current();
if (_input_not_const) {
// inlining won't be possible so no need to enqueue right now.
call_node()->set_generator(this);
*** 484,501 ****
public:
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->log_inline_id(this);
C->add_string_late_inline(this);
! JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
return new_jvms;
}
virtual bool is_string_late_inline() const { return true; }
};
--- 484,501 ----
public:
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
! virtual JVMState* generate(JVMState* jvms) {
Compile *C = Compile::current();
C->log_inline_id(this);
C->add_string_late_inline(this);
! JVMState* new_jvms = DirectCallGenerator::generate(jvms);
return new_jvms;
}
virtual bool is_string_late_inline() const { return true; }
};
*** 508,525 ****
public:
LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->log_inline_id(this);
C->add_boxing_late_inline(this);
! JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
return new_jvms;
}
};
CallGenerator* CallGenerator::for_boxing_late_inline(ciMethod* method, CallGenerator* inline_cg) {
--- 508,525 ----
public:
LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
! virtual JVMState* generate(JVMState* jvms) {
Compile *C = Compile::current();
C->log_inline_id(this);
C->add_boxing_late_inline(this);
! JVMState* new_jvms = DirectCallGenerator::generate(jvms);
return new_jvms;
}
};
CallGenerator* CallGenerator::for_boxing_late_inline(ciMethod* method, CallGenerator* inline_cg) {
*** 551,578 ****
virtual bool is_inline() const { return _is_inline; }
virtual bool is_virtual() const { return _is_virtual; }
virtual bool is_deferred() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
CallGenerator* if_cold,
CallGenerator* if_hot) {
return new WarmCallGenerator(ci, if_cold, if_hot);
}
! JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
Compile* C = Compile::current();
C->print_inlining_update(this);
if (C->log() != NULL) {
C->log()->elem("warm_call bci='%d'", jvms->bci());
}
! jvms = _if_cold->generate(jvms, parent_parser);
if (jvms != NULL) {
Node* m = jvms->map()->control();
if (m->is_CatchProj()) m = m->in(0); else m = C->top();
if (m->is_Catch()) m = m->in(0); else m = C->top();
if (m->is_Proj()) m = m->in(0); else m = C->top();
--- 551,578 ----
virtual bool is_inline() const { return _is_inline; }
virtual bool is_virtual() const { return _is_virtual; }
virtual bool is_deferred() const { return true; }
! virtual JVMState* generate(JVMState* jvms);
};
CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
CallGenerator* if_cold,
CallGenerator* if_hot) {
return new WarmCallGenerator(ci, if_cold, if_hot);
}
! JVMState* WarmCallGenerator::generate(JVMState* jvms) {
Compile* C = Compile::current();
C->print_inlining_update(this);
if (C->log() != NULL) {
C->log()->elem("warm_call bci='%d'", jvms->bci());
}
! jvms = _if_cold->generate(jvms);
if (jvms != NULL) {
Node* m = jvms->map()->control();
if (m->is_CatchProj()) m = m->in(0); else m = C->top();
if (m->is_Catch()) m = m->in(0); else m = C->top();
if (m->is_Proj()) m = m->in(0); else m = C->top();
*** 629,639 ****
virtual bool is_virtual() const { return true; }
virtual bool is_inline() const { return _if_hit->is_inline(); }
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
CallGenerator* if_missed,
--- 629,639 ----
virtual bool is_virtual() const { return true; }
virtual bool is_inline() const { return _if_hit->is_inline(); }
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
! virtual JVMState* generate(JVMState* jvms);
};
CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
CallGenerator* if_missed,
*** 641,658 ****
float hit_prob) {
return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob);
}
! JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
PhaseGVN& gvn = kit.gvn();
// We need an explicit receiver null_check before checking its type.
// We share a map with the caller, so his JVMS gets adjusted.
Node* receiver = kit.argument(0);
-
CompileLog* log = kit.C->log();
if (log != NULL) {
log->elem("predicted_call bci='%d' klass='%d'",
jvms->bci(), log->identify(_predicted_receiver));
}
--- 641,657 ----
float hit_prob) {
return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob);
}
! JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
PhaseGVN& gvn = kit.gvn();
// We need an explicit receiver null_check before checking its type.
// We share a map with the caller, so his JVMS gets adjusted.
Node* receiver = kit.argument(0);
CompileLog* log = kit.C->log();
if (log != NULL) {
log->elem("predicted_call bci='%d' klass='%d'",
jvms->bci(), log->identify(_predicted_receiver));
}
*** 660,680 ****
receiver = kit.null_check_receiver_before_call(method());
if (kit.stopped()) {
return kit.transfer_exceptions_into_jvms();
}
Node* exact_receiver = receiver; // will get updated in place...
Node* slow_ctl = kit.type_check_receiver(receiver,
_predicted_receiver, _hit_prob,
&exact_receiver);
SafePointNode* slow_map = NULL;
JVMState* slow_jvms;
{ PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
! slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser);
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
kit.add_exception_states_from(slow_jvms);
kit.set_map(slow_jvms->map());
--- 659,683 ----
receiver = kit.null_check_receiver_before_call(method());
if (kit.stopped()) {
return kit.transfer_exceptions_into_jvms();
}
+ // Make a copy of the replaced nodes in case we need to restore them
+ ReplacedNodes r = kit.map()->_replaced_nodes;
+ r.clone();
+
Node* exact_receiver = receiver; // will get updated in place...
Node* slow_ctl = kit.type_check_receiver(receiver,
_predicted_receiver, _hit_prob,
&exact_receiver);
SafePointNode* slow_map = NULL;
JVMState* slow_jvms;
{ PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
! slow_jvms = _if_missed->generate(kit.sync_jvms());
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
kit.add_exception_states_from(slow_jvms);
kit.set_map(slow_jvms->map());
*** 691,706 ****
// fall through if the instance exactly matches the desired type
kit.replace_in_map(receiver, exact_receiver);
// Make the hot call:
! JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser);
if (new_jvms == NULL) {
// Inline failed, so make a direct call.
assert(_if_hit->is_inline(), "must have been a failed inline");
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
! new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
}
kit.add_exception_states_from(new_jvms);
kit.set_jvms(new_jvms);
// Need to merge slow and fast?
--- 694,709 ----
// fall through if the instance exactly matches the desired type
kit.replace_in_map(receiver, exact_receiver);
// Make the hot call:
! JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
if (new_jvms == NULL) {
// Inline failed, so make a direct call.
assert(_if_hit->is_inline(), "must have been a failed inline");
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
! new_jvms = cg->generate(kit.sync_jvms());
}
kit.add_exception_states_from(new_jvms);
kit.set_jvms(new_jvms);
// Need to merge slow and fast?
*** 713,722 ****
--- 716,730 ----
// Inlined method threw an exception, so it's just the slow path after all.
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
+ // There are 2 branches and the replaced nodes are only valid on
+ // one: restore the replaced nodes to what they were before the
+ // branch.
+ kit.map()->_replaced_nodes = r;
+
// Finish the diamond.
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
RegionNode* region = new (kit.C) RegionNode(3);
region->init_req(1, kit.control());
region->init_req(2, slow_map->control());
*** 899,919 ****
virtual bool is_virtual() const { return true; }
virtual bool is_inlined() const { return true; }
virtual bool is_intrinsic() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic,
CallGenerator* cg) {
return new PredictedIntrinsicGenerator(intrinsic, cg);
}
! JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
CompileLog* log = kit.C->log();
if (log != NULL) {
--- 907,927 ----
virtual bool is_virtual() const { return true; }
virtual bool is_inlined() const { return true; }
virtual bool is_intrinsic() const { return true; }
! virtual JVMState* generate(JVMState* jvms);
};
CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic,
CallGenerator* cg) {
return new PredictedIntrinsicGenerator(intrinsic, cg);
}
! JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
CompileLog* log = kit.C->log();
if (log != NULL) {
*** 930,940 ****
JVMState* slow_jvms;
if (slow_ctl != NULL) {
PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
! slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
kit.add_exception_states_from(slow_jvms);
kit.set_map(slow_jvms->map());
--- 938,948 ----
JVMState* slow_jvms;
if (slow_ctl != NULL) {
PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
! slow_jvms = _cg->generate(kit.sync_jvms());
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
kit.add_exception_states_from(slow_jvms);
kit.set_map(slow_jvms->map());
*** 948,963 ****
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
// Generate intrinsic code:
! JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
if (new_jvms == NULL) {
// Intrinsic failed, so use slow code or make a direct call.
if (slow_map == NULL) {
CallGenerator* cg = CallGenerator::for_direct_call(method());
! new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
} else {
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
}
--- 956,971 ----
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
// Generate intrinsic code:
! JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
if (new_jvms == NULL) {
// Intrinsic failed, so use slow code or make a direct call.
if (slow_map == NULL) {
CallGenerator* cg = CallGenerator::for_direct_call(method());
! new_jvms = cg->generate(kit.sync_jvms());
} else {
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
}
}
*** 1023,1033 ****
}
virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
virtual bool is_trap() const { return true; }
! virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
CallGenerator*
CallGenerator::for_uncommon_trap(ciMethod* m,
--- 1031,1041 ----
}
virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
virtual bool is_trap() const { return true; }
! virtual JVMState* generate(JVMState* jvms);
};
CallGenerator*
CallGenerator::for_uncommon_trap(ciMethod* m,
*** 1035,1045 ****
Deoptimization::DeoptAction action) {
return new UncommonTrapCallGenerator(m, reason, action);
}
! JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
// Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
int nargs = method()->arg_size();
kit.inc_sp(nargs);
--- 1043,1053 ----
Deoptimization::DeoptAction action) {
return new UncommonTrapCallGenerator(m, reason, action);
}
! JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
kit.C->print_inlining_update(this);
// Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
int nargs = method()->arg_size();
kit.inc_sp(nargs);
src/share/vm/opto/callGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File