< prev index next >

src/share/vm/opto/parse1.cpp

Print this page
rev 5783 : 8024069: replace_in_map() should operate on parent maps
Summary: type information gets lost because replace_in_map() doesn't update parent maps
Reviewed-by: kvn, twisti
rev 5784 : 8026796: Make replace_in_map() on parent maps generic
Summary: propagate node replacements along control flow edges to callers
Reviewed-by: kvn, vlivanov
rev 5786 : 8174164: SafePointNode::_replaced_nodes breaks with irreducible loops
Reviewed-by: kvn

@@ -393,10 +393,13 @@
   // Add MemBarRelease for constructors which write volatile field (PPC64).
   PPC64_ONLY(_wrote_volatile = false;)
   _entry_bci = InvocationEntryBci;
   _tf = NULL;
   _block = NULL;
+  _first_return = true;
+  _replaced_nodes_for_exceptions = false;
+  _new_idx = C->unique();
   debug_only(_block_count = -1);
   debug_only(_blocks = (Block*)-1);
 #ifndef PRODUCT
   if (PrintCompilation || PrintOpto) {
     // Make sure I have an inline tree, so I can print messages about it.

@@ -916,10 +919,14 @@
   caller.set_sp(_caller->sp());
   // Copy out the standard machine state:
   for (uint i = 0; i < TypeFunc::Parms; i++) {
     caller.map()->set_req(i, ex_map->in(i));
   }
+  if (ex_map->has_replaced_nodes()) {
+    _replaced_nodes_for_exceptions = true;
+  }
+  caller.map()->transfer_replaced_nodes_from(ex_map, _new_idx);
   // ...and the exception:
   Node*          ex_oop        = saved_ex_oop(ex_map);
   SafePointNode* caller_ex_map = caller.make_exception_state(ex_oop);
   // Finally, collect the new exception state in my exits:
   _exits.add_exception_state(caller_ex_map);

@@ -985,11 +992,11 @@
   // (e.g., null checks) arising from multiple points within this method.
   // See GraphKit::add_exception_state, which performs the commoning.
   bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
 
   // record exit from a method if compiled while Dtrace is turned on.
-  if (do_synch || C->env()->dtrace_method_probes()) {
+  if (do_synch || C->env()->dtrace_method_probes() || _replaced_nodes_for_exceptions) {
     // First move the exception list out of _exits:
     GraphKit kit(_exits.transfer_exceptions_into_jvms());
     SafePointNode* normal_map = kit.map();  // keep this guy safe
     // Now re-collect the exceptions into _exits:
     SafePointNode* ex_map;

@@ -1010,10 +1017,13 @@
         kit.shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
       }
       if (C->env()->dtrace_method_probes()) {
         kit.make_dtrace_method_exit(method());
       }
+      if (_replaced_nodes_for_exceptions) {
+        kit.map()->apply_replaced_nodes(_new_idx);
+      }
       // Done with exception-path processing.
       ex_map = kit.make_exception_state(ex_oop);
       assert(ex_jvms->same_calls_as(ex_map->jvms()), "sanity");
       // Pop the last vestige of this method:
       ex_map->set_jvms(caller->clone_shallow(C));

@@ -1029,10 +1039,11 @@
     SafePointNode* ex_map;
     while ((ex_map = caller.pop_exception_state()) != NULL) {
       _exits.add_exception_state(ex_map);
     }
   }
+  _exits.map()->apply_replaced_nodes(_new_idx);
 }
 
 //-----------------------------create_entry_map-------------------------------
 // Initialize our parser map to contain the types at method entry.
 // For OSR, the map contains a single RawPtr parameter.

@@ -1043,10 +1054,13 @@
   if (len >= 32760) {
     C->record_method_not_compilable_all_tiers("too many local variables");
     return NULL;
   }
 
+  // clear current replaced nodes that are of no use from here on (map was cloned in build_exits).
+  _caller->map()->delete_replaced_nodes();
+
   // If this is an inlined method, we may have to do a receiver null check.
   if (_caller->has_method() && is_normal_parse() && !method()->is_static()) {
     GraphKit kit(_caller);
     kit.null_check_receiver_before_call(method());
     _caller = kit.transfer_exceptions_into_jvms();

@@ -1066,10 +1080,12 @@
   record_for_igvn(map());
   assert(jvms->endoff() == len, "correct jvms sizing");
 
   SafePointNode* inmap = _caller->map();
   assert(inmap != NULL, "must have inmap");
+  // In case of null check on receiver above
+  map()->transfer_replaced_nodes_from(inmap, _new_idx);
 
   uint i;
 
   // Pass thru the predefined input parameters.
   for (i = 0; i < TypeFunc::Parms; i++) {

@@ -1691,10 +1707,12 @@
         !r->in(0)) {         // The occasional useless Region
       assert(control() == r, "");
       set_control(r->nonnull_req());
     }
 
+    map()->merge_replaced_nodes_with(newin);
+
     // newin has been subsumed into the lazy merge, and is now dead.
     set_block(save_block);
 
     stop();                     // done with this guy, for now
   }

@@ -2059,10 +2077,17 @@
       }
     }
     phi->add_req(value);
   }
 
+  if (_first_return) {
+    _exits.map()->transfer_replaced_nodes_from(map(), _new_idx);
+    _first_return = false;
+  } else {
+    _exits.map()->merge_replaced_nodes_with(map());
+  }
+
   stop_and_kill_map();          // This CFG path dies here
 }
 
 
 //------------------------------add_safepoint----------------------------------
< prev index next >