mirror of
https://github.com/corda/corda.git
synced 2025-06-18 23:28:21 +00:00
sign-extend array indexes from 32 to 64 bits on amd64; provide useful messages for certain runtime exceptions
This commit is contained in:
125
src/compile.cpp
125
src/compile.cpp
@ -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));
|
||||||
|
@ -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));
|
||||||
|
Reference in New Issue
Block a user