mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
improve efficiency of array bounds checks and generate a thunk table for native functions called indirectly
This commit is contained in:
parent
51256f3cc2
commit
65830a76c5
@ -159,11 +159,11 @@ class Assembler {
|
|||||||
virtual int argumentRegister(unsigned index) = 0;
|
virtual int argumentRegister(unsigned index) = 0;
|
||||||
|
|
||||||
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
||||||
uint64_t* registerMask, uintptr_t* procedure) = 0;
|
uint64_t* registerMask, bool* thunk) = 0;
|
||||||
|
|
||||||
virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
|
virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
|
||||||
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
||||||
uint64_t* bRegisterMask, uintptr_t* procedure) = 0;
|
uint64_t* bRegisterMask, bool* thunk) = 0;
|
||||||
|
|
||||||
virtual void apply(Operation op) = 0;
|
virtual void apply(Operation op) = 0;
|
||||||
|
|
||||||
|
703
src/compile.cpp
703
src/compile.cpp
File diff suppressed because it is too large
Load Diff
180
src/compiler.cpp
180
src/compiler.cpp
@ -184,11 +184,12 @@ class Value: public Compiler::Operand {
|
|||||||
|
|
||||||
class Context {
|
class Context {
|
||||||
public:
|
public:
|
||||||
Context(System* system, Assembler* assembler, Zone* zone, void* indirection):
|
Context(System* system, Assembler* assembler, Zone* zone,
|
||||||
|
Compiler::Client* client):
|
||||||
system(system),
|
system(system),
|
||||||
assembler(assembler),
|
assembler(assembler),
|
||||||
zone(zone),
|
zone(zone),
|
||||||
indirection(indirection),
|
client(client),
|
||||||
logicalIp(-1),
|
logicalIp(-1),
|
||||||
state(new (zone->allocate(sizeof(State))) State(0, 0)),
|
state(new (zone->allocate(sizeof(State))) State(0, 0)),
|
||||||
logicalCode(0),
|
logicalCode(0),
|
||||||
@ -220,7 +221,7 @@ class Context {
|
|||||||
System* system;
|
System* system;
|
||||||
Assembler* assembler;
|
Assembler* assembler;
|
||||||
Zone* zone;
|
Zone* zone;
|
||||||
void* indirection;
|
Compiler::Client* client;
|
||||||
int logicalIp;
|
int logicalIp;
|
||||||
State* state;
|
State* state;
|
||||||
LogicalInstruction* logicalCode;
|
LogicalInstruction* logicalCode;
|
||||||
@ -884,6 +885,13 @@ anyRegisterSite(Context* c)
|
|||||||
return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast<uint64_t>(0));
|
return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast<uint64_t>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VirtualSite*
|
||||||
|
registerOrConstantSite(Context* c)
|
||||||
|
{
|
||||||
|
return virtualSite(c, 0, (1 << RegisterOperand) | (1 << ConstantOperand),
|
||||||
|
~static_cast<uint64_t>(0));
|
||||||
|
}
|
||||||
|
|
||||||
Site*
|
Site*
|
||||||
targetOrRegister(Context* c, Value* v)
|
targetOrRegister(Context* c, Value* v)
|
||||||
{
|
{
|
||||||
@ -1366,14 +1374,8 @@ class CallEvent: public Event {
|
|||||||
s = s->next;
|
s = s->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & Compiler::Indirect) {
|
addRead(c, address, BytesPerWord, virtualSite
|
||||||
int r = c->assembler->returnLow();
|
(c, 0, ~0, (static_cast<uint64_t>(mask) << 32) | mask));
|
||||||
addRead(c, address, BytesPerWord, fixedRegisterSite(c, r));
|
|
||||||
mask &= ~(1 << r);
|
|
||||||
} else {
|
|
||||||
addRead(c, address, BytesPerWord, virtualSite
|
|
||||||
(c, 0, ~0, (static_cast<uint64_t>(mask) << 32) | mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Stack* s = stack; s; s = s->next) {
|
for (Stack* s = stack; s; s = s->next) {
|
||||||
s->pushEvent->active = true;
|
s->pushEvent->active = true;
|
||||||
@ -1392,12 +1394,7 @@ class CallEvent: public Event {
|
|||||||
pushNow(c, stack);
|
pushNow(c, stack);
|
||||||
|
|
||||||
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
|
UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call);
|
||||||
if (flags & Compiler::Indirect) {
|
apply(c, type, BytesPerWord, address->source);
|
||||||
apply(c, type, BytesPerWord,
|
|
||||||
constantSite(c, reinterpret_cast<intptr_t>(c->indirection)));
|
|
||||||
} else {
|
|
||||||
apply(c, type, BytesPerWord, address->source);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (traceHandler) {
|
if (traceHandler) {
|
||||||
traceHandler->handleTrace
|
traceHandler->handleTrace
|
||||||
@ -1575,14 +1572,14 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
|
|||||||
|
|
||||||
VirtualSite* srcTarget = virtualSite(c, dst);
|
VirtualSite* srcTarget = virtualSite(c, dst);
|
||||||
VirtualSite* dstTarget = virtualSite(c);
|
VirtualSite* dstTarget = virtualSite(c);
|
||||||
uintptr_t procedure;
|
bool thunk;
|
||||||
|
|
||||||
c->assembler->plan(type, size,
|
c->assembler->plan(type, size,
|
||||||
&(srcTarget->typeMask), &(srcTarget->registerMask),
|
&(srcTarget->typeMask), &(srcTarget->registerMask),
|
||||||
&(dstTarget->typeMask), &(dstTarget->registerMask),
|
&(dstTarget->typeMask), &(dstTarget->registerMask),
|
||||||
&procedure);
|
&thunk);
|
||||||
|
|
||||||
assert(c, procedure == 0); // todo
|
assert(c, not thunk); // todo
|
||||||
|
|
||||||
new (c->zone->allocate(sizeof(MoveEvent)))
|
new (c->zone->allocate(sizeof(MoveEvent)))
|
||||||
MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
|
MoveEvent(c, type, size, src, dst, srcTarget, dstTarget);
|
||||||
@ -1619,14 +1616,14 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second)
|
|||||||
{
|
{
|
||||||
VirtualSite* firstTarget = virtualSite(c);
|
VirtualSite* firstTarget = virtualSite(c);
|
||||||
VirtualSite* secondTarget = virtualSite(c);
|
VirtualSite* secondTarget = virtualSite(c);
|
||||||
uintptr_t procedure;
|
bool thunk;
|
||||||
|
|
||||||
c->assembler->plan(Compare, size,
|
c->assembler->plan(Compare, size,
|
||||||
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
||||||
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
||||||
&procedure);
|
&thunk);
|
||||||
|
|
||||||
assert(c, procedure == 0); // todo
|
assert(c, not thunk); // todo
|
||||||
|
|
||||||
if (DebugAppend) {
|
if (DebugAppend) {
|
||||||
fprintf(stderr, "appendCompare\n");
|
fprintf(stderr, "appendCompare\n");
|
||||||
@ -1723,14 +1720,14 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
|
|||||||
{
|
{
|
||||||
VirtualSite* firstTarget = virtualSite(c);
|
VirtualSite* firstTarget = virtualSite(c);
|
||||||
VirtualSite* secondTarget = virtualSite(c, result);
|
VirtualSite* secondTarget = virtualSite(c, result);
|
||||||
uintptr_t procedure;
|
bool thunk;
|
||||||
|
|
||||||
c->assembler->plan(type, size,
|
c->assembler->plan(type, size,
|
||||||
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
&(firstTarget->typeMask), &(firstTarget->registerMask),
|
||||||
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
&(secondTarget->typeMask), &(secondTarget->registerMask),
|
||||||
&procedure);
|
&thunk);
|
||||||
|
|
||||||
if (procedure) {
|
if (thunk) {
|
||||||
secondTarget->value = 0;
|
secondTarget->value = 0;
|
||||||
|
|
||||||
Stack* oldStack = c->state->stack;
|
Stack* oldStack = c->state->stack;
|
||||||
@ -1741,8 +1738,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
|
|||||||
Stack* argumentStack = c->state->stack;
|
Stack* argumentStack = c->state->stack;
|
||||||
c->state->stack = oldStack;
|
c->state->stack = oldStack;
|
||||||
|
|
||||||
appendCall(c, value(c, constantSite(c, procedure)), Compiler::Indirect,
|
appendCall(c, value(c, constantSite(c, c->client->getThunk(type, size))),
|
||||||
0, result, size, argumentStack, 2);
|
0, 0, result, size, argumentStack, 2);
|
||||||
} else {
|
} else {
|
||||||
if (DebugAppend) {
|
if (DebugAppend) {
|
||||||
fprintf(stderr, "appendCombine\n");
|
fprintf(stderr, "appendCombine\n");
|
||||||
@ -1798,12 +1795,12 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualSite* target = virtualSite(c, result);
|
VirtualSite* target = virtualSite(c, result);
|
||||||
uintptr_t procedure;
|
bool thunk;
|
||||||
|
|
||||||
c->assembler->plan
|
c->assembler->plan
|
||||||
(type, size, &(target->typeMask), &(target->registerMask), &procedure);
|
(type, size, &(target->typeMask), &(target->registerMask), &thunk);
|
||||||
|
|
||||||
assert(c, procedure == 0); // todo
|
assert(c, not thunk); // todo
|
||||||
|
|
||||||
target->typeMask &= ~(1 << MemoryOperand);
|
target->typeMask &= ~(1 << MemoryOperand);
|
||||||
|
|
||||||
@ -2178,6 +2175,105 @@ appendLocal(Context* c, unsigned size, Local* local)
|
|||||||
new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local);
|
new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodePromise*
|
||||||
|
codePromise(Context* c, Event* e)
|
||||||
|
{
|
||||||
|
return e->promises = new (c->zone->allocate(sizeof(CodePromise)))
|
||||||
|
CodePromise(c, e->promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePromise*
|
||||||
|
codePromise(Context* c, int offset)
|
||||||
|
{
|
||||||
|
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
addRead(c, object, BytesPerWord, anyRegisterSite(c));
|
||||||
|
addRead(c, index, BytesPerWord, registerOrConstantSite(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compile(Context* c) {
|
||||||
|
if (DebugCompile) {
|
||||||
|
fprintf(stderr, "BoundsCheckEvent.compile\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Assembler* a = c->assembler;
|
||||||
|
|
||||||
|
ConstantSite* constant = 0;
|
||||||
|
for (Site* s = index->sites; s; s = s->next) {
|
||||||
|
if (s->type(c) == ConstantOperand) {
|
||||||
|
constant = static_cast<ConstantSite*>(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodePromise* nextPromise = codePromise(c, -1);
|
||||||
|
CodePromise* outOfBoundsPromise;
|
||||||
|
|
||||||
|
if (constant) {
|
||||||
|
expect(c, constant->value.value->value() >= 0);
|
||||||
|
} else {
|
||||||
|
outOfBoundsPromise = codePromise(c, -1);
|
||||||
|
|
||||||
|
apply(c, Compare, 4, constantSite(c, resolved(c, 0)), index->source);
|
||||||
|
|
||||||
|
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
|
||||||
|
a->apply
|
||||||
|
(JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(c, object->source->type(c) == RegisterOperand);
|
||||||
|
int base = static_cast<RegisterSite*>(object->source)->register_.low;
|
||||||
|
|
||||||
|
Site* length = memorySite(c, base, lengthOffset);
|
||||||
|
length->acquire(c, 0, 0, 0);
|
||||||
|
|
||||||
|
apply(c, Compare, BytesPerWord, index->source, length);
|
||||||
|
|
||||||
|
length->release(c);
|
||||||
|
|
||||||
|
Assembler::Constant nextConstant(nextPromise);
|
||||||
|
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
|
||||||
|
|
||||||
|
if (constant == 0) {
|
||||||
|
outOfBoundsPromise->offset = a->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvedPromise handlerPromise(handler);
|
||||||
|
Assembler::Constant handlerConstant(&handlerPromise);
|
||||||
|
a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant);
|
||||||
|
|
||||||
|
nextPromise->offset = a->length();
|
||||||
|
|
||||||
|
nextRead(c, object);
|
||||||
|
nextRead(c, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* object;
|
||||||
|
unsigned lengthOffset;
|
||||||
|
Value* index;
|
||||||
|
intptr_t handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
||||||
|
Value* index, intptr_t handler)
|
||||||
|
{
|
||||||
|
if (DebugAppend) {
|
||||||
|
fprintf(stderr, "appendLocal\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent
|
||||||
|
(c, object, lengthOffset, index, handler);
|
||||||
|
}
|
||||||
|
|
||||||
Site*
|
Site*
|
||||||
readSource(Context* c, Stack* stack, Read* r)
|
readSource(Context* c, Stack* stack, Read* r)
|
||||||
{
|
{
|
||||||
@ -2420,8 +2516,9 @@ class Client: public Assembler::Client {
|
|||||||
|
|
||||||
class MyCompiler: public Compiler {
|
class MyCompiler: public Compiler {
|
||||||
public:
|
public:
|
||||||
MyCompiler(System* s, Assembler* assembler, Zone* zone, void* indirection):
|
MyCompiler(System* s, Assembler* assembler, Zone* zone,
|
||||||
c(s, assembler, zone, indirection), client(&c)
|
Compiler::Client* compilerClient):
|
||||||
|
c(s, assembler, zone, compilerClient), client(&c)
|
||||||
{
|
{
|
||||||
assembler->setClient(&client);
|
assembler->setClient(&client);
|
||||||
}
|
}
|
||||||
@ -2569,9 +2666,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Promise* machineIp() {
|
Promise* machineIp() {
|
||||||
Event* e = c.logicalCode[c.logicalIp].lastEvent;
|
return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent);
|
||||||
return e->promises = new (c.zone->allocate(sizeof(CodePromise)))
|
|
||||||
CodePromise(&c, e->promises);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void mark(Operand* label) {
|
virtual void mark(Operand* label) {
|
||||||
@ -2710,6 +2805,13 @@ class MyCompiler: public Compiler {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void checkBounds(Operand* object, unsigned lengthOffset,
|
||||||
|
Operand* index, intptr_t handler)
|
||||||
|
{
|
||||||
|
appendBoundsCheck(&c, static_cast<Value*>(object),
|
||||||
|
lengthOffset, static_cast<Value*>(index), handler);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void store(unsigned size, Operand* src, Operand* dst) {
|
virtual void store(unsigned size, Operand* src, Operand* dst) {
|
||||||
appendMove(&c, Move, size, static_cast<Value*>(src),
|
appendMove(&c, Move, size, static_cast<Value*>(src),
|
||||||
static_cast<Value*>(dst));
|
static_cast<Value*>(dst));
|
||||||
@ -2876,7 +2978,7 @@ class MyCompiler: public Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context c;
|
Context c;
|
||||||
Client client;
|
::Client client;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -2885,10 +2987,10 @@ namespace vm {
|
|||||||
|
|
||||||
Compiler*
|
Compiler*
|
||||||
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
||||||
void* indirection)
|
Compiler::Client* client)
|
||||||
{
|
{
|
||||||
return new (zone->allocate(sizeof(MyCompiler)))
|
return new (zone->allocate(sizeof(MyCompiler)))
|
||||||
MyCompiler(system, assembler, zone, indirection);
|
MyCompiler(system, assembler, zone, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
@ -19,9 +19,16 @@ namespace vm {
|
|||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
virtual ~Client() { }
|
||||||
|
|
||||||
|
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
|
||||||
|
virtual intptr_t getThunk(BinaryOperation op, unsigned size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
static const unsigned Aligned = 1 << 0;
|
static const unsigned Aligned = 1 << 0;
|
||||||
static const unsigned NoReturn = 1 << 1;
|
static const unsigned NoReturn = 1 << 1;
|
||||||
static const unsigned Indirect = 1 << 2;
|
|
||||||
|
|
||||||
class Operand { };
|
class Operand { };
|
||||||
|
|
||||||
@ -80,6 +87,9 @@ class Compiler {
|
|||||||
virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0;
|
virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0;
|
||||||
virtual Operand* loadLocal(unsigned size, unsigned index) = 0;
|
virtual Operand* loadLocal(unsigned size, unsigned index) = 0;
|
||||||
|
|
||||||
|
virtual void checkBounds(Operand* object, unsigned lengthOffset,
|
||||||
|
Operand* index, intptr_t handler) = 0;
|
||||||
|
|
||||||
virtual void store(unsigned size, Operand* src, Operand* dst) = 0;
|
virtual void store(unsigned size, Operand* src, Operand* dst) = 0;
|
||||||
virtual Operand* load(unsigned size, Operand* src) = 0;
|
virtual Operand* load(unsigned size, Operand* src) = 0;
|
||||||
virtual Operand* loadz(unsigned size, Operand* src) = 0;
|
virtual Operand* loadz(unsigned size, Operand* src) = 0;
|
||||||
@ -114,7 +124,7 @@ class Compiler {
|
|||||||
|
|
||||||
Compiler*
|
Compiler*
|
||||||
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
||||||
void* indirection);
|
Compiler::Client* client);
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
44
src/thunks.cpp
Normal file
44
src/thunks.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
THUNK(tryInitClass)
|
||||||
|
THUNK(findInterfaceMethodFromInstance)
|
||||||
|
THUNK(compareDoublesG)
|
||||||
|
THUNK(compareDoublesL)
|
||||||
|
THUNK(compareFloatsG)
|
||||||
|
THUNK(compareFloatsL)
|
||||||
|
THUNK(addDouble)
|
||||||
|
THUNK(subtractDouble)
|
||||||
|
THUNK(multiplyDouble)
|
||||||
|
THUNK(divideDouble)
|
||||||
|
THUNK(moduloDouble)
|
||||||
|
THUNK(negateDouble)
|
||||||
|
THUNK(doubleToFloat)
|
||||||
|
THUNK(doubleToInt)
|
||||||
|
THUNK(doubleToLong)
|
||||||
|
THUNK(addFloat)
|
||||||
|
THUNK(subtractFloat)
|
||||||
|
THUNK(multiplyFloat)
|
||||||
|
THUNK(divideFloat)
|
||||||
|
THUNK(moduloFloat)
|
||||||
|
THUNK(negateFloat)
|
||||||
|
THUNK(floatToDouble)
|
||||||
|
THUNK(floatToInt)
|
||||||
|
THUNK(floatToLong)
|
||||||
|
THUNK(intToDouble)
|
||||||
|
THUNK(intToFloat)
|
||||||
|
THUNK(longToDouble)
|
||||||
|
THUNK(longToFloat)
|
||||||
|
THUNK(divideLong)
|
||||||
|
THUNK(moduloLong)
|
||||||
|
THUNK(makeBlankObjectArray)
|
||||||
|
THUNK(makeBlankArray)
|
||||||
|
THUNK(lookUpAddress)
|
||||||
|
THUNK(setMaybeNull)
|
||||||
|
THUNK(acquireMonitorForObject)
|
||||||
|
THUNK(releaseMonitorForObject)
|
||||||
|
THUNK(makeMultidimensionalArray)
|
||||||
|
THUNK(throw_)
|
||||||
|
THUNK(checkCast)
|
||||||
|
THUNK(instanceOf)
|
||||||
|
THUNK(makeNewWeakReference)
|
||||||
|
THUNK(makeNew)
|
||||||
|
THUNK(set)
|
||||||
|
THUNK(gcIfNecessary)
|
39
src/x86.cpp
39
src/x86.cpp
@ -35,18 +35,6 @@ enum {
|
|||||||
r15 = 15,
|
r15 = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
int64_t FORCE_ALIGN
|
|
||||||
divideLong(int64_t a, int64_t b)
|
|
||||||
{
|
|
||||||
return a / b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t FORCE_ALIGN
|
|
||||||
moduloLong(int64_t a, int64_t b)
|
|
||||||
{
|
|
||||||
return a % b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
isInt8(intptr_t v)
|
isInt8(intptr_t v)
|
||||||
{
|
{
|
||||||
@ -364,16 +352,23 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a)
|
|||||||
{
|
{
|
||||||
assert(c, size == BytesPerWord);
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
|
if (a->low & 8) rex(c, 0x40, a->low);
|
||||||
c->code.append(0xff);
|
c->code.append(0xff);
|
||||||
c->code.append(0xe0 | a->low);
|
c->code.append(0xe0 | (a->low & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a)
|
jumpC(Context* c, unsigned size, Assembler::Constant* a)
|
||||||
{
|
{
|
||||||
assert(c, size == BytesPerWord);
|
assert(c, size == BytesPerWord);
|
||||||
|
|
||||||
unconditional(c, 0xe9, a);
|
if (BytesPerWord == 8) {
|
||||||
|
Assembler::Register r(r10);
|
||||||
|
moveCR(c, size, a, &r);
|
||||||
|
jumpR(c, size, &r);
|
||||||
|
} else {
|
||||||
|
unconditional(c, 0xe9, a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -660,7 +655,7 @@ moveCM(Context* c, unsigned size, Assembler::Constant* a,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
encode(c, 0xc7, 0, b, true);
|
encode(c, 0xc7, 0, b, false);
|
||||||
c->code.append4(a->value->value());
|
c->code.append4(a->value->value());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1940,7 +1935,7 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
||||||
uint64_t* registerMask, uintptr_t* procedure)
|
uint64_t* registerMask, bool* thunk)
|
||||||
{
|
{
|
||||||
if (op == Negate and BytesPerWord == 4 and size == 8) {
|
if (op == Negate and BytesPerWord == 4 and size == 8) {
|
||||||
*typeMask = 1 << RegisterOperand;
|
*typeMask = 1 << RegisterOperand;
|
||||||
@ -1950,12 +1945,12 @@ class MyAssembler: public Assembler {
|
|||||||
*typeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
*typeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||||
*registerMask = ~static_cast<uint64_t>(0);
|
*registerMask = ~static_cast<uint64_t>(0);
|
||||||
}
|
}
|
||||||
*procedure = 0;
|
*thunk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
|
virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
|
||||||
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
||||||
uint64_t* bRegisterMask, uintptr_t* procedure)
|
uint64_t* bRegisterMask, bool* thunk)
|
||||||
{
|
{
|
||||||
*aTypeMask = ~0;
|
*aTypeMask = ~0;
|
||||||
*aRegisterMask = ~static_cast<uint64_t>(0);
|
*aRegisterMask = ~static_cast<uint64_t>(0);
|
||||||
@ -1963,7 +1958,7 @@ class MyAssembler: public Assembler {
|
|||||||
*bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
*bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
||||||
*bRegisterMask = ~static_cast<uint64_t>(0);
|
*bRegisterMask = ~static_cast<uint64_t>(0);
|
||||||
|
|
||||||
*procedure = 0;
|
*thunk = false;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Compare:
|
case Compare:
|
||||||
@ -2004,7 +1999,7 @@ class MyAssembler: public Assembler {
|
|||||||
case Divide:
|
case Divide:
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
*bTypeMask = ~0;
|
*bTypeMask = ~0;
|
||||||
*procedure = reinterpret_cast<uintptr_t>(divideLong);
|
*thunk = true;
|
||||||
} else {
|
} else {
|
||||||
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||||
*bRegisterMask = 1 << rax;
|
*bRegisterMask = 1 << rax;
|
||||||
@ -2014,7 +2009,7 @@ class MyAssembler: public Assembler {
|
|||||||
case Remainder:
|
case Remainder:
|
||||||
if (BytesPerWord == 4 and size == 8) {
|
if (BytesPerWord == 4 and size == 8) {
|
||||||
*bTypeMask = ~0;
|
*bTypeMask = ~0;
|
||||||
*procedure = reinterpret_cast<uintptr_t>(moduloLong);
|
*thunk = true;
|
||||||
} else {
|
} else {
|
||||||
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
*aRegisterMask = ~((1 << rax) | (1 << rdx));
|
||||||
*bRegisterMask = 1 << rax;
|
*bRegisterMask = 1 << rax;
|
||||||
|
Loading…
Reference in New Issue
Block a user