src/share/vm/opto/callGenerator.cpp

changeset 7026
922c87c9aed4
parent 6746
dda2ae6f9557
child 7041
411e30e5fbb8
     1.1 --- a/src/share/vm/opto/callGenerator.cpp	Tue Aug 05 15:02:10 2014 -0700
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Tue Jun 10 12:28:06 2014 -0700
     1.3 @@ -710,7 +710,15 @@
     1.4    Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
     1.5    iophi->set_req(2, slow_map->i_o());
     1.6    kit.set_i_o(gvn.transform(iophi));
     1.7 +  // Merge memory
     1.8    kit.merge_memory(slow_map->merged_memory(), region, 2);
     1.9 +  // Transform new memory Phis.
    1.10 +  for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
    1.11 +    Node* phi = mms.memory();
    1.12 +    if (phi->is_Phi() && phi->in(0) == region) {
    1.13 +      mms.set_memory(gvn.transform(phi));
    1.14 +    }
    1.15 +  }
    1.16    uint tos = kit.jvms()->stkoff() + kit.sp();
    1.17    uint limit = slow_map->req();
    1.18    for (uint i = TypeFunc::Parms; i < limit; i++) {
    1.19 @@ -864,15 +872,15 @@
    1.20  }
    1.21  
    1.22  
    1.23 -//------------------------PredictedIntrinsicGenerator------------------------------
    1.24 -// Internal class which handles all predicted Intrinsic calls.
    1.25 -class PredictedIntrinsicGenerator : public CallGenerator {
    1.26 +//------------------------PredicatedIntrinsicGenerator------------------------------
    1.27 +// Internal class which handles all predicated Intrinsic calls.
    1.28 +class PredicatedIntrinsicGenerator : public CallGenerator {
    1.29    CallGenerator* _intrinsic;
    1.30    CallGenerator* _cg;
    1.31  
    1.32  public:
    1.33 -  PredictedIntrinsicGenerator(CallGenerator* intrinsic,
    1.34 -                              CallGenerator* cg)
    1.35 +  PredicatedIntrinsicGenerator(CallGenerator* intrinsic,
    1.36 +                               CallGenerator* cg)
    1.37      : CallGenerator(cg->method())
    1.38    {
    1.39      _intrinsic = intrinsic;
    1.40 @@ -887,103 +895,182 @@
    1.41  };
    1.42  
    1.43  
    1.44 -CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic,
    1.45 -                                                      CallGenerator* cg) {
    1.46 -  return new PredictedIntrinsicGenerator(intrinsic, cg);
    1.47 +CallGenerator* CallGenerator::for_predicated_intrinsic(CallGenerator* intrinsic,
    1.48 +                                                       CallGenerator* cg) {
    1.49 +  return new PredicatedIntrinsicGenerator(intrinsic, cg);
    1.50  }
    1.51  
    1.52  
    1.53 -JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
    1.54 +JVMState* PredicatedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
    1.55 +  // The code we want to generate here is:
    1.56 +  //    if (receiver == NULL)
    1.57 +  //        uncommon_Trap
    1.58 +  //    if (predicate(0))
    1.59 +  //        do_intrinsic(0)
    1.60 +  //    else
    1.61 +  //    if (predicate(1))
    1.62 +  //        do_intrinsic(1)
    1.63 +  //    ...
    1.64 +  //    else
    1.65 +  //        do_java_comp
    1.66 +
    1.67    GraphKit kit(jvms);
    1.68    PhaseGVN& gvn = kit.gvn();
    1.69  
    1.70    CompileLog* log = kit.C->log();
    1.71    if (log != NULL) {
    1.72 -    log->elem("predicted_intrinsic bci='%d' method='%d'",
    1.73 +    log->elem("predicated_intrinsic bci='%d' method='%d'",
    1.74                jvms->bci(), log->identify(method()));
    1.75    }
    1.76  
    1.77 -  Node* slow_ctl = _intrinsic->generate_predicate(kit.sync_jvms());
    1.78 -  if (kit.failing())
    1.79 -    return NULL;  // might happen because of NodeCountInliningCutoff
    1.80 -
    1.81 -  SafePointNode* slow_map = NULL;
    1.82 -  JVMState* slow_jvms;
    1.83 -  if (slow_ctl != NULL) {
    1.84 -    PreserveJVMState pjvms(&kit);
    1.85 -    kit.set_control(slow_ctl);
    1.86 -    if (!kit.stopped()) {
    1.87 -      slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
    1.88 -      if (kit.failing())
    1.89 -        return NULL;  // might happen because of NodeCountInliningCutoff
    1.90 -      assert(slow_jvms != NULL, "must be");
    1.91 -      kit.add_exception_states_from(slow_jvms);
    1.92 -      kit.set_map(slow_jvms->map());
    1.93 -      if (!kit.stopped())
    1.94 -        slow_map = kit.stop();
    1.95 +  if (!method()->is_static()) {
    1.96 +    // We need an explicit receiver null_check before checking its type in predicate.
    1.97 +    // We share a map with the caller, so his JVMS gets adjusted.
    1.98 +    Node* receiver = kit.null_check_receiver_before_call(method());
    1.99 +    if (kit.stopped()) {
   1.100 +      return kit.transfer_exceptions_into_jvms();
   1.101      }
   1.102    }
   1.103  
   1.104 -  if (kit.stopped()) {
   1.105 -    // Predicate is always false.
   1.106 -    kit.set_jvms(slow_jvms);
   1.107 +  int n_predicates = _intrinsic->predicates_count();
   1.108 +  assert(n_predicates > 0, "sanity");
   1.109 +
   1.110 +  JVMState** result_jvms = NEW_RESOURCE_ARRAY(JVMState*, (n_predicates+1));
   1.111 +
   1.112 +  // Region for normal compilation code if intrinsic failed.
   1.113 +  Node* slow_region = new (kit.C) RegionNode(1);
   1.114 +
   1.115 +  int results = 0;
   1.116 +  for (int predicate = 0; (predicate < n_predicates) && !kit.stopped(); predicate++) {
   1.117 +#ifdef ASSERT
   1.118 +    JVMState* old_jvms = kit.jvms();
   1.119 +    SafePointNode* old_map = kit.map();
   1.120 +    Node* old_io  = old_map->i_o();
   1.121 +    Node* old_mem = old_map->memory();
   1.122 +    Node* old_exc = old_map->next_exception();
   1.123 +#endif
   1.124 +    Node* else_ctrl = _intrinsic->generate_predicate(kit.sync_jvms(), predicate);
   1.125 +#ifdef ASSERT
   1.126 +    // Assert(no_new_memory && no_new_io && no_new_exceptions) after generate_predicate.
   1.127 +    assert(old_jvms == kit.jvms(), "generate_predicate should not change jvm state");
   1.128 +    SafePointNode* new_map = kit.map();
   1.129 +    assert(old_io  == new_map->i_o(), "generate_predicate should not change i_o");
   1.130 +    assert(old_mem == new_map->memory(), "generate_predicate should not change memory");
   1.131 +    assert(old_exc == new_map->next_exception(), "generate_predicate should not add exceptions");
   1.132 +#endif
   1.133 +    if (!kit.stopped()) {
   1.134 +      PreserveJVMState pjvms(&kit);
   1.135 +      // Generate intrinsic code:
   1.136 +      JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
   1.137 +      if (new_jvms == NULL) {
   1.138 +        // Intrinsic failed, use normal compilation path for this predicate.
   1.139 +        slow_region->add_req(kit.control());
   1.140 +      } else {
   1.141 +        kit.add_exception_states_from(new_jvms);
   1.142 +        kit.set_jvms(new_jvms);
   1.143 +        if (!kit.stopped()) {
   1.144 +          result_jvms[results++] = kit.jvms();
   1.145 +        }
   1.146 +      }
   1.147 +    }
   1.148 +    if (else_ctrl == NULL) {
   1.149 +      else_ctrl = kit.C->top();
   1.150 +    }
   1.151 +    kit.set_control(else_ctrl);
   1.152 +  }
   1.153 +  if (!kit.stopped()) {
   1.154 +    // Final 'else' after predicates.
   1.155 +    slow_region->add_req(kit.control());
   1.156 +  }
   1.157 +  if (slow_region->req() > 1) {
   1.158 +    PreserveJVMState pjvms(&kit);
   1.159 +    // Generate normal compilation code:
   1.160 +    kit.set_control(gvn.transform(slow_region));
   1.161 +    JVMState* new_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
   1.162 +    if (kit.failing())
   1.163 +      return NULL;  // might happen because of NodeCountInliningCutoff
   1.164 +    assert(new_jvms != NULL, "must be");
   1.165 +    kit.add_exception_states_from(new_jvms);
   1.166 +    kit.set_jvms(new_jvms);
   1.167 +    if (!kit.stopped()) {
   1.168 +      result_jvms[results++] = kit.jvms();
   1.169 +    }
   1.170 +  }
   1.171 +
   1.172 +  if (results == 0) {
   1.173 +    // All paths ended in uncommon traps.
   1.174 +    (void) kit.stop();
   1.175      return kit.transfer_exceptions_into_jvms();
   1.176    }
   1.177  
   1.178 -  // Generate intrinsic code:
   1.179 -  JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
   1.180 -  if (new_jvms == NULL) {
   1.181 -    // Intrinsic failed, so use slow code or make a direct call.
   1.182 -    if (slow_map == NULL) {
   1.183 -      CallGenerator* cg = CallGenerator::for_direct_call(method());
   1.184 -      new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
   1.185 -    } else {
   1.186 -      kit.set_jvms(slow_jvms);
   1.187 -      return kit.transfer_exceptions_into_jvms();
   1.188 -    }
   1.189 -  }
   1.190 -  kit.add_exception_states_from(new_jvms);
   1.191 -  kit.set_jvms(new_jvms);
   1.192 -
   1.193 -  // Need to merge slow and fast?
   1.194 -  if (slow_map == NULL) {
   1.195 -    // The fast path is the only path remaining.
   1.196 +  if (results == 1) { // Only one path
   1.197 +    kit.set_jvms(result_jvms[0]);
   1.198      return kit.transfer_exceptions_into_jvms();
   1.199    }
   1.200  
   1.201 -  if (kit.stopped()) {
   1.202 -    // Intrinsic method threw an exception, so it's just the slow path after all.
   1.203 -    kit.set_jvms(slow_jvms);
   1.204 -    return kit.transfer_exceptions_into_jvms();
   1.205 +  // Merge all paths.
   1.206 +  kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
   1.207 +  RegionNode* region = new (kit.C) RegionNode(results + 1);
   1.208 +  Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
   1.209 +  for (int i = 0; i < results; i++) {
   1.210 +    JVMState* jvms = result_jvms[i];
   1.211 +    int path = i + 1;
   1.212 +    SafePointNode* map = jvms->map();
   1.213 +    region->init_req(path, map->control());
   1.214 +    iophi->set_req(path, map->i_o());
   1.215 +    if (i == 0) {
   1.216 +      kit.set_jvms(jvms);
   1.217 +    } else {
   1.218 +      kit.merge_memory(map->merged_memory(), region, path);
   1.219 +    }
   1.220 +  }
   1.221 +  kit.set_control(gvn.transform(region));
   1.222 +  kit.set_i_o(gvn.transform(iophi));
   1.223 +  // Transform new memory Phis.
   1.224 +  for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
   1.225 +    Node* phi = mms.memory();
   1.226 +    if (phi->is_Phi() && phi->in(0) == region) {
   1.227 +      mms.set_memory(gvn.transform(phi));
   1.228 +    }
   1.229    }
   1.230  
   1.231 -  // Finish the diamond.
   1.232 -  kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
   1.233 -  RegionNode* region = new (kit.C) RegionNode(3);
   1.234 -  region->init_req(1, kit.control());
   1.235 -  region->init_req(2, slow_map->control());
   1.236 -  kit.set_control(gvn.transform(region));
   1.237 -  Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
   1.238 -  iophi->set_req(2, slow_map->i_o());
   1.239 -  kit.set_i_o(gvn.transform(iophi));
   1.240 -  kit.merge_memory(slow_map->merged_memory(), region, 2);
   1.241 +  // Merge debug info.
   1.242 +  Node** ins = NEW_RESOURCE_ARRAY(Node*, results);
   1.243    uint tos = kit.jvms()->stkoff() + kit.sp();
   1.244 -  uint limit = slow_map->req();
   1.245 +  Node* map = kit.map();
   1.246 +  uint limit = map->req();
   1.247    for (uint i = TypeFunc::Parms; i < limit; i++) {
   1.248      // Skip unused stack slots; fast forward to monoff();
   1.249      if (i == tos) {
   1.250        i = kit.jvms()->monoff();
   1.251        if( i >= limit ) break;
   1.252      }
   1.253 -    Node* m = kit.map()->in(i);
   1.254 -    Node* n = slow_map->in(i);
   1.255 -    if (m != n) {
   1.256 -      const Type* t = gvn.type(m)->meet_speculative(gvn.type(n));
   1.257 -      Node* phi = PhiNode::make(region, m, t);
   1.258 -      phi->set_req(2, n);
   1.259 -      kit.map()->set_req(i, gvn.transform(phi));
   1.260 +    Node* n = map->in(i);
   1.261 +    ins[0] = n;
   1.262 +    const Type* t = gvn.type(n);
   1.263 +    bool needs_phi = false;
   1.264 +    for (int j = 1; j < results; j++) {
   1.265 +      JVMState* jvms = result_jvms[j];
   1.266 +      Node* jmap = jvms->map();
   1.267 +      Node* m = NULL;
   1.268 +      if (jmap->req() > i) {
   1.269 +        m = jmap->in(i);
   1.270 +        if (m != n) {
   1.271 +          needs_phi = true;
   1.272 +          t = t->meet_speculative(gvn.type(m));
   1.273 +        }
   1.274 +      }
   1.275 +      ins[j] = m;
   1.276 +    }
   1.277 +    if (needs_phi) {
   1.278 +      Node* phi = PhiNode::make(region, n, t);
   1.279 +      for (int j = 1; j < results; j++) {
   1.280 +        phi->set_req(j + 1, ins[j]);
   1.281 +      }
   1.282 +      map->set_req(i, gvn.transform(phi));
   1.283      }
   1.284    }
   1.285 +
   1.286    return kit.transfer_exceptions_into_jvms();
   1.287  }
   1.288  

mercurial