make array bounds checking optional; add comments describing stack mapping algorithm

This commit is contained in:
Joel Dice 2008-01-08 10:10:24 -07:00
parent c8472c4d30
commit 551addc638

View File

@ -21,6 +21,8 @@ const bool DebugNatives = false;
const bool DebugTraces = false; const bool DebugTraces = false;
const bool DebugFrameMaps = false; const bool DebugFrameMaps = false;
const bool CheckArrayBounds = true;
class MyThread: public Thread { class MyThread: public Thread {
public: public:
class CallTrace { class CallTrace {
@ -1616,27 +1618,29 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
case iaload: case iaload:
case laload: case laload:
case saload: { case saload: {
Operand* load = c->label();
Operand* throw_ = c->label();
Operand* index = frame->popInt4(); Operand* index = frame->popInt4();
Operand* array = frame->popObject(); Operand* array = frame->popObject();
c->cmp4(c->constant(0), index); if (CheckArrayBounds) {
c->jl(throw_); Operand* load = c->label();
Operand* throw_ = c->label();
c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), c->cmp4(c->constant(0), index);
index); c->jl(throw_);
c->jl(load);
c->mark(throw_); c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)),
index);
c->jl(load);
c->indirectCallNoReturn c->mark(throw_);
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
frame->trace(0, false),
3, c->thread(), array, index);
c->mark(load); 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:
@ -1688,27 +1692,29 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
value = frame->popInt(); value = frame->popInt();
} }
Operand* store = c->label();
Operand* throw_ = c->label();
Operand* index = frame->popInt4(); Operand* index = frame->popInt4();
Operand* array = frame->popObject(); Operand* array = frame->popObject();
c->cmp4(c->constant(0), index); if (CheckArrayBounds) {
c->jl(throw_); Operand* store = c->label();
Operand* throw_ = c->label();
c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), c->cmp4(c->constant(0), index);
index); c->jl(throw_);
c->jl(store);
c->mark(throw_); c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)),
index);
c->jl(store);
c->indirectCallNoReturn c->mark(throw_);
(c->constant(reinterpret_cast<intptr_t>(throwArrayIndexOutOfBounds)),
frame->trace(0, false),
3, c->thread(), array, index);
c->mark(store); 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: {
@ -3471,6 +3477,14 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
int32_t ip = -1; int32_t ip = -1;
// invariant: for each stack position, roots contains a zero at that
// position if there exists some path to the current instruction
// such that there is definitely not an object pointer at that
// position. Otherwise, roots contains a one at that position,
// meaning either all known paths result in an object pointer at
// that position, or the contents of that position are as yet
// unknown.
while (ei < context->eventLog.length()) { while (ei < context->eventLog.length()) {
Event e = static_cast<Event>(context->eventLog.get(ei++)); Event e = static_cast<Event>(context->eventLog.get(ei++));
switch (e) { switch (e) {
@ -3610,8 +3624,11 @@ calculateFrameMaps(MyThread* t, Context* context)
uintptr_t roots[mapSize]; uintptr_t roots[mapSize];
memset(roots, 0, mapSize * BytesPerWord); memset(roots, 0, mapSize * BytesPerWord);
// first pass: calculate reachable roots at instructions with more // first pass: for each instruction with more than one predecessor,
// than one predecessor. // and for each stack position, determine if there exists a path to
// that instruction such that there is not an object pointer left at
// that stack position (i.e. it is uninitialized or contains
// primitive data).
calculateJunctions(t, context, roots, 0); calculateJunctions(t, context, roots, 0);
// second pass: update trace elements. // second pass: update trace elements.