From 651a27f73e2c4a96d52e624c15dcfd7facecccf1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 3 Jan 2008 11:37:00 -0700 Subject: [PATCH] sign-extend array indexes from 32 to 64 bits on amd64; provide useful messages for certain runtime exceptions --- src/compile.cpp | 125 +++++++++++++++++++++++++++-------------------- src/compiler.cpp | 5 +- 2 files changed, 77 insertions(+), 53 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 6ee598dc64..605e2768bb 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -812,6 +812,12 @@ class Frame { return tmp; } + Operand* popInt4() { + Operand* tmp = c->temporary(); + popInt4(tmp); + return tmp; + } + Operand* popLong() { Operand* tmp = c->temporary(); popLong(tmp); @@ -829,6 +835,11 @@ class Frame { poppedInt(); } + void popInt4(Operand* o) { + stack = c->pop4(stack, o); + poppedInt(); + } + void popLong(Operand* o) { stack = c->pop8(stack, o); if (BytesPerWord == 8) { @@ -1408,11 +1419,19 @@ makeMultidimensionalArray(MyThread* t, object class_, uintptr_t* stack, } void NO_RETURN -throwNew(MyThread* t, object class_) +throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) { - t->exception = makeNew(t, class_); - object trace = makeTrace(t); - set(t, t->exception, ThrowableTrace, trace); + object message = makeString + (t, "array of length %d indexed at %d", arrayLength(t, array), index); + t->exception = makeArrayIndexOutOfBoundsException(t, message); + unwind(t); +} + +void NO_RETURN +throwNegativeArraySize(MyThread* t, int32_t length) +{ + object message = makeString(t, "%d", length); + t->exception = makeArrayIndexOutOfBoundsException(t, message); unwind(t); } @@ -1427,23 +1446,15 @@ throw_(MyThread* t, object o) unwind(t); } -void -compileThrowNew(MyThread* t, Frame* frame, Machine::Type type) -{ - Operand* class_ = frame->append(arrayBody(t, t->m->types, type)); - Compiler* c = frame->c; - - c->indirectCallNoReturn - (c->constant(reinterpret_cast(throwNew)), - frame->trace(0, false), - 2, c->thread(), class_); -} - void checkCast(MyThread* t, object class_, object o) { if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, o)))) { - throwNew(t, arrayBody(t, t->m->types, Machine::ClassCastExceptionType)); + object message = makeString(t, "%s as %s", + className(t, objectClass(t, o)), + className(t, class_)); + t->exception = makeClassCastException(t, message); + unwind(t); } } @@ -1569,18 +1580,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case iaload: case laload: case saload: { - Operand* next = c->label(); - Operand* outOfBounds = c->label(); + Operand* load = c->label(); + Operand* throw_ = c->label(); - Operand* index = frame->popInt(); + Operand* index = frame->popInt4(); Operand* array = frame->popObject(); c->cmp4(c->constant(0), index); - c->jl(outOfBounds); + c->jl(throw_); c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index); - c->jge(outOfBounds); + c->jl(load); + + c->mark(throw_); + + c->indirectCallNoReturn + (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), + frame->trace(0, false), + 3, c->thread(), array, index); + + c->mark(load); switch (instruction) { case aaload: @@ -1613,13 +1633,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(index); c->release(array); - - c->jmp(next); - - c->mark(outOfBounds); - compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType); - - c->mark(next); } break; case aastore: @@ -1630,9 +1643,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case iastore: case lastore: case sastore: { - Operand* next = c->label(); - Operand* outOfBounds = c->label(); - Operand* value; if (instruction == dastore or instruction == lastore) { value = frame->popLong(); @@ -1642,15 +1652,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) value = frame->popInt(); } - Operand* index = frame->popInt(); + Operand* store = c->label(); + Operand* throw_ = c->label(); + + Operand* index = frame->popInt4(); Operand* array = frame->popObject(); c->cmp4(c->constant(0), index); - c->jl(outOfBounds); + c->jl(throw_); - c->cmp4(c->memory(array, BytesPerWord, 0, 1, frame->trace(0, false)), + c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), index); - c->jge(outOfBounds); + c->jl(store); + + c->mark(throw_); + + c->indirectCallNoReturn + (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), + frame->trace(0, false), + 3, c->thread(), array, index); + + c->mark(store); switch (instruction) { case aastore: { @@ -1686,13 +1708,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(value); c->release(index); c->release(array); - - c->jmp(next); - - c->mark(outOfBounds); - compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType); - - c->mark(next); } break; case aconst_null: @@ -1727,11 +1742,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* nonnegative = c->label(); - Operand* length = frame->popInt(); + Operand* length = frame->popInt4(); c->cmp4(c->constant(0), length); c->jge(nonnegative); - compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); + c->indirectCallNoReturn + (c->constant(reinterpret_cast(throwNegativeArraySize)), + frame->trace(0, false), + 2, c->thread(), length); c->mark(nonnegative); @@ -2831,7 +2849,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) ip = (ip + 3) & ~3; // pad to four byte boundary - Operand* key = frame->popInt(); + Operand* key = frame->popInt4(); uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); @@ -3024,12 +3042,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* nonnegative = c->label(); - Operand* size = frame->popInt(); - c->cmp4(c->constant(0), size); + Operand* length = frame->popInt4(); + c->cmp4(c->constant(0), length); c->jge(nonnegative); - compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); + c->indirectCallNoReturn + (c->constant(reinterpret_cast(throwNegativeArraySize)), + frame->trace(0, false), + 2, c->thread(), length); c->mark(nonnegative); @@ -3074,11 +3095,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(makeBlankArray)), frame->trace(0, false), 3, c->thread(), c->constant(reinterpret_cast(constructor)), - size); + length); Operand* result = ::result(c); - c->release(size); + c->release(length); frame->pushObject(result); c->release(result); @@ -3218,7 +3239,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) ip = (ip + 3) & ~3; // pad to four byte boundary - Operand* key = frame->popInt(); + Operand* key = frame->popInt4(); uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); diff --git a/src/compiler.cpp b/src/compiler.cpp index c56d383489..4439011406 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1226,6 +1226,9 @@ RegisterOperand::apply(Context* c, Operation op) register_(c, high(c))->apply(c, pop); } else { c->code.append(0x58 | value(c)); + if (BytesPerWord == 8 and op == pop4) { + accept(c, mov4To8, this); + } } break; @@ -1390,7 +1393,7 @@ RegisterOperand::accept(Context* c, Operation op, case cmp8: { assert(c, BytesPerWord == 8 or op == cmp4); // todo - rex(c); + if (op == cmp8) rex(c); if (isInt8(operand->value)) { c->code.append(0x83); c->code.append(0xf8 | value(c));