sign-extend array indexes from 32 to 64 bits on amd64; provide useful messages for certain runtime exceptions

This commit is contained in:
Joel Dice
2008-01-03 11:37:00 -07:00
parent 6cecdc8295
commit 651a27f73e
2 changed files with 77 additions and 53 deletions

View File

@ -812,6 +812,12 @@ class Frame {
return tmp; return tmp;
} }
Operand* popInt4() {
Operand* tmp = c->temporary();
popInt4(tmp);
return tmp;
}
Operand* popLong() { Operand* popLong() {
Operand* tmp = c->temporary(); Operand* tmp = c->temporary();
popLong(tmp); popLong(tmp);
@ -829,6 +835,11 @@ class Frame {
poppedInt(); poppedInt();
} }
void popInt4(Operand* o) {
stack = c->pop4(stack, o);
poppedInt();
}
void popLong(Operand* o) { void popLong(Operand* o) {
stack = c->pop8(stack, o); stack = c->pop8(stack, o);
if (BytesPerWord == 8) { if (BytesPerWord == 8) {
@ -1408,11 +1419,19 @@ makeMultidimensionalArray(MyThread* t, object class_, uintptr_t* stack,
} }
void NO_RETURN void NO_RETURN
throwNew(MyThread* t, object class_) throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index)
{ {
t->exception = makeNew(t, class_); object message = makeString
object trace = makeTrace(t); (t, "array of length %d indexed at %d", arrayLength(t, array), index);
set(t, t->exception, ThrowableTrace, trace); 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); unwind(t);
} }
@ -1427,23 +1446,15 @@ throw_(MyThread* t, object o)
unwind(t); 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<intptr_t>(throwNew)),
frame->trace(0, false),
2, c->thread(), class_);
}
void void
checkCast(MyThread* t, object class_, object o) checkCast(MyThread* t, object class_, object o)
{ {
if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, 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 iaload:
case laload: case laload:
case saload: { case saload: {
Operand* next = c->label(); Operand* load = c->label();
Operand* outOfBounds = c->label(); Operand* throw_ = c->label();
Operand* index = frame->popInt(); Operand* index = frame->popInt4();
Operand* array = frame->popObject(); Operand* array = frame->popObject();
c->cmp4(c->constant(0), index); c->cmp4(c->constant(0), index);
c->jl(outOfBounds); c->jl(throw_);
c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)),
index); index);
c->jge(outOfBounds); c->jl(load);
c->mark(throw_);
c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
frame->trace(0, false),
3, c->thread(), array, index);
c->mark(load);
switch (instruction) { switch (instruction) {
case aaload: case aaload:
@ -1613,13 +1633,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->release(index); c->release(index);
c->release(array); c->release(array);
c->jmp(next);
c->mark(outOfBounds);
compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType);
c->mark(next);
} break; } break;
case aastore: case aastore:
@ -1630,9 +1643,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case iastore: case iastore:
case lastore: case lastore:
case sastore: { case sastore: {
Operand* next = c->label();
Operand* outOfBounds = c->label();
Operand* value; Operand* value;
if (instruction == dastore or instruction == lastore) { if (instruction == dastore or instruction == lastore) {
value = frame->popLong(); value = frame->popLong();
@ -1642,15 +1652,27 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
value = frame->popInt(); value = frame->popInt();
} }
Operand* index = frame->popInt(); Operand* store = c->label();
Operand* throw_ = c->label();
Operand* index = frame->popInt4();
Operand* array = frame->popObject(); Operand* array = frame->popObject();
c->cmp4(c->constant(0), index); 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); index);
c->jge(outOfBounds); c->jl(store);
c->mark(throw_);
c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
frame->trace(0, false),
3, c->thread(), array, index);
c->mark(store);
switch (instruction) { switch (instruction) {
case aastore: { case aastore: {
@ -1686,13 +1708,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->release(value); c->release(value);
c->release(index); c->release(index);
c->release(array); c->release(array);
c->jmp(next);
c->mark(outOfBounds);
compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType);
c->mark(next);
} break; } break;
case aconst_null: case aconst_null:
@ -1727,11 +1742,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
Operand* nonnegative = c->label(); Operand* nonnegative = c->label();
Operand* length = frame->popInt(); Operand* length = frame->popInt4();
c->cmp4(c->constant(0), length); c->cmp4(c->constant(0), length);
c->jge(nonnegative); c->jge(nonnegative);
compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
frame->trace(0, false),
2, c->thread(), length);
c->mark(nonnegative); c->mark(nonnegative);
@ -2831,7 +2849,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
ip = (ip + 3) & ~3; // pad to four byte boundary 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); uint32_t defaultIp = base + codeReadInt32(t, code, ip);
assert(t, defaultIp < codeLength(t, code)); assert(t, defaultIp < codeLength(t, code));
@ -3024,12 +3042,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
Operand* nonnegative = c->label(); Operand* nonnegative = c->label();
Operand* size = frame->popInt(); Operand* length = frame->popInt4();
c->cmp4(c->constant(0), size); c->cmp4(c->constant(0), length);
c->jge(nonnegative); c->jge(nonnegative);
compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
frame->trace(0, false),
2, c->thread(), length);
c->mark(nonnegative); c->mark(nonnegative);
@ -3074,11 +3095,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)), (c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
frame->trace(0, false), frame->trace(0, false),
3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)), 3, c->thread(), c->constant(reinterpret_cast<intptr_t>(constructor)),
size); length);
Operand* result = ::result(c); Operand* result = ::result(c);
c->release(size); c->release(length);
frame->pushObject(result); frame->pushObject(result);
c->release(result); c->release(result);
@ -3218,7 +3239,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
ip = (ip + 3) & ~3; // pad to four byte boundary 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); uint32_t defaultIp = base + codeReadInt32(t, code, ip);
assert(t, defaultIp < codeLength(t, code)); assert(t, defaultIp < codeLength(t, code));

View File

@ -1226,6 +1226,9 @@ RegisterOperand::apply(Context* c, Operation op)
register_(c, high(c))->apply(c, pop); register_(c, high(c))->apply(c, pop);
} else { } else {
c->code.append(0x58 | value(c)); c->code.append(0x58 | value(c));
if (BytesPerWord == 8 and op == pop4) {
accept(c, mov4To8, this);
}
} }
break; break;
@ -1390,7 +1393,7 @@ RegisterOperand::accept(Context* c, Operation op,
case cmp8: { case cmp8: {
assert(c, BytesPerWord == 8 or op == cmp4); // todo assert(c, BytesPerWord == 8 or op == cmp4); // todo
rex(c); if (op == cmp8) rex(c);
if (isInt8(operand->value)) { if (isInt8(operand->value)) {
c->code.append(0x83); c->code.append(0x83);
c->code.append(0xf8 | value(c)); c->code.append(0xf8 | value(c));