1.1 --- a/src/share/vm/opto/graphKit.cpp Fri Oct 18 12:15:32 2013 -0700 1.2 +++ b/src/share/vm/opto/graphKit.cpp Sat Oct 19 12:16:43 2013 +0200 1.3 @@ -639,6 +639,7 @@ 1.4 _map = kit->map(); // preserve the map 1.5 _sp = kit->sp(); 1.6 kit->set_map(clone_map ? kit->clone_map() : NULL); 1.7 + Compile::current()->inc_preserve_jvm_state(); 1.8 #ifdef ASSERT 1.9 _bci = kit->bci(); 1.10 Parse* parser = kit->is_Parse(); 1.11 @@ -656,6 +657,7 @@ 1.12 #endif 1.13 kit->set_map(_map); 1.14 kit->set_sp(_sp); 1.15 + Compile::current()->dec_preserve_jvm_state(); 1.16 } 1.17 1.18 1.19 @@ -1373,17 +1375,70 @@ 1.20 1.21 //--------------------------replace_in_map------------------------------------- 1.22 void GraphKit::replace_in_map(Node* old, Node* neww) { 1.23 - this->map()->replace_edge(old, neww); 1.24 + if (old == neww) { 1.25 + return; 1.26 + } 1.27 + 1.28 + map()->replace_edge(old, neww); 1.29 1.30 // Note: This operation potentially replaces any edge 1.31 // on the map. This includes locals, stack, and monitors 1.32 // of the current (innermost) JVM state. 1.33 1.34 - // We can consider replacing in caller maps. 1.35 - // The idea would be that an inlined function's null checks 1.36 - // can be shared with the entire inlining tree. 1.37 - // The expense of doing this is that the PreserveJVMState class 1.38 - // would have to preserve caller states too, with a deep copy. 1.39 + if (!ReplaceInParentMaps) { 1.40 + return; 1.41 + } 1.42 + 1.43 + // PreserveJVMState doesn't do a deep copy so we can't modify 1.44 + // parents 1.45 + if (Compile::current()->has_preserve_jvm_state()) { 1.46 + return; 1.47 + } 1.48 + 1.49 + Parse* parser = is_Parse(); 1.50 + bool progress = true; 1.51 + Node* ctrl = map()->in(0); 1.52 + // Follow the chain of parsers and see whether the update can be 1.53 + // done in the map of callers. We can do the replace for a caller if 1.54 + // the current control post dominates the control of a caller. 1.55 + while (parser != NULL && parser->caller() != NULL && progress) { 1.56 + progress = false; 1.57 + Node* parent_map = parser->caller()->map(); 1.58 + assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch"); 1.59 + 1.60 + Node* parent_ctrl = parent_map->in(0); 1.61 + 1.62 + while (parent_ctrl->is_Region()) { 1.63 + Node* n = parent_ctrl->as_Region()->is_copy(); 1.64 + if (n == NULL) { 1.65 + break; 1.66 + } 1.67 + parent_ctrl = n; 1.68 + } 1.69 + 1.70 + for (;;) { 1.71 + if (ctrl == parent_ctrl) { 1.72 + // update the map of the exits which is the one that will be 1.73 + // used when compilation resume after inlining 1.74 + parser->exits().map()->replace_edge(old, neww); 1.75 + progress = true; 1.76 + break; 1.77 + } 1.78 + if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) { 1.79 + ctrl = ctrl->in(0)->in(0); 1.80 + } else if (ctrl->is_Region()) { 1.81 + Node* n = ctrl->as_Region()->is_copy(); 1.82 + if (n == NULL) { 1.83 + break; 1.84 + } 1.85 + ctrl = n; 1.86 + } else { 1.87 + break; 1.88 + } 1.89 + } 1.90 + 1.91 + parser = parser->parent_parser(); 1.92 + } 1.93 } 1.94 1.95