hotspot/src/share/vm/opto/callnode.cpp
changeset 2528 feeff04a3129
parent 2127 268ea58ed775
child 3600 27aa4477d039
child 3261 c7d5aae8d3f7
--- a/hotspot/src/share/vm/opto/callnode.cpp	Thu Apr 02 10:49:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Fri Apr 03 13:33:32 2009 -0700
@@ -1043,6 +1043,51 @@
 //=============================================================================
 uint AllocateArrayNode::size_of() const { return sizeof(*this); }
 
+Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+  if (remove_dead_region(phase, can_reshape))  return this;
+
+  const Type* type = phase->type(Ideal_length());
+  if (type->isa_int() && type->is_int()->_hi < 0) {
+    if (can_reshape) {
+      PhaseIterGVN *igvn = phase->is_IterGVN();
+      // Unreachable fall through path (negative array length),
+      // the allocation can only throw so disconnect it.
+      Node* proj = proj_out(TypeFunc::Control);
+      Node* catchproj = NULL;
+      if (proj != NULL) {
+        for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) {
+          Node *cn = proj->fast_out(i);
+          if (cn->is_Catch()) {
+            catchproj = cn->as_Multi()->proj_out(CatchProjNode::fall_through_index);
+            break;
+          }
+        }
+      }
+      if (catchproj != NULL && catchproj->outcnt() > 0 &&
+          (catchproj->outcnt() > 1 ||
+           catchproj->unique_out()->Opcode() != Op_Halt)) {
+        assert(catchproj->is_CatchProj(), "must be a CatchProjNode");
+        Node* nproj = catchproj->clone();
+        igvn->register_new_node_with_optimizer(nproj);
+
+        Node *frame = new (phase->C, 1) ParmNode( phase->C->start(), TypeFunc::FramePtr );
+        frame = phase->transform(frame);
+        // Halt & Catch Fire
+        Node *halt = new (phase->C, TypeFunc::Parms) HaltNode( nproj, frame );
+        phase->C->root()->add_req(halt);
+        phase->transform(halt);
+
+        igvn->replace_node(catchproj, phase->C->top());
+        return this;
+      }
+    } else {
+      // Can't correct it during regular GVN so register for IGVN
+      phase->C->record_for_igvn(this);
+    }
+  }
+  return NULL;
+}
+
 // Retrieve the length from the AllocateArrayNode. Narrow the type with a
 // CastII, if appropriate.  If we are not allowed to create new nodes, and
 // a CastII is appropriate, return NULL.