src/share/vm/opto/callGenerator.cpp

changeset 1515
7c57aead6d3e
parent 772
9ee9cf798b59
child 1572
97125851f396
     1.1 --- a/src/share/vm/opto/callGenerator.cpp	Fri Nov 27 07:56:58 2009 -0800
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Thu Nov 12 09:24:21 2009 -0800
     1.3 @@ -98,12 +98,21 @@
     1.4  //---------------------------DirectCallGenerator------------------------------
     1.5  // Internal class which handles all out-of-line calls w/o receiver type checks.
     1.6  class DirectCallGenerator : public CallGenerator {
     1.7 -public:
     1.8 -  DirectCallGenerator(ciMethod* method)
     1.9 -    : CallGenerator(method)
    1.10 + private:
    1.11 +  CallStaticJavaNode* _call_node;
    1.12 +  // Force separate memory and I/O projections for the exceptional
    1.13 +  // paths to facilitate late inlinig.
    1.14 +  bool                _separate_io_proj;
    1.15 +
    1.16 + public:
    1.17 +  DirectCallGenerator(ciMethod* method, bool separate_io_proj)
    1.18 +    : CallGenerator(method),
    1.19 +      _separate_io_proj(separate_io_proj)
    1.20    {
    1.21    }
    1.22    virtual JVMState* generate(JVMState* jvms);
    1.23 +
    1.24 +  CallStaticJavaNode* call_node() const { return _call_node; }
    1.25  };
    1.26  
    1.27  JVMState* DirectCallGenerator::generate(JVMState* jvms) {
    1.28 @@ -129,9 +138,10 @@
    1.29      call->set_optimized_virtual(true);
    1.30    }
    1.31    kit.set_arguments_for_java_call(call);
    1.32 -  kit.set_edges_for_java_call(call);
    1.33 -  Node* ret = kit.set_results_for_java_call(call);
    1.34 +  kit.set_edges_for_java_call(call, false, _separate_io_proj);
    1.35 +  Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
    1.36    kit.push_node(method()->return_type()->basic_type(), ret);
    1.37 +  _call_node = call;  // Save the call node in case we need it later
    1.38    return kit.transfer_exceptions_into_jvms();
    1.39  }
    1.40  
    1.41 @@ -238,9 +248,9 @@
    1.42    return new ParseGenerator(m, expected_uses, true);
    1.43  }
    1.44  
    1.45 -CallGenerator* CallGenerator::for_direct_call(ciMethod* m) {
    1.46 +CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
    1.47    assert(!m->is_abstract(), "for_direct_call mismatch");
    1.48 -  return new DirectCallGenerator(m);
    1.49 +  return new DirectCallGenerator(m, separate_io_proj);
    1.50  }
    1.51  
    1.52  CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
    1.53 @@ -248,6 +258,108 @@
    1.54    return new VirtualCallGenerator(m, vtable_index);
    1.55  }
    1.56  
    1.57 +// Allow inlining decisions to be delayed
    1.58 +class LateInlineCallGenerator : public DirectCallGenerator {
    1.59 +  CallGenerator* _inline_cg;
    1.60 +
    1.61 + public:
    1.62 +  LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
    1.63 +    DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
    1.64 +
    1.65 +  virtual bool      is_late_inline() const { return true; }
    1.66 +
    1.67 +  // Convert the CallStaticJava into an inline
    1.68 +  virtual void do_late_inline();
    1.69 +
    1.70 +  JVMState* generate(JVMState* jvms) {
    1.71 +    // Record that this call site should be revisited once the main
    1.72 +    // parse is finished.
    1.73 +    Compile::current()->add_late_inline(this);
    1.74 +
    1.75 +    // Emit the CallStaticJava and request separate projections so
    1.76 +    // that the late inlining logic can distinguish between fall
    1.77 +    // through and exceptional uses of the memory and io projections
    1.78 +    // as is done for allocations and macro expansion.
    1.79 +    return DirectCallGenerator::generate(jvms);
    1.80 +  }
    1.81 +
    1.82 +};
    1.83 +
    1.84 +
    1.85 +void LateInlineCallGenerator::do_late_inline() {
    1.86 +  // Can't inline it
    1.87 +  if (call_node() == NULL || call_node()->outcnt() == 0 ||
    1.88 +      call_node()->in(0) == NULL || call_node()->in(0)->is_top())
    1.89 +    return;
    1.90 +
    1.91 +  CallStaticJavaNode* call = call_node();
    1.92 +
    1.93 +  // Make a clone of the JVMState that appropriate to use for driving a parse
    1.94 +  Compile* C = Compile::current();
    1.95 +  JVMState* jvms     = call->jvms()->clone_shallow(C);
    1.96 +  uint size = call->req();
    1.97 +  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
    1.98 +  for (uint i1 = 0; i1 < size; i1++) {
    1.99 +    map->init_req(i1, call->in(i1));
   1.100 +  }
   1.101 +
   1.102 +  // Make sure the state is a MergeMem for parsing.
   1.103 +  if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
   1.104 +    map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory)));
   1.105 +  }
   1.106 +
   1.107 +  // Make enough space for the expression stack and transfer the incoming arguments
   1.108 +  int nargs    = method()->arg_size();
   1.109 +  jvms->set_map(map);
   1.110 +  map->ensure_stack(jvms, jvms->method()->max_stack());
   1.111 +  if (nargs > 0) {
   1.112 +    for (int i1 = 0; i1 < nargs; i1++) {
   1.113 +      map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1));
   1.114 +    }
   1.115 +  }
   1.116 +
   1.117 +  CompileLog* log = C->log();
   1.118 +  if (log != NULL) {
   1.119 +    log->head("late_inline method='%d'", log->identify(method()));
   1.120 +    JVMState* p = jvms;
   1.121 +    while (p != NULL) {
   1.122 +      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
   1.123 +      p = p->caller();
   1.124 +    }
   1.125 +    log->tail("late_inline");
   1.126 +  }
   1.127 +
   1.128 +  // Setup default node notes to be picked up by the inlining
   1.129 +  Node_Notes* old_nn = C->default_node_notes();
   1.130 +  if (old_nn != NULL) {
   1.131 +    Node_Notes* entry_nn = old_nn->clone(C);
   1.132 +    entry_nn->set_jvms(jvms);
   1.133 +    C->set_default_node_notes(entry_nn);
   1.134 +  }
   1.135 +
   1.136 +  // Now perform the inling using the synthesized JVMState
   1.137 +  JVMState* new_jvms = _inline_cg->generate(jvms);
   1.138 +  if (new_jvms == NULL)  return;  // no change
   1.139 +  if (C->failing())      return;
   1.140 +
   1.141 +  // Capture any exceptional control flow
   1.142 +  GraphKit kit(new_jvms);
   1.143 +
   1.144 +  // Find the result object
   1.145 +  Node* result = C->top();
   1.146 +  int   result_size = method()->return_type()->size();
   1.147 +  if (result_size != 0 && !kit.stopped()) {
   1.148 +    result = (result_size == 1) ? kit.pop() : kit.pop_pair();
   1.149 +  }
   1.150 +
   1.151 +  kit.replace_call(call, result);
   1.152 +}
   1.153 +
   1.154 +
   1.155 +CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
   1.156 +  return new LateInlineCallGenerator(method, inline_cg);
   1.157 +}
   1.158 +
   1.159  
   1.160  //---------------------------WarmCallGenerator--------------------------------
   1.161  // Internal class which handles initial deferral of inlining decisions.
   1.162 @@ -315,70 +427,7 @@
   1.163  }
   1.164  
   1.165  void WarmCallInfo::make_hot() {
   1.166 -  Compile* C = Compile::current();
   1.167 -  // Replace the callnode with something better.
   1.168 -  CallJavaNode* call = this->call()->as_CallJava();
   1.169 -  ciMethod* method   = call->method();
   1.170 -  int       nargs    = method->arg_size();
   1.171 -  JVMState* jvms     = call->jvms()->clone_shallow(C);
   1.172 -  uint size = TypeFunc::Parms + MAX2(2, nargs);
   1.173 -  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
   1.174 -  for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) {
   1.175 -    map->init_req(i1, call->in(i1));
   1.176 -  }
   1.177 -  jvms->set_map(map);
   1.178 -  jvms->set_offsets(map->req());
   1.179 -  jvms->set_locoff(TypeFunc::Parms);
   1.180 -  jvms->set_stkoff(TypeFunc::Parms);
   1.181 -  GraphKit kit(jvms);
   1.182 -
   1.183 -  JVMState* new_jvms = _hot_cg->generate(kit.jvms());
   1.184 -  if (new_jvms == NULL)  return;  // no change
   1.185 -  if (C->failing())      return;
   1.186 -
   1.187 -  kit.set_jvms(new_jvms);
   1.188 -  Node* res = C->top();
   1.189 -  int   res_size = method->return_type()->size();
   1.190 -  if (res_size != 0) {
   1.191 -    kit.inc_sp(-res_size);
   1.192 -    res = kit.argument(0);
   1.193 -  }
   1.194 -  GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms());
   1.195 -
   1.196 -  // Replace the call:
   1.197 -  for (DUIterator i = call->outs(); call->has_out(i); i++) {
   1.198 -    Node* n = call->out(i);
   1.199 -    Node* nn = NULL;  // replacement
   1.200 -    if (n->is_Proj()) {
   1.201 -      ProjNode* nproj = n->as_Proj();
   1.202 -      assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj");
   1.203 -      if (nproj->_con == TypeFunc::Parms) {
   1.204 -        nn = res;
   1.205 -      } else {
   1.206 -        nn = kit.map()->in(nproj->_con);
   1.207 -      }
   1.208 -      if (nproj->_con == TypeFunc::I_O) {
   1.209 -        for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) {
   1.210 -          Node* e = nproj->out(j);
   1.211 -          if (e->Opcode() == Op_CreateEx) {
   1.212 -            e->replace_by(ekit.argument(0));
   1.213 -          } else if (e->Opcode() == Op_Catch) {
   1.214 -            for (DUIterator k = e->outs(); e->has_out(k); k++) {
   1.215 -              CatchProjNode* p = e->out(j)->as_CatchProj();
   1.216 -              if (p->is_handler_proj()) {
   1.217 -                p->replace_by(ekit.control());
   1.218 -              } else {
   1.219 -                p->replace_by(kit.control());
   1.220 -              }
   1.221 -            }
   1.222 -          }
   1.223 -        }
   1.224 -      }
   1.225 -    }
   1.226 -    NOT_PRODUCT(if (!nn)  n->dump(2));
   1.227 -    assert(nn != NULL, "don't know what to do with this user");
   1.228 -    n->replace_by(nn);
   1.229 -  }
   1.230 +  Unimplemented();
   1.231  }
   1.232  
   1.233  void WarmCallInfo::make_cold() {

mercurial