mirror of
https://github.com/corda/corda.git
synced 2025-06-18 07:08:15 +00:00
move BoundsCheckEvent out of compiler.cpp
This commit is contained in:
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "codegen/compiler.h"
|
#include "codegen/compiler.h"
|
||||||
#include "codegen/assembler.h"
|
#include "codegen/assembler.h"
|
||||||
|
#include "codegen/promise.h"
|
||||||
|
|
||||||
#include "codegen/compiler/regalloc.h"
|
#include "codegen/compiler/regalloc.h"
|
||||||
#include "codegen/compiler/context.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
|
void
|
||||||
move(Context* c, Value* value, Site* src, Site* dst);
|
move(Context* c, Value* value, Site* src, Site* dst);
|
||||||
|
|
||||||
@ -1425,90 +1414,6 @@ register_(Context* c, int number)
|
|||||||
return value(c, type, s, s);
|
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 {
|
class FrameSiteEvent: public Event {
|
||||||
public:
|
public:
|
||||||
FrameSiteEvent(Context* c, Value* value, int index):
|
FrameSiteEvent(Context* c, Value* value, int index):
|
||||||
@ -2650,7 +2555,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* poolAppend(intptr_t value) {
|
virtual Promise* poolAppend(intptr_t value) {
|
||||||
return poolAppendPromise(resolved(&c, value));
|
return poolAppendPromise(resolvedPromise(&c, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Promise* poolAppendPromise(Promise* value) {
|
virtual Promise* poolAppendPromise(Promise* value) {
|
||||||
@ -2670,7 +2575,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual Operand* constant(int64_t value, Compiler::OperandType type) {
|
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) {
|
virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) {
|
||||||
|
@ -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));
|
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 compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -147,6 +147,10 @@ void
|
|||||||
appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false,
|
appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false,
|
||||||
bool cleanLocals = false);
|
bool cleanLocals = false);
|
||||||
|
|
||||||
|
void
|
||||||
|
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
||||||
|
Value* index, intptr_t handler);
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -15,12 +15,42 @@ namespace avian {
|
|||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
|
|
||||||
CodePromise*
|
CodePromise::CodePromise(Context* c, CodePromise* next):
|
||||||
codePromise(Context* c, Promise* offset)
|
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);
|
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 compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -18,25 +18,13 @@ namespace compiler {
|
|||||||
|
|
||||||
class CodePromise: public Promise {
|
class CodePromise: public Promise {
|
||||||
public:
|
public:
|
||||||
CodePromise(Context* c, CodePromise* next):
|
CodePromise(Context* c, CodePromise* next);
|
||||||
c(c), offset(0), next(next)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
CodePromise(Context* c, Promise* offset):
|
CodePromise(Context* c, Promise* offset);
|
||||||
c(c), offset(offset), next(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual int64_t value() {
|
virtual int64_t value();
|
||||||
if (resolved()) {
|
|
||||||
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
|
||||||
}
|
|
||||||
|
|
||||||
abort(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool resolved() {
|
virtual bool resolved();
|
||||||
return c->machineCode != 0 and offset and offset->resolved();
|
|
||||||
}
|
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
Promise* offset;
|
Promise* offset;
|
||||||
@ -45,6 +33,12 @@ class CodePromise: public Promise {
|
|||||||
|
|
||||||
CodePromise* codePromise(Context* c, Promise* offset);
|
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 compiler
|
||||||
} // namespace codegen
|
} // namespace codegen
|
||||||
} // namespace avian
|
} // namespace avian
|
||||||
|
@ -14,18 +14,14 @@
|
|||||||
#include "codegen/compiler/value.h"
|
#include "codegen/compiler/value.h"
|
||||||
#include "codegen/compiler/site.h"
|
#include "codegen/compiler/site.h"
|
||||||
#include "codegen/compiler/resource.h"
|
#include "codegen/compiler/resource.h"
|
||||||
|
#include "codegen/compiler/frame.h"
|
||||||
|
#include "codegen/compiler/promise.h"
|
||||||
|
|
||||||
namespace avian {
|
namespace avian {
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
namespace compiler {
|
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) {
|
int intersectFrameIndexes(int a, int b) {
|
||||||
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
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) {
|
Site* constantSite(Context* c, int64_t value) {
|
||||||
return constantSite(c, resolved(c, value));
|
return constantSite(c, resolvedPromise(c, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user