src/share/vm/opto/callGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/callGenerator.cpp Wed Oct 28 20:02:34 2009
--- new/src/share/vm/opto/callGenerator.cpp Wed Oct 28 20:02:34 2009
*** 136,146 ****
--- 136,146 ----
kit.push_node(method()->return_type()->basic_type(), ret);
return kit.transfer_exceptions_into_jvms();
}
//---------------------------DynamicCallGenerator-----------------------------
! // Internal class which handles all out-of-line invokedynamic calls.
class DynamicCallGenerator : public CallGenerator {
public:
DynamicCallGenerator(ciMethod* method)
: CallGenerator(method)
{
*** 167,195 ****
--- 167,195 ----
int index = str.get_method_index();
size_t call_site_offset = cpcache->get_f1_offset(index);
// Load the CallSite object from the constant pool cache.
const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
! Node* cpcache_adr = kit.makecon(cpcache_ptr);
! Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset);
! Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
! Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
! Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
! // Load the MethodHandle (target) from the CallSite object.
! Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
! Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
! // Load the target MethodHandle from the CallSite object.
! Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
! Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
! address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
! CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci());
// invokedynamic is treated as an optimized invokevirtual.
call->set_optimized_virtual(true);
// Take extra care (in the presence of argument motion) not to trash the SP:
call->set_method_handle_invoke(true);
! // Pass the MethodHandle as first argument and shift the other
! // arguments.
! call->init_req(0 + TypeFunc::Parms, mh);
! // Pass the target MethodHandle as first argument and shift the
! // other arguments.
! call->init_req(0 + TypeFunc::Parms, target_mh);
uint nargs = call->method()->arg_size();
for (uint i = 1; i < nargs; i++) {
Node* arg = kit.argument(i - 1);
call->init_req(i + TypeFunc::Parms, arg);
}
*** 596,605 ****
--- 596,754 ----
}
return kit.transfer_exceptions_into_jvms();
}
+ //------------------------PredictedDynamicCallGenerator-----------------------
+ // Internal class which handles all out-of-line calls checking receiver type.
+ class PredictedDynamicCallGenerator : public CallGenerator {
+ ciMethodHandle* _predicted_method_handle;
+ CallGenerator* _if_missed;
+ CallGenerator* _if_hit;
+ float _hit_prob;
+
+ public:
+ PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
+ CallGenerator* if_missed,
+ CallGenerator* if_hit,
+ float hit_prob)
+ : CallGenerator(if_missed->method()),
+ _predicted_method_handle(predicted_method_handle),
+ _if_missed(if_missed),
+ _if_hit(if_hit),
+ _hit_prob(hit_prob)
+ {}
+
+ 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_dynamic_call(ciMethodHandle* predicted_method_handle,
+ CallGenerator* if_missed,
+ CallGenerator* if_hit,
+ float hit_prob) {
+ return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
+ }
+
+
+ JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
+ GraphKit kit(jvms);
+ PhaseGVN& gvn = kit.gvn();
+
+ CompileLog* log = kit.C->log();
+ if (log != NULL) {
+ log->elem("predicted_dynamic_call bci='%d'", jvms->bci());
+ }
+
+ // Get the constant pool cache from the caller class.
+ ciMethod* caller_method = jvms->method();
+ ciBytecodeStream str(caller_method);
+ str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
+ ciCPCache* cpcache = str.get_cpcache();
+
+ // Get the offset of the CallSite from the constant pool cache
+ // pointer.
+ int index = str.get_method_index();
+ size_t call_site_offset = cpcache->get_f1_offset(index);
+
+ // Load the CallSite object from the constant pool cache.
+ const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
+ Node* cpcache_adr = kit.makecon(cpcache_ptr);
+ Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
+ Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
+
+ // Load the target MethodHandle from the CallSite object.
+ Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
+ Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
+
+ // Check if the MethodHandle is still the same.
+ const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true);
+ Node* predicted_mh = kit.makecon(predicted_mh_ptr);
+
+ Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
+ Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
+ IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
+ kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
+ Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
+
+ 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());
+ assert(slow_jvms != NULL, "miss path must not fail to generate");
+ kit.add_exception_states_from(slow_jvms);
+ kit.set_map(slow_jvms->map());
+ if (!kit.stopped())
+ slow_map = kit.stop();
+ }
+ }
+
+ if (kit.stopped()) {
+ // Instance exactly does not matches the desired type.
+ kit.set_jvms(slow_jvms);
+ return kit.transfer_exceptions_into_jvms();
+ }
+
+ // 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?
+ if (slow_map == NULL) {
+ // The fast path is the only path remaining.
+ return kit.transfer_exceptions_into_jvms();
+ }
+
+ if (kit.stopped()) {
+ // 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();
+ }
+
+ // Finish the diamond.
+ kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
+ RegionNode* region = new (kit.C, 3) RegionNode(3);
+ region->init_req(1, kit.control());
+ region->init_req(2, slow_map->control());
+ kit.set_control(gvn.transform(region));
+ Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
+ iophi->set_req(2, slow_map->i_o());
+ kit.set_i_o(gvn.transform(iophi));
+ kit.merge_memory(slow_map->merged_memory(), region, 2);
+ uint tos = kit.jvms()->stkoff() + kit.sp();
+ uint limit = slow_map->req();
+ for (uint i = TypeFunc::Parms; i < limit; i++) {
+ // Skip unused stack slots; fast forward to monoff();
+ if (i == tos) {
+ i = kit.jvms()->monoff();
+ if( i >= limit ) break;
+ }
+ Node* m = kit.map()->in(i);
+ Node* n = slow_map->in(i);
+ if (m != n) {
+ const Type* t = gvn.type(m)->meet(gvn.type(n));
+ Node* phi = PhiNode::make(region, m, t);
+ phi->set_req(2, n);
+ kit.map()->set_req(i, gvn.transform(phi));
+ }
+ }
+ return kit.transfer_exceptions_into_jvms();
+ }
+
+
//-------------------------UncommonTrapCallGenerator-----------------------------
// Internal class which handles all out-of-line calls checking receiver type.
class UncommonTrapCallGenerator : public CallGenerator {
Deoptimization::DeoptReason _reason;
Deoptimization::DeoptAction _action;
src/share/vm/opto/callGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File