From e75b57a1272fdbd3b99c1f3bad38b03c8d37519c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 25 Sep 2010 15:48:15 -0600 Subject: [PATCH] don't abort when compiling an array lookup with a constant negative index Instead, just compile it as a direct call to the thunk which throws an ArrayIndexOutOfBoundsException. --- src/compiler.cpp | 40 +++++++++++++++++++++++----------------- test/Arrays.java | 11 +++++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 44217336a2..5e8c447b7e 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4865,12 +4865,13 @@ class BoundsCheckEvent: public Event { Assembler* a = c->assembler; ConstantSite* constant = findConstantSite(c, index); - CodePromise* nextPromise = codePromise - (c, static_cast(0)); CodePromise* outOfBoundsPromise = 0; if (constant) { - expect(c, constant->value->value() >= 0); + if (constant->value->value() < 0) { + Assembler::Constant handlerConstant(resolved(c, handler)); + a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); + } } else { outOfBoundsPromise = codePromise(c, static_cast(0)); @@ -4880,24 +4881,29 @@ class BoundsCheckEvent: public Event { BytesPerWord, &oob, &oob); } - assert(c, object->source->type(c) == RegisterOperand); - MemorySite length(static_cast(object->source)->number, - lengthOffset, NoRegister, 1); - length.acquired = true; + if (constant == 0 or constant->value->value() >= 0) { + assert(c, object->source->type(c) == RegisterOperand); + MemorySite length(static_cast(object->source)->number, + lengthOffset, NoRegister, 1); + length.acquired = true; - ConstantSite next(nextPromise); - apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length, - &length, BytesPerWord, &next, &next); + CodePromise* nextPromise = codePromise + (c, static_cast(0)); - if (constant == 0) { - outOfBoundsPromise->offset = a->offset(); + ConstantSite next(nextPromise); + apply(c, JumpIfGreater, 4, index->source, index->source, 4, &length, + &length, BytesPerWord, &next, &next); + + if (constant == 0) { + outOfBoundsPromise->offset = a->offset(); + } + + Assembler::Constant handlerConstant(resolved(c, handler)); + a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); + + nextPromise->offset = a->offset(); } - Assembler::Constant handlerConstant(resolved(c, handler)); - a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); - - nextPromise->offset = a->offset(); - popRead(c, this, object); popRead(c, this, index); } diff --git a/test/Arrays.java b/test/Arrays.java index 2dd2bcfc30..52c519ba69 100644 --- a/test/Arrays.java +++ b/test/Arrays.java @@ -15,6 +15,17 @@ public class Arrays { expect(exception != null); } + { int[] array = new int[0]; + Exception exception = null; + try { + int x = array[-1]; + } catch (ArrayIndexOutOfBoundsException e) { + exception = e; + } + + expect(exception != null); + } + { int[] array = new int[3]; int i = 0; array[i++] = 1;