mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
make array bounds checking optional; add comments describing stack mapping algorithm
This commit is contained in:
parent
c8472c4d30
commit
551addc638
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user