aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto/graphKit.cpp
diff options
context:
space:
mode:
authorroland <none@none>2013-10-19 12:16:43 +0200
committerroland <none@none>2013-10-19 12:16:43 +0200
commit07b56092c33eeece957448e6703448186e832248 (patch)
treebda1fba3bc1b9a0f26652e60468fb3107b20d8fa /src/share/vm/opto/graphKit.cpp
parenta1a245c428f3db760409c12acadaaba20766b901 (diff)
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
Diffstat (limited to 'src/share/vm/opto/graphKit.cpp')
-rw-r--r--src/share/vm/opto/graphKit.cpp67
1 files changed, 61 insertions, 6 deletions
diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
index 7377053a7..be79674f2 100644
--- a/src/share/vm/opto/graphKit.cpp
+++ b/src/share/vm/opto/graphKit.cpp
@@ -639,6 +639,7 @@ PreserveJVMState::PreserveJVMState(GraphKit* kit, bool clone_map) {
_map = kit->map(); // preserve the map
_sp = kit->sp();
kit->set_map(clone_map ? kit->clone_map() : NULL);
+ Compile::current()->inc_preserve_jvm_state();
#ifdef ASSERT
_bci = kit->bci();
Parse* parser = kit->is_Parse();
@@ -656,6 +657,7 @@ PreserveJVMState::~PreserveJVMState() {
#endif
kit->set_map(_map);
kit->set_sp(_sp);
+ Compile::current()->dec_preserve_jvm_state();
}
@@ -1373,17 +1375,70 @@ Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) {
//--------------------------replace_in_map-------------------------------------
void GraphKit::replace_in_map(Node* old, Node* neww) {
- this->map()->replace_edge(old, neww);
+ if (old == neww) {
+ return;
+ }
+
+ map()->replace_edge(old, neww);
// Note: This operation potentially replaces any edge
// on the map. This includes locals, stack, and monitors
// of the current (innermost) JVM state.
- // We can consider replacing in caller maps.
- // The idea would be that an inlined function's null checks
- // can be shared with the entire inlining tree.
- // The expense of doing this is that the PreserveJVMState class
- // would have to preserve caller states too, with a deep copy.
+ if (!ReplaceInParentMaps) {
+ return;
+ }
+
+ // PreserveJVMState doesn't do a deep copy so we can't modify
+ // parents
+ if (Compile::current()->has_preserve_jvm_state()) {
+ return;
+ }
+
+ Parse* parser = is_Parse();
+ bool progress = true;
+ Node* ctrl = map()->in(0);
+ // Follow the chain of parsers and see whether the update can be
+ // done in the map of callers. We can do the replace for a caller if
+ // the current control post dominates the control of a caller.
+ while (parser != NULL && parser->caller() != NULL && progress) {
+ progress = false;
+ Node* parent_map = parser->caller()->map();
+ assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch");
+
+ Node* parent_ctrl = parent_map->in(0);
+
+ while (parent_ctrl->is_Region()) {
+ Node* n = parent_ctrl->as_Region()->is_copy();
+ if (n == NULL) {
+ break;
+ }
+ parent_ctrl = n;
+ }
+
+ for (;;) {
+ if (ctrl == parent_ctrl) {
+ // update the map of the exits which is the one that will be
+ // used when compilation resume after inlining
+ parser->exits().map()->replace_edge(old, neww);
+ progress = true;
+ break;
+ }
+ if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
+ ctrl = ctrl->in(0)->in(0);
+ } else if (ctrl->is_Region()) {
+ Node* n = ctrl->as_Region()->is_copy();
+ if (n == NULL) {
+ break;
+ }
+ ctrl = n;
+ } else {
+ break;
+ }
+ }
+
+ parser = parser->parent_parser();
+ }
}