src/hotspot/share/opto/callGenerator.cpp
changeset 53633 eebdde444bb5
parent 53595 8462b295c08b
child 55635 0fb70c9118ce
equal deleted inserted replaced
53632:d620a4a1d5ed 53633:eebdde444bb5
   294 }
   294 }
   295 
   295 
   296 // Allow inlining decisions to be delayed
   296 // Allow inlining decisions to be delayed
   297 class LateInlineCallGenerator : public DirectCallGenerator {
   297 class LateInlineCallGenerator : public DirectCallGenerator {
   298  private:
   298  private:
   299   // unique id for log compilation
   299   jlong _unique_id;   // unique id for log compilation
   300   jlong _unique_id;
   300   bool _is_pure_call; // a hint that the call doesn't have important side effects to care about
   301 
   301 
   302  protected:
   302  protected:
   303   CallGenerator* _inline_cg;
   303   CallGenerator* _inline_cg;
   304   virtual bool do_late_inline_check(JVMState* jvms) { return true; }
   304   virtual bool do_late_inline_check(JVMState* jvms) { return true; }
   305 
   305 
   306  public:
   306  public:
   307   LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
   307   LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg, bool is_pure_call = false) :
   308     DirectCallGenerator(method, true), _unique_id(0), _inline_cg(inline_cg) {}
   308     DirectCallGenerator(method, true), _unique_id(0), _is_pure_call(is_pure_call), _inline_cg(inline_cg) {}
   309 
   309 
   310   virtual bool is_late_inline() const { return true; }
   310   virtual bool is_late_inline() const { return true; }
   311 
   311 
   312   // Convert the CallStaticJava into an inline
   312   // Convert the CallStaticJava into an inline
   313   virtual void do_late_inline();
   313   virtual void do_late_inline();
   387   // Remove inlined methods from Compiler's lists.
   387   // Remove inlined methods from Compiler's lists.
   388   if (call->is_macro()) {
   388   if (call->is_macro()) {
   389     C->remove_macro_node(call);
   389     C->remove_macro_node(call);
   390   }
   390   }
   391 
   391 
   392   // Make a clone of the JVMState that appropriate to use for driving a parse
   392   bool result_not_used = (callprojs.resproj == NULL || callprojs.resproj->outcnt() == 0);
   393   JVMState* old_jvms = call->jvms();
   393   if (_is_pure_call && result_not_used) {
   394   JVMState* jvms = old_jvms->clone_shallow(C);
   394     // The call is marked as pure (no important side effects), but result isn't used.
   395   uint size = call->req();
   395     // It's safe to remove the call.
   396   SafePointNode* map = new SafePointNode(size, jvms);
   396     GraphKit kit(call->jvms());
   397   for (uint i1 = 0; i1 < size; i1++) {
   397     kit.replace_call(call, C->top(), true);
   398     map->init_req(i1, call->in(i1));
   398   } else {
   399   }
   399     // Make a clone of the JVMState that appropriate to use for driving a parse
   400 
   400     JVMState* old_jvms = call->jvms();
   401   // Make sure the state is a MergeMem for parsing.
   401     JVMState* jvms = old_jvms->clone_shallow(C);
   402   if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
   402     uint size = call->req();
   403     Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory));
   403     SafePointNode* map = new SafePointNode(size, jvms);
   404     C->initial_gvn()->set_type_bottom(mem);
   404     for (uint i1 = 0; i1 < size; i1++) {
   405     map->set_req(TypeFunc::Memory, mem);
   405       map->init_req(i1, call->in(i1));
   406   }
   406     }
   407 
   407 
   408   uint nargs = method()->arg_size();
   408     // Make sure the state is a MergeMem for parsing.
   409   // blow away old call arguments
   409     if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
   410   Node* top = C->top();
   410       Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory));
   411   for (uint i1 = 0; i1 < nargs; i1++) {
   411       C->initial_gvn()->set_type_bottom(mem);
   412     map->set_req(TypeFunc::Parms + i1, top);
   412       map->set_req(TypeFunc::Memory, mem);
   413   }
   413     }
   414   jvms->set_map(map);
   414 
   415 
   415     uint nargs = method()->arg_size();
   416   // Make enough space in the expression stack to transfer
   416     // blow away old call arguments
   417   // the incoming arguments and return value.
   417     Node* top = C->top();
   418   map->ensure_stack(jvms, jvms->method()->max_stack());
   418     for (uint i1 = 0; i1 < nargs; i1++) {
   419   for (uint i1 = 0; i1 < nargs; i1++) {
   419       map->set_req(TypeFunc::Parms + i1, top);
   420     map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1));
   420     }
   421   }
   421     jvms->set_map(map);
   422 
   422 
   423   C->print_inlining_assert_ready();
   423     // Make enough space in the expression stack to transfer
   424 
   424     // the incoming arguments and return value.
   425   C->print_inlining_move_to(this);
   425     map->ensure_stack(jvms, jvms->method()->max_stack());
   426 
   426     for (uint i1 = 0; i1 < nargs; i1++) {
   427   C->log_late_inline(this);
   427       map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1));
   428 
   428     }
   429   // This check is done here because for_method_handle_inline() method
   429 
   430   // needs jvms for inlined state.
   430     C->print_inlining_assert_ready();
   431   if (!do_late_inline_check(jvms)) {
   431 
   432     map->disconnect_inputs(NULL, C);
   432     C->print_inlining_move_to(this);
   433     return;
   433 
   434   }
   434     C->log_late_inline(this);
   435 
   435 
   436   // Setup default node notes to be picked up by the inlining
   436     // This check is done here because for_method_handle_inline() method
   437   Node_Notes* old_nn = C->node_notes_at(call->_idx);
   437     // needs jvms for inlined state.
   438   if (old_nn != NULL) {
   438     if (!do_late_inline_check(jvms)) {
   439     Node_Notes* entry_nn = old_nn->clone(C);
   439       map->disconnect_inputs(NULL, C);
   440     entry_nn->set_jvms(jvms);
   440       return;
   441     C->set_default_node_notes(entry_nn);
   441     }
   442   }
   442 
   443 
   443     // Setup default node notes to be picked up by the inlining
   444   // Now perform the inlining using the synthesized JVMState
   444     Node_Notes* old_nn = C->node_notes_at(call->_idx);
   445   JVMState* new_jvms = _inline_cg->generate(jvms);
   445     if (old_nn != NULL) {
   446   if (new_jvms == NULL)  return;  // no change
   446       Node_Notes* entry_nn = old_nn->clone(C);
   447   if (C->failing())      return;
   447       entry_nn->set_jvms(jvms);
   448 
   448       C->set_default_node_notes(entry_nn);
   449   // Capture any exceptional control flow
   449     }
   450   GraphKit kit(new_jvms);
   450 
   451 
   451     // Now perform the inlining using the synthesized JVMState
   452   // Find the result object
   452     JVMState* new_jvms = _inline_cg->generate(jvms);
   453   Node* result = C->top();
   453     if (new_jvms == NULL)  return;  // no change
   454   int   result_size = method()->return_type()->size();
   454     if (C->failing())      return;
   455   if (result_size != 0 && !kit.stopped()) {
   455 
   456     result = (result_size == 1) ? kit.pop() : kit.pop_pair();
   456     // Capture any exceptional control flow
   457   }
   457     GraphKit kit(new_jvms);
   458 
   458 
   459   C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
   459     // Find the result object
   460   C->env()->notice_inlined_method(_inline_cg->method());
   460     Node* result = C->top();
   461   C->set_inlining_progress(true);
   461     int   result_size = method()->return_type()->size();
   462   C->set_do_cleanup(kit.stopped()); // path is dead; needs cleanup
   462     if (result_size != 0 && !kit.stopped()) {
   463   kit.replace_call(call, result, true);
   463       result = (result_size == 1) ? kit.pop() : kit.pop_pair();
       
   464     }
       
   465 
       
   466     C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
       
   467     C->env()->notice_inlined_method(_inline_cg->method());
       
   468     C->set_inlining_progress(true);
       
   469     C->set_do_cleanup(kit.stopped()); // path is dead; needs cleanup
       
   470     kit.replace_call(call, result, true);
       
   471   }
   464 }
   472 }
   465 
   473 
   466 
   474 
   467 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
   475 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
   468   return new LateInlineCallGenerator(method, inline_cg);
   476   return new LateInlineCallGenerator(method, inline_cg);
   549 
   557 
   550 class LateInlineBoxingCallGenerator : public LateInlineCallGenerator {
   558 class LateInlineBoxingCallGenerator : public LateInlineCallGenerator {
   551 
   559 
   552  public:
   560  public:
   553   LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
   561   LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
   554     LateInlineCallGenerator(method, inline_cg) {}
   562     LateInlineCallGenerator(method, inline_cg, /*is_pure=*/true) {}
   555 
   563 
   556   virtual JVMState* generate(JVMState* jvms) {
   564   virtual JVMState* generate(JVMState* jvms) {
   557     Compile *C = Compile::current();
   565     Compile *C = Compile::current();
   558 
   566 
   559     C->log_inline_id(this);
   567     C->log_inline_id(this);