src/share/vm/opto/callGenerator.cpp

changeset 4409
d092d1b31229
parent 4357
ad5dd04754ee
child 4414
5698813d45eb
     1.1 --- a/src/share/vm/opto/callGenerator.cpp	Fri Dec 21 10:27:49 2012 -0800
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Sun Dec 23 17:08:22 2012 +0100
     1.3 @@ -262,8 +262,11 @@
     1.4  
     1.5  // Allow inlining decisions to be delayed
     1.6  class LateInlineCallGenerator : public DirectCallGenerator {
     1.7 + protected:
     1.8    CallGenerator* _inline_cg;
     1.9  
    1.10 +  virtual bool do_late_inline_check(JVMState* jvms) { return true; }
    1.11 +
    1.12   public:
    1.13    LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
    1.14      DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
    1.15 @@ -279,7 +282,9 @@
    1.16  
    1.17      // Record that this call site should be revisited once the main
    1.18      // parse is finished.
    1.19 -    Compile::current()->add_late_inline(this);
    1.20 +    if (!is_mh_late_inline()) {
    1.21 +      C->add_late_inline(this);
    1.22 +    }
    1.23  
    1.24      // Emit the CallStaticJava and request separate projections so
    1.25      // that the late inlining logic can distinguish between fall
    1.26 @@ -287,15 +292,34 @@
    1.27      // as is done for allocations and macro expansion.
    1.28      return DirectCallGenerator::generate(jvms);
    1.29    }
    1.30 +
    1.31 +  virtual void print_inlining_late(const char* msg) {
    1.32 +    CallNode* call = call_node();
    1.33 +    Compile* C = Compile::current();
    1.34 +    C->print_inlining_insert(this);
    1.35 +    C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg);
    1.36 +  }
    1.37 +
    1.38  };
    1.39  
    1.40 -
    1.41  void LateInlineCallGenerator::do_late_inline() {
    1.42    // Can't inline it
    1.43    if (call_node() == NULL || call_node()->outcnt() == 0 ||
    1.44        call_node()->in(0) == NULL || call_node()->in(0)->is_top())
    1.45      return;
    1.46  
    1.47 +  for (int i1 = 0; i1 < method()->arg_size(); i1++) {
    1.48 +    if (call_node()->in(TypeFunc::Parms + i1)->is_top()) {
    1.49 +      assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
    1.50 +      return;
    1.51 +    }
    1.52 +  }
    1.53 +
    1.54 +  if (call_node()->in(TypeFunc::Memory)->is_top()) {
    1.55 +    assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
    1.56 +    return;
    1.57 +  }
    1.58 +
    1.59    CallStaticJavaNode* call = call_node();
    1.60  
    1.61    // Make a clone of the JVMState that appropriate to use for driving a parse
    1.62 @@ -324,6 +348,11 @@
    1.63      }
    1.64    }
    1.65  
    1.66 +  if (!do_late_inline_check(jvms)) {
    1.67 +    map->disconnect_inputs(NULL, C);
    1.68 +    return;
    1.69 +  }
    1.70 +
    1.71    C->print_inlining_insert(this);
    1.72  
    1.73    CompileLog* log = C->log();
    1.74 @@ -360,6 +389,10 @@
    1.75      result = (result_size == 1) ? kit.pop() : kit.pop_pair();
    1.76    }
    1.77  
    1.78 +  C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
    1.79 +  C->env()->notice_inlined_method(_inline_cg->method());
    1.80 +  C->set_inlining_progress(true);
    1.81 +
    1.82    kit.replace_call(call, result);
    1.83  }
    1.84  
    1.85 @@ -368,6 +401,83 @@
    1.86    return new LateInlineCallGenerator(method, inline_cg);
    1.87  }
    1.88  
    1.89 +class LateInlineMHCallGenerator : public LateInlineCallGenerator {
    1.90 +  ciMethod* _caller;
    1.91 +  int _attempt;
    1.92 +  bool _input_not_const;
    1.93 +
    1.94 +  virtual bool do_late_inline_check(JVMState* jvms);
    1.95 +  virtual bool already_attempted() const { return _attempt > 0; }
    1.96 +
    1.97 + public:
    1.98 +  LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) :
    1.99 +    LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {}
   1.100 +
   1.101 +  virtual bool is_mh_late_inline() const { return true; }
   1.102 +
   1.103 +  virtual JVMState* generate(JVMState* jvms) {
   1.104 +    JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
   1.105 +    if (_input_not_const) {
   1.106 +      // inlining won't be possible so no need to enqueue right now.
   1.107 +      call_node()->set_generator(this);
   1.108 +    } else {
   1.109 +      Compile::current()->add_late_inline(this);
   1.110 +    }
   1.111 +    return new_jvms;
   1.112 +  }
   1.113 +
   1.114 +  virtual void print_inlining_late(const char* msg) {
   1.115 +    if (!_input_not_const) return;
   1.116 +    LateInlineCallGenerator::print_inlining_late(msg);
   1.117 +  }
   1.118 +};
   1.119 +
   1.120 +bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) {
   1.121 +
   1.122 +  CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const);
   1.123 +
   1.124 +  if (!_input_not_const) {
   1.125 +    _attempt++;
   1.126 +  }
   1.127 +
   1.128 +  if (cg != NULL) {
   1.129 +    assert(!cg->is_late_inline() && cg->is_inline(), "we're doing late inlining");
   1.130 +    _inline_cg = cg;
   1.131 +    Compile::current()->dec_number_of_mh_late_inlines();
   1.132 +    return true;
   1.133 +  }
   1.134 +
   1.135 +  call_node()->set_generator(this);
   1.136 +  return false;
   1.137 +}
   1.138 +
   1.139 +CallGenerator* CallGenerator::for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const) {
   1.140 +  Compile::current()->inc_number_of_mh_late_inlines();
   1.141 +  CallGenerator* cg = new LateInlineMHCallGenerator(caller, callee, input_not_const);
   1.142 +  return cg;
   1.143 +}
   1.144 +
   1.145 +class LateInlineStringCallGenerator : public LateInlineCallGenerator {
   1.146 +
   1.147 + public:
   1.148 +  LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
   1.149 +    LateInlineCallGenerator(method, inline_cg) {}
   1.150 +
   1.151 +  virtual JVMState* generate(JVMState* jvms) {
   1.152 +    Compile *C = Compile::current();
   1.153 +    C->print_inlining_skip(this);
   1.154 +
   1.155 +    C->add_string_late_inline(this);
   1.156 +
   1.157 +    JVMState* new_jvms =  DirectCallGenerator::generate(jvms);
   1.158 +    return new_jvms;
   1.159 +  }
   1.160 +};
   1.161 +
   1.162 +CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) {
   1.163 +  return new LateInlineStringCallGenerator(method, inline_cg);
   1.164 +}
   1.165 +
   1.166  
   1.167  //---------------------------WarmCallGenerator--------------------------------
   1.168  // Internal class which handles initial deferral of inlining decisions.
   1.169 @@ -586,35 +696,52 @@
   1.170  }
   1.171  
   1.172  
   1.173 -CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
   1.174 +CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden) {
   1.175    assert(callee->is_method_handle_intrinsic() ||
   1.176           callee->is_compiled_lambda_form(), "for_method_handle_call mismatch");
   1.177 -  CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee);
   1.178 -  if (cg != NULL)
   1.179 -    return cg;
   1.180 -  return CallGenerator::for_direct_call(callee);
   1.181 +  bool input_not_const;
   1.182 +  CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee, input_not_const);
   1.183 +  Compile* C = Compile::current();
   1.184 +  if (cg != NULL) {
   1.185 +    if (!delayed_forbidden && AlwaysIncrementalInline) {
   1.186 +      return CallGenerator::for_late_inline(callee, cg);
   1.187 +    } else {
   1.188 +      return cg;
   1.189 +    }
   1.190 +  }
   1.191 +  int bci = jvms->bci();
   1.192 +  ciCallProfile profile = caller->call_profile_at_bci(bci);
   1.193 +  int call_site_count = caller->scale_count(profile.count());
   1.194 +
   1.195 +  if (IncrementalInline && call_site_count > 0 &&
   1.196 +      (input_not_const || !C->inlining_incrementally() || C->over_inlining_cutoff())) {
   1.197 +    return CallGenerator::for_mh_late_inline(caller, callee, input_not_const);
   1.198 +  } else {
   1.199 +    return CallGenerator::for_direct_call(callee);
   1.200 +  }
   1.201  }
   1.202  
   1.203 -CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
   1.204 +CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) {
   1.205    GraphKit kit(jvms);
   1.206    PhaseGVN& gvn = kit.gvn();
   1.207    Compile* C = kit.C;
   1.208    vmIntrinsics::ID iid = callee->intrinsic_id();
   1.209 +  input_not_const = true;
   1.210    switch (iid) {
   1.211    case vmIntrinsics::_invokeBasic:
   1.212      {
   1.213        // Get MethodHandle receiver:
   1.214        Node* receiver = kit.argument(0);
   1.215        if (receiver->Opcode() == Op_ConP) {
   1.216 +        input_not_const = false;
   1.217          const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
   1.218          ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
   1.219          guarantee(!target->is_method_handle_intrinsic(), "should not happen");  // XXX remove
   1.220          const int vtable_index = Method::invalid_vtable_index;
   1.221 -        CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS);
   1.222 +        CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, true, true);
   1.223 +        assert (!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
   1.224          if (cg != NULL && cg->is_inline())
   1.225            return cg;
   1.226 -      } else {
   1.227 -        if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant");
   1.228        }
   1.229      }
   1.230      break;
   1.231 @@ -627,6 +754,7 @@
   1.232        // Get MemberName argument:
   1.233        Node* member_name = kit.argument(callee->arg_size() - 1);
   1.234        if (member_name->Opcode() == Op_ConP) {
   1.235 +        input_not_const = false;
   1.236          const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr();
   1.237          ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget();
   1.238  
   1.239 @@ -661,7 +789,8 @@
   1.240          }
   1.241          const int vtable_index = Method::invalid_vtable_index;
   1.242          const bool call_is_virtual = target->is_abstract();  // FIXME workaround
   1.243 -        CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS);
   1.244 +        CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS, true, true);
   1.245 +        assert (!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
   1.246          if (cg != NULL && cg->is_inline())
   1.247            return cg;
   1.248        }

mercurial