move BoundsCheckEvent out of compiler.cpp

This commit is contained in:
Joshua Warner 2013-02-13 21:49:37 -07:00
parent d00950458f
commit be86d26512
6 changed files with 137 additions and 124 deletions

View File

@ -14,6 +14,7 @@
#include "codegen/compiler.h"
#include "codegen/assembler.h"
#include "codegen/promise.h"
#include "codegen/compiler/regalloc.h"
#include "codegen/compiler/context.h"
@ -358,18 +359,6 @@ valueType(Context* c, Compiler::OperandType type)
}
}
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
return new(c->zone) ShiftMaskPromise(base, shift, mask);
}
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
return new(c->zone) CombinedPromise(low, high);
}
Promise* resolved(Context* c, int64_t value) {
return new(c->zone) ResolvedPromise(value);
}
void
move(Context* c, Value* value, Site* src, Site* dst);
@ -1425,90 +1414,6 @@ register_(Context* c, int number)
return value(c, type, s, s);
}
class BoundsCheckEvent: public Event {
public:
BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler):
Event(c), object(object), lengthOffset(lengthOffset), index(index),
handler(handler)
{
this->addRead(c, object, generalRegisterMask(c));
this->addRead(c, index, generalRegisterOrConstantMask(c));
}
virtual const char* name() {
return "BoundsCheckEvent";
}
virtual void compile(Context* c) {
Assembler* a = c->assembler;
ConstantSite* constant = findConstantSite(c, index);
CodePromise* outOfBoundsPromise = 0;
if (constant) {
if (constant->value->value() < 0) {
lir::Constant handlerConstant(resolved(c, handler));
a->apply(lir::Call,
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
}
} else {
outOfBoundsPromise = compiler::codePromise(c, static_cast<Promise*>(0));
ConstantSite zero(resolved(c, 0));
ConstantSite oob(outOfBoundsPromise);
apply(c, lir::JumpIfLess,
4, &zero, &zero,
4, index->source, index->source,
TargetBytesPerWord, &oob, &oob);
}
if (constant == 0 or constant->value->value() >= 0) {
assert(c, object->source->type(c) == lir::RegisterOperand);
MemorySite length(static_cast<RegisterSite*>(object->source)->number,
lengthOffset, lir::NoRegister, 1);
length.acquired = true;
CodePromise* nextPromise = compiler::codePromise(c, static_cast<Promise*>(0));
freezeSource(c, TargetBytesPerWord, index);
ConstantSite next(nextPromise);
apply(c, lir::JumpIfGreater,
4, index->source,
index->source, 4, &length,
&length, TargetBytesPerWord, &next, &next);
thawSource(c, TargetBytesPerWord, index);
if (constant == 0) {
outOfBoundsPromise->offset = a->offset();
}
lir::Constant handlerConstant(resolved(c, handler));
a->apply(lir::Call,
OperandInfo(TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
nextPromise->offset = a->offset();
}
popRead(c, this, object);
popRead(c, this, index);
}
Value* object;
unsigned lengthOffset;
Value* index;
intptr_t handler;
};
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler)
{
append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler));
}
class FrameSiteEvent: public Event {
public:
FrameSiteEvent(Context* c, Value* value, int index):
@ -2650,7 +2555,7 @@ class MyCompiler: public Compiler {
}
virtual Promise* poolAppend(intptr_t value) {
return poolAppendPromise(resolved(&c, value));
return poolAppendPromise(resolvedPromise(&c, value));
}
virtual Promise* poolAppendPromise(Promise* value) {
@ -2670,7 +2575,7 @@ class MyCompiler: public Compiler {
}
virtual Operand* constant(int64_t value, Compiler::OperandType type) {
return promiseConstant(resolved(&c, value), type);
return promiseConstant(resolvedPromise(&c, value), type);
}
virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) {

View File

@ -1494,6 +1494,90 @@ void appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit,
append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals));
}
class BoundsCheckEvent: public Event {
public:
BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler):
Event(c), object(object), lengthOffset(lengthOffset), index(index),
handler(handler)
{
this->addRead(c, object, generalRegisterMask(c));
this->addRead(c, index, generalRegisterOrConstantMask(c));
}
virtual const char* name() {
return "BoundsCheckEvent";
}
virtual void compile(Context* c) {
Assembler* a = c->assembler;
ConstantSite* constant = findConstantSite(c, index);
CodePromise* outOfBoundsPromise = 0;
if (constant) {
if (constant->value->value() < 0) {
lir::Constant handlerConstant(resolvedPromise(c, handler));
a->apply(lir::Call,
OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
}
} else {
outOfBoundsPromise = compiler::codePromise(c, static_cast<Promise*>(0));
ConstantSite zero(resolvedPromise(c, 0));
ConstantSite oob(outOfBoundsPromise);
apply(c, lir::JumpIfLess,
4, &zero, &zero,
4, index->source, index->source,
vm::TargetBytesPerWord, &oob, &oob);
}
if (constant == 0 or constant->value->value() >= 0) {
assert(c, object->source->type(c) == lir::RegisterOperand);
MemorySite length(static_cast<RegisterSite*>(object->source)->number,
lengthOffset, lir::NoRegister, 1);
length.acquired = true;
CodePromise* nextPromise = compiler::codePromise(c, static_cast<Promise*>(0));
freezeSource(c, vm::TargetBytesPerWord, index);
ConstantSite next(nextPromise);
apply(c, lir::JumpIfGreater,
4, index->source,
index->source, 4, &length,
&length, vm::TargetBytesPerWord, &next, &next);
thawSource(c, vm::TargetBytesPerWord, index);
if (constant == 0) {
outOfBoundsPromise->offset = a->offset();
}
lir::Constant handlerConstant(resolvedPromise(c, handler));
a->apply(lir::Call,
OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant));
nextPromise->offset = a->offset();
}
popRead(c, this, object);
popRead(c, this, index);
}
Value* object;
unsigned lengthOffset;
Value* index;
intptr_t handler;
};
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler)
{
append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler));
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -147,6 +147,10 @@ void
appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false,
bool cleanLocals = false);
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
Value* index, intptr_t handler);
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -15,12 +15,42 @@ namespace avian {
namespace codegen {
namespace compiler {
CodePromise*
codePromise(Context* c, Promise* offset)
{
CodePromise::CodePromise(Context* c, CodePromise* next):
c(c), offset(0), next(next)
{ }
CodePromise::CodePromise(Context* c, Promise* offset):
c(c), offset(offset), next(0)
{ }
int64_t CodePromise::value() {
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
}
abort(c);
}
bool CodePromise::resolved() {
return c->machineCode != 0 and offset and offset->resolved();
}
CodePromise* codePromise(Context* c, Promise* offset) {
return new (c->zone) CodePromise(c, offset);
}
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) {
return new (c->zone) ShiftMaskPromise(base, shift, mask);
}
Promise* combinedPromise(Context* c, Promise* low, Promise* high) {
return new (c->zone) CombinedPromise(low, high);
}
Promise* resolvedPromise(Context* c, int64_t value) {
return new (c->zone) ResolvedPromise(value);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -18,25 +18,13 @@ namespace compiler {
class CodePromise: public Promise {
public:
CodePromise(Context* c, CodePromise* next):
c(c), offset(0), next(next)
{ }
CodePromise(Context* c, CodePromise* next);
CodePromise(Context* c, Promise* offset):
c(c), offset(offset), next(0)
{ }
CodePromise(Context* c, Promise* offset);
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
}
abort(c);
}
virtual int64_t value();
virtual bool resolved() {
return c->machineCode != 0 and offset and offset->resolved();
}
virtual bool resolved();
Context* c;
Promise* offset;
@ -45,6 +33,12 @@ class CodePromise: public Promise {
CodePromise* codePromise(Context* c, Promise* offset);
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
Promise* resolvedPromise(Context* c, int64_t value);
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -14,18 +14,14 @@
#include "codegen/compiler/value.h"
#include "codegen/compiler/site.h"
#include "codegen/compiler/resource.h"
#include "codegen/compiler/frame.h"
#include "codegen/compiler/promise.h"
namespace avian {
namespace codegen {
namespace compiler {
unsigned frameIndexToOffset(Context* c, unsigned frameIndex);
unsigned offsetToFrameIndex(Context* c, unsigned offset);
ResolvedPromise* resolved(Context* c, int64_t value);
int intersectFrameIndexes(int a, int b) {
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
@ -120,7 +116,7 @@ Site* constantSite(Context* c, Promise* value) {
}
Site* constantSite(Context* c, int64_t value) {
return constantSite(c, resolved(c, value));
return constantSite(c, resolvedPromise(c, value));
}