src/share/vm/opto/callGenerator.cpp

changeset 435
a61af66fc99e
child 728
c3e045194476
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,744 @@
     1.4 +/*
     1.5 + * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "incls/_precompiled.incl"
    1.29 +#include "incls/_callGenerator.cpp.incl"
    1.30 +
    1.31 +CallGenerator::CallGenerator(ciMethod* method) {
    1.32 +  _method = method;
    1.33 +}
    1.34 +
    1.35 +// Utility function.
    1.36 +const TypeFunc* CallGenerator::tf() const {
    1.37 +  return TypeFunc::make(method());
    1.38 +}
    1.39 +
    1.40 +//-----------------------------ParseGenerator---------------------------------
    1.41 +// Internal class which handles all direct bytecode traversal.
    1.42 +class ParseGenerator : public InlineCallGenerator {
    1.43 +private:
    1.44 +  bool  _is_osr;
    1.45 +  float _expected_uses;
    1.46 +
    1.47 +public:
    1.48 +  ParseGenerator(ciMethod* method, float expected_uses, bool is_osr = false)
    1.49 +    : InlineCallGenerator(method)
    1.50 +  {
    1.51 +    _is_osr        = is_osr;
    1.52 +    _expected_uses = expected_uses;
    1.53 +    assert(can_parse(method, is_osr), "parse must be possible");
    1.54 +  }
    1.55 +
    1.56 +  // Can we build either an OSR or a regular parser for this method?
    1.57 +  static bool can_parse(ciMethod* method, int is_osr = false);
    1.58 +
    1.59 +  virtual bool      is_parse() const           { return true; }
    1.60 +  virtual JVMState* generate(JVMState* jvms);
    1.61 +  int is_osr() { return _is_osr; }
    1.62 +
    1.63 +};
    1.64 +
    1.65 +JVMState* ParseGenerator::generate(JVMState* jvms) {
    1.66 +  Compile* C = Compile::current();
    1.67 +
    1.68 +  if (is_osr()) {
    1.69 +    // The JVMS for a OSR has a single argument (see its TypeFunc).
    1.70 +    assert(jvms->depth() == 1, "no inline OSR");
    1.71 +  }
    1.72 +
    1.73 +  if (C->failing()) {
    1.74 +    return NULL;  // bailing out of the compile; do not try to parse
    1.75 +  }
    1.76 +
    1.77 +  Parse parser(jvms, method(), _expected_uses);
    1.78 +  // Grab signature for matching/allocation
    1.79 +#ifdef ASSERT
    1.80 +  if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
    1.81 +    MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
    1.82 +    assert(C->env()->system_dictionary_modification_counter_changed(),
    1.83 +           "Must invalidate if TypeFuncs differ");
    1.84 +  }
    1.85 +#endif
    1.86 +
    1.87 +  GraphKit& exits = parser.exits();
    1.88 +
    1.89 +  if (C->failing()) {
    1.90 +    while (exits.pop_exception_state() != NULL) ;
    1.91 +    return NULL;
    1.92 +  }
    1.93 +
    1.94 +  assert(exits.jvms()->same_calls_as(jvms), "sanity");
    1.95 +
    1.96 +  // Simply return the exit state of the parser,
    1.97 +  // augmented by any exceptional states.
    1.98 +  return exits.transfer_exceptions_into_jvms();
    1.99 +}
   1.100 +
   1.101 +//---------------------------DirectCallGenerator------------------------------
   1.102 +// Internal class which handles all out-of-line calls w/o receiver type checks.
   1.103 +class DirectCallGenerator : public CallGenerator {
   1.104 +public:
   1.105 +  DirectCallGenerator(ciMethod* method)
   1.106 +    : CallGenerator(method)
   1.107 +  {
   1.108 +  }
   1.109 +  virtual JVMState* generate(JVMState* jvms);
   1.110 +};
   1.111 +
   1.112 +JVMState* DirectCallGenerator::generate(JVMState* jvms) {
   1.113 +  GraphKit kit(jvms);
   1.114 +  bool is_static = method()->is_static();
   1.115 +  address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
   1.116 +                             : SharedRuntime::get_resolve_opt_virtual_call_stub();
   1.117 +
   1.118 +  if (kit.C->log() != NULL) {
   1.119 +    kit.C->log()->elem("direct_call bci='%d'", jvms->bci());
   1.120 +  }
   1.121 +
   1.122 +  CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
   1.123 +  if (!is_static) {
   1.124 +    // Make an explicit receiver null_check as part of this call.
   1.125 +    // Since we share a map with the caller, his JVMS gets adjusted.
   1.126 +    kit.null_check_receiver(method());
   1.127 +    if (kit.stopped()) {
   1.128 +      // And dump it back to the caller, decorated with any exceptions:
   1.129 +      return kit.transfer_exceptions_into_jvms();
   1.130 +    }
   1.131 +    // Mark the call node as virtual, sort of:
   1.132 +    call->set_optimized_virtual(true);
   1.133 +  }
   1.134 +  kit.set_arguments_for_java_call(call);
   1.135 +  kit.set_edges_for_java_call(call);
   1.136 +  Node* ret = kit.set_results_for_java_call(call);
   1.137 +  kit.push_node(method()->return_type()->basic_type(), ret);
   1.138 +  return kit.transfer_exceptions_into_jvms();
   1.139 +}
   1.140 +
   1.141 +class VirtualCallGenerator : public CallGenerator {
   1.142 +private:
   1.143 +  int _vtable_index;
   1.144 +public:
   1.145 +  VirtualCallGenerator(ciMethod* method, int vtable_index)
   1.146 +    : CallGenerator(method), _vtable_index(vtable_index)
   1.147 +  {
   1.148 +    assert(vtable_index == methodOopDesc::invalid_vtable_index ||
   1.149 +           vtable_index >= 0, "either invalid or usable");
   1.150 +  }
   1.151 +  virtual bool      is_virtual() const          { return true; }
   1.152 +  virtual JVMState* generate(JVMState* jvms);
   1.153 +};
   1.154 +
   1.155 +//--------------------------VirtualCallGenerator------------------------------
   1.156 +// Internal class which handles all out-of-line calls checking receiver type.
   1.157 +JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
   1.158 +  GraphKit kit(jvms);
   1.159 +  Node* receiver = kit.argument(0);
   1.160 +
   1.161 +  if (kit.C->log() != NULL) {
   1.162 +    kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
   1.163 +  }
   1.164 +
   1.165 +  // If the receiver is a constant null, do not torture the system
   1.166 +  // by attempting to call through it.  The compile will proceed
   1.167 +  // correctly, but may bail out in final_graph_reshaping, because
   1.168 +  // the call instruction will have a seemingly deficient out-count.
   1.169 +  // (The bailout says something misleading about an "infinite loop".)
   1.170 +  if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
   1.171 +    kit.inc_sp(method()->arg_size());  // restore arguments
   1.172 +    kit.uncommon_trap(Deoptimization::Reason_null_check,
   1.173 +                      Deoptimization::Action_none,
   1.174 +                      NULL, "null receiver");
   1.175 +    return kit.transfer_exceptions_into_jvms();
   1.176 +  }
   1.177 +
   1.178 +  // Ideally we would unconditionally do a null check here and let it
   1.179 +  // be converted to an implicit check based on profile information.
   1.180 +  // However currently the conversion to implicit null checks in
   1.181 +  // Block::implicit_null_check() only looks for loads and stores, not calls.
   1.182 +  ciMethod *caller = kit.method();
   1.183 +  ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data();
   1.184 +  if (!UseInlineCaches || !ImplicitNullChecks ||
   1.185 +       ((ImplicitNullCheckThreshold > 0) && caller_md &&
   1.186 +       (caller_md->trap_count(Deoptimization::Reason_null_check)
   1.187 +       >= (uint)ImplicitNullCheckThreshold))) {
   1.188 +    // Make an explicit receiver null_check as part of this call.
   1.189 +    // Since we share a map with the caller, his JVMS gets adjusted.
   1.190 +    receiver = kit.null_check_receiver(method());
   1.191 +    if (kit.stopped()) {
   1.192 +      // And dump it back to the caller, decorated with any exceptions:
   1.193 +      return kit.transfer_exceptions_into_jvms();
   1.194 +    }
   1.195 +  }
   1.196 +
   1.197 +  assert(!method()->is_static(), "virtual call must not be to static");
   1.198 +  assert(!method()->is_final(), "virtual call should not be to final");
   1.199 +  assert(!method()->is_private(), "virtual call should not be to private");
   1.200 +  assert(_vtable_index == methodOopDesc::invalid_vtable_index || !UseInlineCaches,
   1.201 +         "no vtable calls if +UseInlineCaches ");
   1.202 +  address target = SharedRuntime::get_resolve_virtual_call_stub();
   1.203 +  // Normal inline cache used for call
   1.204 +  CallDynamicJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci());
   1.205 +  kit.set_arguments_for_java_call(call);
   1.206 +  kit.set_edges_for_java_call(call);
   1.207 +  Node* ret = kit.set_results_for_java_call(call);
   1.208 +  kit.push_node(method()->return_type()->basic_type(), ret);
   1.209 +
   1.210 +  // Represent the effect of an implicit receiver null_check
   1.211 +  // as part of this call.  Since we share a map with the caller,
   1.212 +  // his JVMS gets adjusted.
   1.213 +  kit.cast_not_null(receiver);
   1.214 +  return kit.transfer_exceptions_into_jvms();
   1.215 +}
   1.216 +
   1.217 +bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) {
   1.218 +  // Certain methods cannot be parsed at all:
   1.219 +  if (!m->can_be_compiled())              return false;
   1.220 +  if (!m->has_balanced_monitors())        return false;
   1.221 +  if (m->get_flow_analysis()->failing())  return false;
   1.222 +
   1.223 +  // (Methods may bail out for other reasons, after the parser is run.
   1.224 +  // We try to avoid this, but if forced, we must return (Node*)NULL.
   1.225 +  // The user of the CallGenerator must check for this condition.)
   1.226 +  return true;
   1.227 +}
   1.228 +
   1.229 +CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
   1.230 +  if (!ParseGenerator::can_parse(m))  return NULL;
   1.231 +  return new ParseGenerator(m, expected_uses);
   1.232 +}
   1.233 +
   1.234 +// As a special case, the JVMS passed to this CallGenerator is
   1.235 +// for the method execution already in progress, not just the JVMS
   1.236 +// of the caller.  Thus, this CallGenerator cannot be mixed with others!
   1.237 +CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
   1.238 +  if (!ParseGenerator::can_parse(m, true))  return NULL;
   1.239 +  float past_uses = m->interpreter_invocation_count();
   1.240 +  float expected_uses = past_uses;
   1.241 +  return new ParseGenerator(m, expected_uses, true);
   1.242 +}
   1.243 +
   1.244 +CallGenerator* CallGenerator::for_direct_call(ciMethod* m) {
   1.245 +  assert(!m->is_abstract(), "for_direct_call mismatch");
   1.246 +  return new DirectCallGenerator(m);
   1.247 +}
   1.248 +
   1.249 +CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
   1.250 +  assert(!m->is_static(), "for_virtual_call mismatch");
   1.251 +  return new VirtualCallGenerator(m, vtable_index);
   1.252 +}
   1.253 +
   1.254 +
   1.255 +//---------------------------WarmCallGenerator--------------------------------
   1.256 +// Internal class which handles initial deferral of inlining decisions.
   1.257 +class WarmCallGenerator : public CallGenerator {
   1.258 +  WarmCallInfo*   _call_info;
   1.259 +  CallGenerator*  _if_cold;
   1.260 +  CallGenerator*  _if_hot;
   1.261 +  bool            _is_virtual;   // caches virtuality of if_cold
   1.262 +  bool            _is_inline;    // caches inline-ness of if_hot
   1.263 +
   1.264 +public:
   1.265 +  WarmCallGenerator(WarmCallInfo* ci,
   1.266 +                    CallGenerator* if_cold,
   1.267 +                    CallGenerator* if_hot)
   1.268 +    : CallGenerator(if_cold->method())
   1.269 +  {
   1.270 +    assert(method() == if_hot->method(), "consistent choices");
   1.271 +    _call_info  = ci;
   1.272 +    _if_cold    = if_cold;
   1.273 +    _if_hot     = if_hot;
   1.274 +    _is_virtual = if_cold->is_virtual();
   1.275 +    _is_inline  = if_hot->is_inline();
   1.276 +  }
   1.277 +
   1.278 +  virtual bool      is_inline() const           { return _is_inline; }
   1.279 +  virtual bool      is_virtual() const          { return _is_virtual; }
   1.280 +  virtual bool      is_deferred() const         { return true; }
   1.281 +
   1.282 +  virtual JVMState* generate(JVMState* jvms);
   1.283 +};
   1.284 +
   1.285 +
   1.286 +CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
   1.287 +                                            CallGenerator* if_cold,
   1.288 +                                            CallGenerator* if_hot) {
   1.289 +  return new WarmCallGenerator(ci, if_cold, if_hot);
   1.290 +}
   1.291 +
   1.292 +JVMState* WarmCallGenerator::generate(JVMState* jvms) {
   1.293 +  Compile* C = Compile::current();
   1.294 +  if (C->log() != NULL) {
   1.295 +    C->log()->elem("warm_call bci='%d'", jvms->bci());
   1.296 +  }
   1.297 +  jvms = _if_cold->generate(jvms);
   1.298 +  if (jvms != NULL) {
   1.299 +    Node* m = jvms->map()->control();
   1.300 +    if (m->is_CatchProj()) m = m->in(0);  else m = C->top();
   1.301 +    if (m->is_Catch())     m = m->in(0);  else m = C->top();
   1.302 +    if (m->is_Proj())      m = m->in(0);  else m = C->top();
   1.303 +    if (m->is_CallJava()) {
   1.304 +      _call_info->set_call(m->as_Call());
   1.305 +      _call_info->set_hot_cg(_if_hot);
   1.306 +#ifndef PRODUCT
   1.307 +      if (PrintOpto || PrintOptoInlining) {
   1.308 +        tty->print_cr("Queueing for warm inlining at bci %d:", jvms->bci());
   1.309 +        tty->print("WCI: ");
   1.310 +        _call_info->print();
   1.311 +      }
   1.312 +#endif
   1.313 +      _call_info->set_heat(_call_info->compute_heat());
   1.314 +      C->set_warm_calls(_call_info->insert_into(C->warm_calls()));
   1.315 +    }
   1.316 +  }
   1.317 +  return jvms;
   1.318 +}
   1.319 +
   1.320 +void WarmCallInfo::make_hot() {
   1.321 +  Compile* C = Compile::current();
   1.322 +  // Replace the callnode with something better.
   1.323 +  CallJavaNode* call = this->call()->as_CallJava();
   1.324 +  ciMethod* method   = call->method();
   1.325 +  int       nargs    = method->arg_size();
   1.326 +  JVMState* jvms     = call->jvms()->clone_shallow(C);
   1.327 +  uint size = TypeFunc::Parms + MAX2(2, nargs);
   1.328 +  SafePointNode* map = new (C, size) SafePointNode(size, jvms);
   1.329 +  for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) {
   1.330 +    map->init_req(i1, call->in(i1));
   1.331 +  }
   1.332 +  jvms->set_map(map);
   1.333 +  jvms->set_offsets(map->req());
   1.334 +  jvms->set_locoff(TypeFunc::Parms);
   1.335 +  jvms->set_stkoff(TypeFunc::Parms);
   1.336 +  GraphKit kit(jvms);
   1.337 +
   1.338 +  JVMState* new_jvms = _hot_cg->generate(kit.jvms());
   1.339 +  if (new_jvms == NULL)  return;  // no change
   1.340 +  if (C->failing())      return;
   1.341 +
   1.342 +  kit.set_jvms(new_jvms);
   1.343 +  Node* res = C->top();
   1.344 +  int   res_size = method->return_type()->size();
   1.345 +  if (res_size != 0) {
   1.346 +    kit.inc_sp(-res_size);
   1.347 +    res = kit.argument(0);
   1.348 +  }
   1.349 +  GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms());
   1.350 +
   1.351 +  // Replace the call:
   1.352 +  for (DUIterator i = call->outs(); call->has_out(i); i++) {
   1.353 +    Node* n = call->out(i);
   1.354 +    Node* nn = NULL;  // replacement
   1.355 +    if (n->is_Proj()) {
   1.356 +      ProjNode* nproj = n->as_Proj();
   1.357 +      assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj");
   1.358 +      if (nproj->_con == TypeFunc::Parms) {
   1.359 +        nn = res;
   1.360 +      } else {
   1.361 +        nn = kit.map()->in(nproj->_con);
   1.362 +      }
   1.363 +      if (nproj->_con == TypeFunc::I_O) {
   1.364 +        for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) {
   1.365 +          Node* e = nproj->out(j);
   1.366 +          if (e->Opcode() == Op_CreateEx) {
   1.367 +            e->replace_by(ekit.argument(0));
   1.368 +          } else if (e->Opcode() == Op_Catch) {
   1.369 +            for (DUIterator k = e->outs(); e->has_out(k); k++) {
   1.370 +              CatchProjNode* p = e->out(j)->as_CatchProj();
   1.371 +              if (p->is_handler_proj()) {
   1.372 +                p->replace_by(ekit.control());
   1.373 +              } else {
   1.374 +                p->replace_by(kit.control());
   1.375 +              }
   1.376 +            }
   1.377 +          }
   1.378 +        }
   1.379 +      }
   1.380 +    }
   1.381 +    NOT_PRODUCT(if (!nn)  n->dump(2));
   1.382 +    assert(nn != NULL, "don't know what to do with this user");
   1.383 +    n->replace_by(nn);
   1.384 +  }
   1.385 +}
   1.386 +
   1.387 +void WarmCallInfo::make_cold() {
   1.388 +  // No action:  Just dequeue.
   1.389 +}
   1.390 +
   1.391 +
   1.392 +//------------------------PredictedCallGenerator------------------------------
   1.393 +// Internal class which handles all out-of-line calls checking receiver type.
   1.394 +class PredictedCallGenerator : public CallGenerator {
   1.395 +  ciKlass*       _predicted_receiver;
   1.396 +  CallGenerator* _if_missed;
   1.397 +  CallGenerator* _if_hit;
   1.398 +  float          _hit_prob;
   1.399 +
   1.400 +public:
   1.401 +  PredictedCallGenerator(ciKlass* predicted_receiver,
   1.402 +                         CallGenerator* if_missed,
   1.403 +                         CallGenerator* if_hit, float hit_prob)
   1.404 +    : CallGenerator(if_missed->method())
   1.405 +  {
   1.406 +    // The call profile data may predict the hit_prob as extreme as 0 or 1.
   1.407 +    // Remove the extremes values from the range.
   1.408 +    if (hit_prob > PROB_MAX)   hit_prob = PROB_MAX;
   1.409 +    if (hit_prob < PROB_MIN)   hit_prob = PROB_MIN;
   1.410 +
   1.411 +    _predicted_receiver = predicted_receiver;
   1.412 +    _if_missed          = if_missed;
   1.413 +    _if_hit             = if_hit;
   1.414 +    _hit_prob           = hit_prob;
   1.415 +  }
   1.416 +
   1.417 +  virtual bool      is_virtual()   const    { return true; }
   1.418 +  virtual bool      is_inline()    const    { return _if_hit->is_inline(); }
   1.419 +  virtual bool      is_deferred()  const    { return _if_hit->is_deferred(); }
   1.420 +
   1.421 +  virtual JVMState* generate(JVMState* jvms);
   1.422 +};
   1.423 +
   1.424 +
   1.425 +CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
   1.426 +                                                 CallGenerator* if_missed,
   1.427 +                                                 CallGenerator* if_hit,
   1.428 +                                                 float hit_prob) {
   1.429 +  return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob);
   1.430 +}
   1.431 +
   1.432 +
   1.433 +JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
   1.434 +  GraphKit kit(jvms);
   1.435 +  PhaseGVN& gvn = kit.gvn();
   1.436 +  // We need an explicit receiver null_check before checking its type.
   1.437 +  // We share a map with the caller, so his JVMS gets adjusted.
   1.438 +  Node* receiver = kit.argument(0);
   1.439 +
   1.440 +  CompileLog* log = kit.C->log();
   1.441 +  if (log != NULL) {
   1.442 +    log->elem("predicted_call bci='%d' klass='%d'",
   1.443 +              jvms->bci(), log->identify(_predicted_receiver));
   1.444 +  }
   1.445 +
   1.446 +  receiver = kit.null_check_receiver(method());
   1.447 +  if (kit.stopped()) {
   1.448 +    return kit.transfer_exceptions_into_jvms();
   1.449 +  }
   1.450 +
   1.451 +  Node* exact_receiver = receiver;  // will get updated in place...
   1.452 +  Node* slow_ctl = kit.type_check_receiver(receiver,
   1.453 +                                           _predicted_receiver, _hit_prob,
   1.454 +                                           &exact_receiver);
   1.455 +
   1.456 +  SafePointNode* slow_map = NULL;
   1.457 +  JVMState* slow_jvms;
   1.458 +  { PreserveJVMState pjvms(&kit);
   1.459 +    kit.set_control(slow_ctl);
   1.460 +    if (!kit.stopped()) {
   1.461 +      slow_jvms = _if_missed->generate(kit.sync_jvms());
   1.462 +      assert(slow_jvms != NULL, "miss path must not fail to generate");
   1.463 +      kit.add_exception_states_from(slow_jvms);
   1.464 +      kit.set_map(slow_jvms->map());
   1.465 +      if (!kit.stopped())
   1.466 +        slow_map = kit.stop();
   1.467 +    }
   1.468 +  }
   1.469 +
   1.470 +  // fall through if the instance exactly matches the desired type
   1.471 +  kit.replace_in_map(receiver, exact_receiver);
   1.472 +
   1.473 +  // Make the hot call:
   1.474 +  JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
   1.475 +  if (new_jvms == NULL) {
   1.476 +    // Inline failed, so make a direct call.
   1.477 +    assert(_if_hit->is_inline(), "must have been a failed inline");
   1.478 +    CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
   1.479 +    new_jvms = cg->generate(kit.sync_jvms());
   1.480 +  }
   1.481 +  kit.add_exception_states_from(new_jvms);
   1.482 +  kit.set_jvms(new_jvms);
   1.483 +
   1.484 +  // Need to merge slow and fast?
   1.485 +  if (slow_map == NULL) {
   1.486 +    // The fast path is the only path remaining.
   1.487 +    return kit.transfer_exceptions_into_jvms();
   1.488 +  }
   1.489 +
   1.490 +  if (kit.stopped()) {
   1.491 +    // Inlined method threw an exception, so it's just the slow path after all.
   1.492 +    kit.set_jvms(slow_jvms);
   1.493 +    return kit.transfer_exceptions_into_jvms();
   1.494 +  }
   1.495 +
   1.496 +  // Finish the diamond.
   1.497 +  kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
   1.498 +  RegionNode* region = new (kit.C, 3) RegionNode(3);
   1.499 +  region->init_req(1, kit.control());
   1.500 +  region->init_req(2, slow_map->control());
   1.501 +  kit.set_control(gvn.transform(region));
   1.502 +  Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
   1.503 +  iophi->set_req(2, slow_map->i_o());
   1.504 +  kit.set_i_o(gvn.transform(iophi));
   1.505 +  kit.merge_memory(slow_map->merged_memory(), region, 2);
   1.506 +  uint tos = kit.jvms()->stkoff() + kit.sp();
   1.507 +  uint limit = slow_map->req();
   1.508 +  for (uint i = TypeFunc::Parms; i < limit; i++) {
   1.509 +    // Skip unused stack slots; fast forward to monoff();
   1.510 +    if (i == tos) {
   1.511 +      i = kit.jvms()->monoff();
   1.512 +      if( i >= limit ) break;
   1.513 +    }
   1.514 +    Node* m = kit.map()->in(i);
   1.515 +    Node* n = slow_map->in(i);
   1.516 +    if (m != n) {
   1.517 +      const Type* t = gvn.type(m)->meet(gvn.type(n));
   1.518 +      Node* phi = PhiNode::make(region, m, t);
   1.519 +      phi->set_req(2, n);
   1.520 +      kit.map()->set_req(i, gvn.transform(phi));
   1.521 +    }
   1.522 +  }
   1.523 +  return kit.transfer_exceptions_into_jvms();
   1.524 +}
   1.525 +
   1.526 +
   1.527 +//-------------------------UncommonTrapCallGenerator-----------------------------
   1.528 +// Internal class which handles all out-of-line calls checking receiver type.
   1.529 +class UncommonTrapCallGenerator : public CallGenerator {
   1.530 +  Deoptimization::DeoptReason _reason;
   1.531 +  Deoptimization::DeoptAction _action;
   1.532 +
   1.533 +public:
   1.534 +  UncommonTrapCallGenerator(ciMethod* m,
   1.535 +                            Deoptimization::DeoptReason reason,
   1.536 +                            Deoptimization::DeoptAction action)
   1.537 +    : CallGenerator(m)
   1.538 +  {
   1.539 +    _reason = reason;
   1.540 +    _action = action;
   1.541 +  }
   1.542 +
   1.543 +  virtual bool      is_virtual() const          { ShouldNotReachHere(); return false; }
   1.544 +  virtual bool      is_trap() const             { return true; }
   1.545 +
   1.546 +  virtual JVMState* generate(JVMState* jvms);
   1.547 +};
   1.548 +
   1.549 +
   1.550 +CallGenerator*
   1.551 +CallGenerator::for_uncommon_trap(ciMethod* m,
   1.552 +                                 Deoptimization::DeoptReason reason,
   1.553 +                                 Deoptimization::DeoptAction action) {
   1.554 +  return new UncommonTrapCallGenerator(m, reason, action);
   1.555 +}
   1.556 +
   1.557 +
   1.558 +JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
   1.559 +  GraphKit kit(jvms);
   1.560 +  // Take the trap with arguments pushed on the stack.  (Cf. null_check_receiver).
   1.561 +  int nargs = method()->arg_size();
   1.562 +  kit.inc_sp(nargs);
   1.563 +  assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed");
   1.564 +  if (_reason == Deoptimization::Reason_class_check &&
   1.565 +      _action == Deoptimization::Action_maybe_recompile) {
   1.566 +    // Temp fix for 6529811
   1.567 +    // Don't allow uncommon_trap to override our decision to recompile in the event
   1.568 +    // of a class cast failure for a monomorphic call as it will never let us convert
   1.569 +    // the call to either bi-morphic or megamorphic and can lead to unc-trap loops
   1.570 +    bool keep_exact_action = true;
   1.571 +    kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action);
   1.572 +  } else {
   1.573 +    kit.uncommon_trap(_reason, _action);
   1.574 +  }
   1.575 +  return kit.transfer_exceptions_into_jvms();
   1.576 +}
   1.577 +
   1.578 +// (Note:  Moved hook_up_call to GraphKit::set_edges_for_java_call.)
   1.579 +
   1.580 +// (Node:  Merged hook_up_exits into ParseGenerator::generate.)
   1.581 +
   1.582 +#define NODES_OVERHEAD_PER_METHOD (30.0)
   1.583 +#define NODES_PER_BYTECODE (9.5)
   1.584 +
   1.585 +void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) {
   1.586 +  int call_count = profile.count();
   1.587 +  int code_size = call_method->code_size();
   1.588 +
   1.589 +  // Expected execution count is based on the historical count:
   1.590 +  _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor);
   1.591 +
   1.592 +  // Expected profit from inlining, in units of simple call-overheads.
   1.593 +  _profit = 1.0;
   1.594 +
   1.595 +  // Expected work performed by the call in units of call-overheads.
   1.596 +  // %%% need an empirical curve fit for "work" (time in call)
   1.597 +  float bytecodes_per_call = 3;
   1.598 +  _work = 1.0 + code_size / bytecodes_per_call;
   1.599 +
   1.600 +  // Expected size of compilation graph:
   1.601 +  // -XX:+PrintParseStatistics once reported:
   1.602 +  //  Methods seen: 9184  Methods parsed: 9184  Nodes created: 1582391
   1.603 +  //  Histogram of 144298 parsed bytecodes:
   1.604 +  // %%% Need an better predictor for graph size.
   1.605 +  _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size);
   1.606 +}
   1.607 +
   1.608 +// is_cold:  Return true if the node should never be inlined.
   1.609 +// This is true if any of the key metrics are extreme.
   1.610 +bool WarmCallInfo::is_cold() const {
   1.611 +  if (count()  <  WarmCallMinCount)        return true;
   1.612 +  if (profit() <  WarmCallMinProfit)       return true;
   1.613 +  if (work()   >  WarmCallMaxWork)         return true;
   1.614 +  if (size()   >  WarmCallMaxSize)         return true;
   1.615 +  return false;
   1.616 +}
   1.617 +
   1.618 +// is_hot:  Return true if the node should be inlined immediately.
   1.619 +// This is true if any of the key metrics are extreme.
   1.620 +bool WarmCallInfo::is_hot() const {
   1.621 +  assert(!is_cold(), "eliminate is_cold cases before testing is_hot");
   1.622 +  if (count()  >= HotCallCountThreshold)   return true;
   1.623 +  if (profit() >= HotCallProfitThreshold)  return true;
   1.624 +  if (work()   <= HotCallTrivialWork)      return true;
   1.625 +  if (size()   <= HotCallTrivialSize)      return true;
   1.626 +  return false;
   1.627 +}
   1.628 +
   1.629 +// compute_heat:
   1.630 +float WarmCallInfo::compute_heat() const {
   1.631 +  assert(!is_cold(), "compute heat only on warm nodes");
   1.632 +  assert(!is_hot(),  "compute heat only on warm nodes");
   1.633 +  int min_size = MAX2(0,   (int)HotCallTrivialSize);
   1.634 +  int max_size = MIN2(500, (int)WarmCallMaxSize);
   1.635 +  float method_size = (size() - min_size) / MAX2(1, max_size - min_size);
   1.636 +  float size_factor;
   1.637 +  if      (method_size < 0.05)  size_factor = 4;   // 2 sigmas better than avg.
   1.638 +  else if (method_size < 0.15)  size_factor = 2;   // 1 sigma better than avg.
   1.639 +  else if (method_size < 0.5)   size_factor = 1;   // better than avg.
   1.640 +  else                          size_factor = 0.5; // worse than avg.
   1.641 +  return (count() * profit() * size_factor);
   1.642 +}
   1.643 +
   1.644 +bool WarmCallInfo::warmer_than(WarmCallInfo* that) {
   1.645 +  assert(this != that, "compare only different WCIs");
   1.646 +  assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st");
   1.647 +  if (this->heat() > that->heat())   return true;
   1.648 +  if (this->heat() < that->heat())   return false;
   1.649 +  assert(this->heat() == that->heat(), "no NaN heat allowed");
   1.650 +  // Equal heat.  Break the tie some other way.
   1.651 +  if (!this->call() || !that->call())  return (address)this > (address)that;
   1.652 +  return this->call()->_idx > that->call()->_idx;
   1.653 +}
   1.654 +
   1.655 +//#define UNINIT_NEXT ((WarmCallInfo*)badAddress)
   1.656 +#define UNINIT_NEXT ((WarmCallInfo*)NULL)
   1.657 +
   1.658 +WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) {
   1.659 +  assert(next() == UNINIT_NEXT, "not yet on any list");
   1.660 +  WarmCallInfo* prev_p = NULL;
   1.661 +  WarmCallInfo* next_p = head;
   1.662 +  while (next_p != NULL && next_p->warmer_than(this)) {
   1.663 +    prev_p = next_p;
   1.664 +    next_p = prev_p->next();
   1.665 +  }
   1.666 +  // Install this between prev_p and next_p.
   1.667 +  this->set_next(next_p);
   1.668 +  if (prev_p == NULL)
   1.669 +    head = this;
   1.670 +  else
   1.671 +    prev_p->set_next(this);
   1.672 +  return head;
   1.673 +}
   1.674 +
   1.675 +WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) {
   1.676 +  WarmCallInfo* prev_p = NULL;
   1.677 +  WarmCallInfo* next_p = head;
   1.678 +  while (next_p != this) {
   1.679 +    assert(next_p != NULL, "this must be in the list somewhere");
   1.680 +    prev_p = next_p;
   1.681 +    next_p = prev_p->next();
   1.682 +  }
   1.683 +  next_p = this->next();
   1.684 +  debug_only(this->set_next(UNINIT_NEXT));
   1.685 +  // Remove this from between prev_p and next_p.
   1.686 +  if (prev_p == NULL)
   1.687 +    head = next_p;
   1.688 +  else
   1.689 +    prev_p->set_next(next_p);
   1.690 +  return head;
   1.691 +}
   1.692 +
   1.693 +WarmCallInfo* WarmCallInfo::_always_hot  = NULL;
   1.694 +WarmCallInfo* WarmCallInfo::_always_cold = NULL;
   1.695 +
   1.696 +WarmCallInfo* WarmCallInfo::always_hot() {
   1.697 +  if (_always_hot == NULL) {
   1.698 +    static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
   1.699 +    WarmCallInfo* ci = (WarmCallInfo*) bits;
   1.700 +    ci->_profit = ci->_count = MAX_VALUE();
   1.701 +    ci->_work   = ci->_size  = MIN_VALUE();
   1.702 +    _always_hot = ci;
   1.703 +  }
   1.704 +  assert(_always_hot->is_hot(), "must always be hot");
   1.705 +  return _always_hot;
   1.706 +}
   1.707 +
   1.708 +WarmCallInfo* WarmCallInfo::always_cold() {
   1.709 +  if (_always_cold == NULL) {
   1.710 +    static double bits[sizeof(WarmCallInfo) / sizeof(double) + 1] = {0};
   1.711 +    WarmCallInfo* ci = (WarmCallInfo*) bits;
   1.712 +    ci->_profit = ci->_count = MIN_VALUE();
   1.713 +    ci->_work   = ci->_size  = MAX_VALUE();
   1.714 +    _always_cold = ci;
   1.715 +  }
   1.716 +  assert(_always_cold->is_cold(), "must always be cold");
   1.717 +  return _always_cold;
   1.718 +}
   1.719 +
   1.720 +
   1.721 +#ifndef PRODUCT
   1.722 +
   1.723 +void WarmCallInfo::print() const {
   1.724 +  tty->print("%s : C=%6.1f P=%6.1f W=%6.1f S=%6.1f H=%6.1f -> %p",
   1.725 +             is_cold() ? "cold" : is_hot() ? "hot " : "warm",
   1.726 +             count(), profit(), work(), size(), compute_heat(), next());
   1.727 +  tty->cr();
   1.728 +  if (call() != NULL)  call()->dump();
   1.729 +}
   1.730 +
   1.731 +void print_wci(WarmCallInfo* ci) {
   1.732 +  ci->print();
   1.733 +}
   1.734 +
   1.735 +void WarmCallInfo::print_all() const {
   1.736 +  for (const WarmCallInfo* p = this; p != NULL; p = p->next())
   1.737 +    p->print();
   1.738 +}
   1.739 +
   1.740 +int WarmCallInfo::count_all() const {
   1.741 +  int cnt = 0;
   1.742 +  for (const WarmCallInfo* p = this; p != NULL; p = p->next())
   1.743 +    cnt++;
   1.744 +  return cnt;
   1.745 +}
   1.746 +
   1.747 +#endif //PRODUCT

mercurial