src/share/vm/c1/c1_Instruction.cpp

```rev 4136 : 7153771: array bound check elimination for c1
Summary: when possible optimize out array bound checks, inserting predicates when needed.
Reviewed-by:```

```@@ -32,18 +32,29 @@

// Implementation of Instruction

+int Instruction::dominator_depth() {
+  int result = -1;
+  if (block()) {
+    result = block()->dominator_depth();
+  }
+  assert(result != -1 || this->as_Local(), "Only locals have dominator depth -1");
+  return result;
+}
+
Instruction::Condition Instruction::mirror(Condition cond) {
switch (cond) {
case eql: return eql;
case neq: return neq;
case lss: return gtr;
case leq: return geq;
case gtr: return lss;
case geq: return leq;
+    case aeq: return beq;
+    case beq: return aeq;
}
ShouldNotReachHere();
return eql;
}

```

```@@ -54,10 +65,12 @@
case neq: return eql;
case lss: return geq;
case leq: return gtr;
case gtr: return leq;
case geq: return lss;
+    case aeq: assert(false, "Above equal cannot be negated");
+    case beq: assert(false, "Below equal cannot be negated");
}
ShouldNotReachHere();
return eql;
}

```

```@@ -68,14 +81,14 @@
} else {
_exception_state = NULL;
}
}

-
-Instruction* Instruction::prev(BlockBegin* block) {
+// Prev without need to have BlockBegin
+Instruction* Instruction::prev() {
Instruction* p = NULL;
-  Instruction* q = block;
+  Instruction* q = block();
while (q != this) {
assert(q != NULL, "this is not in the block's instruction list");
p = q; q = q->next();
}
return p;
```

```@@ -120,19 +133,28 @@
#endif // PRODUCT

// perform constant and interval tests on index value
bool AccessIndexed::compute_needs_range_check() {
+
+  if (length()) {
+
Constant* clength = length()->as_Constant();
Constant* cindex = index()->as_Constant();
if (clength && cindex) {
IntConstant* l = clength->type()->as_IntConstant();
IntConstant* i = cindex->type()->as_IntConstant();
if (l && i && i->value() < l->value() && i->value() >= 0) {
return false;
}
}
+  }
+
+  if (!this->check_flag(NeedsRangeCheckFlag)) {
+    return false;
+  }
+
return true;
}

ciType* Local::exact_type() const {
```

```@@ -629,23 +651,29 @@

// In general it is not possible to calculate a value for the field "depth_first_number"
// of the inserted block, without recomputing the values of the other blocks
// in the CFG. Therefore the value of "depth_first_number" in BlockBegin becomes meaningless.
BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) {
-  BlockBegin* new_sux = new BlockBegin(end()->state()->bci());
+  int bci = sux->bci();
+  // critical edge splitting may introduce a goto after a if and array
+  // bound check elimination may insert a predicate between the if and
+  // goto. The bci of the goto can't be the one of the if otherwise
+  // the state and bci are inconsistent and a deoptimization triggered
+  // by the predicate would lead to incorrect execution/a crash.
+  BlockBegin* new_sux = new BlockBegin(bci);

// mark this block (special treatment when block order is computed)
new_sux->set(critical_edge_split_flag);

// This goto is not a safepoint.
Goto* e = new Goto(sux, false);
-  new_sux->set_next(e, end()->state()->bci());
+  new_sux->set_next(e, bci);
new_sux->set_end(e);
// setup states
ValueStack* s = end()->state();
-  new_sux->set_state(s->copy());
-  e->set_state(s->copy());
+  new_sux->set_state(s->copy(s->kind(), bci));
+  e->set_state(s->copy(s->kind(), bci));
assert(new_sux->state()->locals_size() == s->locals_size(), "local size mismatch!");
assert(new_sux->state()->stack_size() == s->stack_size(), "stack size mismatch!");
assert(new_sux->state()->locks_size() == s->locks_size(), "locks size mismatch!");

// link predecessor to new block
```

```@@ -958,19 +986,18 @@

void BlockEnd::set_begin(BlockBegin* begin) {
BlockList* sux = NULL;
if (begin != NULL) {
sux = begin->successors();
-  } else if (_begin != NULL) {
+  } else if (this->begin() != NULL) {
// copy our sux list
-    BlockList* sux = new BlockList(_begin->number_of_sux());
-    for (int i = 0; i < _begin->number_of_sux(); i++) {
-      sux->append(_begin->sux_at(i));
+    BlockList* sux = new BlockList(this->begin()->number_of_sux());
+    for (int i = 0; i < this->begin()->number_of_sux(); i++) {
+      sux->append(this->begin()->sux_at(i));
}
}
_sux = sux;
-  _begin = begin;
}

void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) {
substitute(*_sux, old_sux, new_sux);
```

```@@ -1006,10 +1033,41 @@
} else {
return _block->number_of_preds();
}
}

+#ifndef PRODUCT

+// Constructor of Assert
+Assert::Assert(Value x, Condition cond, bool unordered_is_true, Value y) : Instruction(illegalType)
+  , _x(x)
+  , _cond(cond)
+  , _y(y)
+{
+  set_flag(UnorderedIsTrueFlag, unordered_is_true);
+  assert(x->type()->tag() == y->type()->tag(), "types must match");
+  pin();
+
+  stringStream strStream;
+  Compilation::current()->method()->print_name(&strStream);
+
+  stringStream strStream1;
+  InstructionPrinter ip1(1, &strStream1);
+  ip1.print_instr(x);
+
+  stringStream strStream2;
+  InstructionPrinter ip2(1, &strStream2);
+  ip2.print_instr(y);
+
+  _message = new char[1024];
+  snprintf(_message, 1024, "Assertion %s %s %s in method %s", strStream1.as_string(), ip2.cond_name(cond), strStream2.as_string(), strStream.as_string());
+}
+
+#endif
+
+void RangeCheckPredicate::check_state() {
+  assert(state()->kind() != ValueStack::EmptyExceptionState && state()->kind() != ValueStack::ExceptionState, "will deopt with empty state");
+}

void ProfileInvoke::state_values_do(ValueVisitor* f) {
if (state() != NULL) state()->values_do(f);
}
```