Merge remote-tracking branch 'joshuawarner32/master'

This commit is contained in:
Joel Dice 2013-02-14 08:14:07 -07:00
commit 66108032a6
43 changed files with 7432 additions and 6416 deletions

View File

@ -923,7 +923,7 @@ generated-code = \
$(build)/type-name-initializations.cpp \
$(build)/type-maps.cpp
vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h)
vm-depends := $(generated-code) $(wildcard $(src)/*.h) $(wildcard $(src)/codegen/*.h) $(wildcard $(src)/codegen/compiler/*.h)
vm-sources = \
$(src)/$(system).cpp \
@ -953,6 +953,17 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed))
ifeq ($(process),compile)
vm-sources += \
$(src)/codegen/compiler.cpp \
$(src)/codegen/compiler/context.cpp \
$(src)/codegen/compiler/resource.cpp \
$(src)/codegen/compiler/site.cpp \
$(src)/codegen/compiler/regalloc.cpp \
$(src)/codegen/compiler/value.cpp \
$(src)/codegen/compiler/read.cpp \
$(src)/codegen/compiler/event.cpp \
$(src)/codegen/compiler/promise.cpp \
$(src)/codegen/compiler/frame.cpp \
$(src)/codegen/compiler/ir.cpp \
$(src)/codegen/registers.cpp \
$(src)/codegen/targets.cpp
ifeq ($(codegen-targets),native)

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,32 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef ASSEMBLER_H
#define ASSEMBLER_H
#ifndef AVIAN_CODEGEN_ASSEMBLER_H
#define AVIAN_CODEGEN_ASSEMBLER_H
#include "system.h"
#include "zone.h"
namespace vm {
#include "codegen/lir.h"
#include "codegen/promise.h"
namespace avian {
namespace codegen {
class RegisterFile;
class OperandInfo {
public:
const unsigned size;
const lir::OperandType type;
lir::Operand* const operand;
inline OperandInfo(unsigned size, lir::OperandType type, lir::Operand* operand):
size(size),
type(type),
operand(operand)
{ }
};
#ifdef AVIAN_TAILS
const bool TailCalls = true;
@ -28,286 +47,8 @@ const bool UseFramePointer = true;
const bool UseFramePointer = false;
#endif
enum Operation {
Return,
LoadBarrier,
StoreStoreBarrier,
StoreLoadBarrier,
Trap
};
const unsigned OperationCount = Trap + 1;
enum UnaryOperation {
Call,
LongCall,
AlignedLongCall,
AlignedCall,
Jump,
LongJump,
AlignedLongJump,
AlignedJump,
NoUnaryOperation = -1
};
const unsigned UnaryOperationCount = AlignedJump + 1;
enum BinaryOperation {
Move,
MoveLow,
MoveHigh,
MoveZ,
Negate,
FloatNegate,
Float2Float,
Float2Int,
Int2Float,
FloatSquareRoot,
FloatAbsolute,
Absolute,
NoBinaryOperation = -1
};
const unsigned BinaryOperationCount = Absolute + 1;
enum TernaryOperation {
Add,
Subtract,
Multiply,
Divide,
Remainder,
ShiftLeft,
ShiftRight,
UnsignedShiftRight,
And,
Or,
Xor,
FloatAdd,
FloatSubtract,
FloatMultiply,
FloatDivide,
FloatRemainder,
FloatMax,
FloatMin,
JumpIfLess,
JumpIfGreater,
JumpIfLessOrEqual,
JumpIfGreaterOrEqual,
JumpIfEqual,
JumpIfNotEqual,
JumpIfFloatEqual,
JumpIfFloatNotEqual,
JumpIfFloatLess,
JumpIfFloatGreater,
JumpIfFloatLessOrEqual,
JumpIfFloatGreaterOrEqual,
JumpIfFloatLessOrUnordered,
JumpIfFloatGreaterOrUnordered,
JumpIfFloatLessOrEqualOrUnordered,
JumpIfFloatGreaterOrEqualOrUnordered,
NoTernaryOperation = -1
};
const unsigned TernaryOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
enum OperandType {
ConstantOperand,
AddressOperand,
RegisterOperand,
MemoryOperand
};
enum ValueType {
ValueGeneral,
ValueFloat
};
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
class Promise {
public:
class Listener {
public:
virtual bool resolve(int64_t value, void** location) = 0;
Listener* next;
};
virtual int64_t value() = 0;
virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; }
};
class ResolvedPromise: public Promise {
public:
ResolvedPromise(int64_t value): value_(value) { }
virtual int64_t value() {
return value_;
}
virtual bool resolved() {
return true;
}
int64_t value_;
};
class ShiftMaskPromise: public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
virtual int64_t value() {
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
unsigned shift;
int64_t mask;
};
class CombinedPromise: public Promise {
public:
CombinedPromise(Promise* low, Promise* high):
low(low), high(high)
{ }
virtual int64_t value() {
return low->value() | (high->value() << 32);
}
virtual bool resolved() {
return low->resolved() and high->resolved();
}
Promise* low;
Promise* high;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
virtual int64_t value() {
return base->value() + offset;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
int64_t offset;
};
class ListenPromise: public Promise {
public:
ListenPromise(System* s, Allocator* allocator):
s(s), allocator(allocator), listener(0)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
System* s;
Allocator* allocator;
Listener* listener;
Promise* promise;
};
class DelayedPromise: public ListenPromise {
public:
DelayedPromise(System* s, Allocator* allocator, Promise* basis,
DelayedPromise* next):
ListenPromise(s, allocator), basis(basis), next(next)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
Promise* basis;
DelayedPromise* next;
};
class Assembler {
public:
class Operand { };
class Constant: public Operand {
public:
Constant(Promise* value): value(value) { }
Promise* value;
};
class Address: public Operand {
public:
Address(Promise* address): address(address) { }
Promise* address;
};
class Register: public Operand {
public:
Register(int low, int high = NoRegister): low(low), high(high) { }
int low;
int high;
};
class Memory: public Operand {
public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
base(base), offset(offset), index(index), scale(scale)
{ }
int base;
int offset;
int index;
unsigned scale;
};
class Client {
public:
@ -327,8 +68,7 @@ class Assembler {
public:
virtual unsigned floatRegisterSize() = 0;
virtual uint32_t generalRegisterMask() = 0;
virtual uint32_t floatRegisterMask() = 0;
virtual const RegisterFile* registerFile() = 0;
virtual int scratch() = 0;
virtual int stack() = 0;
@ -342,8 +82,8 @@ class Assembler {
virtual uintptr_t maximumImmediateJump() = 0;
virtual bool alwaysCondensed(BinaryOperation op) = 0;
virtual bool alwaysCondensed(TernaryOperation op) = 0;
virtual bool alwaysCondensed(lir::BinaryOperation op) = 0;
virtual bool alwaysCondensed(lir::TernaryOperation op) = 0;
virtual bool reserved(int register_) = 0;
@ -360,7 +100,7 @@ class Assembler {
virtual bool matchCall(void* returnAddress, void* target) = 0;
virtual void updateCall(UnaryOperation op, void* returnAddress,
virtual void updateCall(lir::UnaryOperation op, void* returnAddress,
void* newTarget) = 0;
virtual void setConstant(void* dst, uint64_t constant) = 0;
@ -379,17 +119,17 @@ class Assembler {
virtual int framePointerOffset() = 0;
virtual void plan
(UnaryOperation op,
(lir::UnaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
bool* thunk) = 0;
virtual void planSource
(BinaryOperation op,
(lir::BinaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
unsigned bSize, bool* thunk) = 0;
virtual void planDestination
(BinaryOperation op,
(lir::BinaryOperation op,
unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask,
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask) = 0;
@ -399,18 +139,18 @@ class Assembler {
uint8_t dstTypeMask, uint64_t dstRegisterMask) = 0;
virtual void planSource
(TernaryOperation op,
(lir::TernaryOperation op,
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
unsigned cSize, bool* thunk) = 0;
virtual void planDestination
(TernaryOperation op,
(lir::TernaryOperation op,
unsigned aSize, uint8_t aTypeMask, uint64_t aRegisterMask,
unsigned bSize, uint8_t bTypeMask, uint64_t bRegisterMask,
unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask) = 0;
virtual Assembler* makeAssembler(Allocator*, Zone*) = 0;
virtual Assembler* makeAssembler(vm::Allocator*, vm::Zone*) = 0;
virtual void acquire() = 0;
virtual void release() = 0;
@ -437,19 +177,10 @@ class Assembler {
unsigned stackOffsetFromThread)
= 0;
virtual void apply(Operation op) = 0;
virtual void apply(UnaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand) = 0;
virtual void apply(BinaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand,
unsigned bSize, OperandType bType, Operand* bOperand) = 0;
virtual void apply(TernaryOperation op,
unsigned aSize, OperandType aType, Operand* aOperand,
unsigned bSize, OperandType bType, Operand* bOperand,
unsigned cSize, OperandType cType, Operand* cOperand) = 0;
virtual void apply(lir::Operation op) = 0;
virtual void apply(lir::UnaryOperation op, OperandInfo a) = 0;
virtual void apply(lir::BinaryOperation op, OperandInfo a, OperandInfo b) = 0;
virtual void apply(lir::TernaryOperation op, OperandInfo a, OperandInfo b, OperandInfo c) = 0;
virtual void setDestination(uint8_t* dst) = 0;
@ -468,6 +199,7 @@ class Assembler {
virtual void dispose() = 0;
};
} // namespace vm
} // namespace codegen
} // namespace avian
#endif//ASSEMBLER_H
#endif // AVIAN_CODEGEN_ASSEMBLER_H

File diff suppressed because it is too large Load Diff

View File

@ -8,14 +8,15 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef COMPILER_H
#define COMPILER_H
#ifndef AVIAN_CODEGEN_COMPILER_H
#define AVIAN_CODEGEN_COMPILER_H
#include "system.h"
#include "zone.h"
#include "assembler.h"
namespace vm {
namespace avian {
namespace codegen {
class TraceHandler {
public:
@ -26,10 +27,10 @@ class Compiler {
public:
class Client {
public:
virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(BinaryOperation op, unsigned size,
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
unsigned resultSize) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size,
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
unsigned resultSize, bool* threadParameter) = 0;
};
@ -200,9 +201,10 @@ class Compiler {
};
Compiler*
makeCompiler(System* system, Assembler* assembler, Zone* zone,
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler::Client* client);
} // namespace vm
} // namespace codegen
} // namespace avian
#endif//COMPILER_H
#endif // AVIAN_CODEGEN_COMPILER_H

View File

@ -0,0 +1,68 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "codegen/compiler/context.h"
#include "codegen/compiler/resource.h"
namespace avian {
namespace codegen {
namespace compiler {
Context::Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler::Client* client):
system(system),
assembler(assembler),
arch(assembler->arch()),
zone(zone),
client(client),
stack(0),
locals(0),
saved(0),
predecessor(0),
logicalCode(0),
regFile(arch->registerFile()),
regAlloc(system, arch->registerFile()),
registerResources
(static_cast<RegisterResource*>
(zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))),
frameResources(0),
acquiredResources(0),
firstConstant(0),
lastConstant(0),
machineCode(0),
firstEvent(0),
lastEvent(0),
forkState(0),
subroutine(0),
firstBlock(0),
logicalIp(-1),
constantCount(0),
logicalCodeLength(0),
parameterFootprint(0),
localFootprint(0),
machineCodeSize(0),
alignedFrameSize(0),
availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start)
{
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) {
new (registerResources + i) RegisterResource(arch->reserved(i));
if (registerResources[i].reserved) {
-- availableGeneralRegisterCount;
}
}
for (unsigned i = regFile->floatRegisters.start; i < regFile->floatRegisters.limit; ++i) {
new (registerResources + i) RegisterResource(arch->reserved(i));
}
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,120 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_CONTEXT_H
#define AVIAN_CODEGEN_COMPILER_CONTEXT_H
#include "codegen/assembler.h"
#include "codegen/compiler.h"
#include "codegen/compiler/regalloc.h"
namespace avian {
namespace codegen {
namespace compiler {
class Stack;
class Local;
class Event;
class LogicalInstruction;
class Resource;
class RegisterResource;
class FrameResource;
class ConstantPoolNode;
class ForkState;
class MySubroutine;
class Block;
template<class T>
class Cell {
public:
Cell(Cell<T>* next, T* value): next(next), value(value) { }
Cell<T>* next;
T* value;
};
template<class T>
unsigned count(Cell<T>* c) {
unsigned count = 0;
while (c) {
++ count;
c = c->next;
}
return count;
}
template<class T>
Cell<T>* reverseDestroy(Cell<T>* cell) {
Cell<T>* previous = 0;
while (cell) {
Cell<T>* next = cell->next;
cell->next = previous;
previous = cell;
cell = next;
}
return previous;
}
class Context {
public:
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler::Client* client);
vm::System* system;
Assembler* assembler;
Assembler::Architecture* arch;
vm::Zone* zone;
Compiler::Client* client;
Stack* stack;
Local* locals;
Cell<Value>* saved;
Event* predecessor;
LogicalInstruction** logicalCode;
const RegisterFile* regFile;
RegisterAllocator regAlloc;
RegisterResource* registerResources;
FrameResource* frameResources;
Resource* acquiredResources;
ConstantPoolNode* firstConstant;
ConstantPoolNode* lastConstant;
uint8_t* machineCode;
Event* firstEvent;
Event* lastEvent;
ForkState* forkState;
MySubroutine* subroutine;
Block* firstBlock;
int logicalIp;
unsigned constantCount;
unsigned logicalCodeLength;
unsigned parameterFootprint;
unsigned localFootprint;
unsigned machineCodeSize;
unsigned alignedFrameSize;
unsigned availableGeneralRegisterCount;
};
inline Aborter* getAborter(Context* c) {
return c->system;
}
template<class T>
Cell<T>* cons(Context* c, T* value, Cell<T>* next) {
return new (c->zone) Cell<T>(next, value);
}
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_CONTEXT_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_EVENT_H
#define AVIAN_CODEGEN_COMPILER_EVENT_H
namespace avian {
namespace codegen {
namespace compiler {
class Context;
class CodePromise;
class Snapshot;
class Link;
class Site;
class StubRead;
const bool DebugReads = false;
const bool DebugMoves = false;
class Event {
public:
Event(Context* c);
virtual const char* name() = 0;
virtual void compile(Context* c) = 0;
virtual bool isBranch() { return false; }
virtual bool allExits() { return false; }
virtual Local* locals() { return localsBefore; }
void addRead(Context* c, Value* v, Read* r);
void addRead(Context* c, Value* v, const SiteMask& mask,
Value* successor = 0);
void addReads(Context* c, Value* v, unsigned size,
const SiteMask& lowMask, Value* lowSuccessor,
const SiteMask& highMask, Value* highSuccessor);
void addReads(Context* c, Value* v, unsigned size,
const SiteMask& lowMask, const SiteMask& highMask);
CodePromise* makeCodePromise(Context* c);
bool isUnreachable();
Event* next;
Stack* stackBefore;
Local* localsBefore;
Stack* stackAfter;
Local* localsAfter;
CodePromise* promises;
Read* reads;
Site** junctionSites;
Snapshot* snapshots;
Link* predecessors;
Link* successors;
Cell<Link>* visitLinks;
Block* block;
LogicalInstruction* logicalInstruction;
unsigned readCount;
};
class StubReadPair {
public:
Value* value;
StubRead* read;
};
class JunctionState {
public:
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
unsigned frameFootprint;
StubReadPair reads[0];
};
class Link {
public:
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState):
predecessor(predecessor), nextPredecessor(nextPredecessor),
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
junctionState(0)
{ }
unsigned countPredecessors();
Link* lastPredecessor();
unsigned countSuccessors();
Event* predecessor;
Link* nextPredecessor;
Event* successor;
Link* nextSuccessor;
ForkState* forkState;
JunctionState* junctionState;
};
Link*
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState);
void
appendCall(Context* c, Value* address, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned resultSize,
Stack* argumentStack, unsigned argumentCount,
unsigned stackArgumentFootprint);
void
appendReturn(Context* c, unsigned size, Value* value);
void
appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst);
void
appendCombine(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result);
void
appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize,
Value* first, unsigned resultSize, Value* result);
void
appendOperation(Context* c, lir::Operation op);
void
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result);
void
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
Value* second, Value* address);
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);
void
appendFrameSite(Context* c, Value* value, int index);
void
appendSaveLocals(Context* c);
void
appendDummy(Context* c);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_EVENT_H

View File

@ -0,0 +1,119 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/context.h"
#include "codegen/compiler/frame.h"
namespace avian {
namespace codegen {
namespace compiler {
unsigned totalFrameSize(Context* c) {
return c->alignedFrameSize
+ c->arch->frameHeaderSize()
+ c->arch->argumentFootprint(c->parameterFootprint);
}
int frameIndex(Context* c, int localIndex) {
assert(c, localIndex >= 0);
int index = c->alignedFrameSize + c->parameterFootprint - localIndex - 1;
if (localIndex < static_cast<int>(c->parameterFootprint)) {
index += c->arch->frameHeaderSize();
} else {
index -= c->arch->frameFooterSize();
}
assert(c, index >= 0);
assert(c, static_cast<unsigned>(index) < totalFrameSize(c));
return index;
}
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
assert(c, frameIndex < totalFrameSize(c));
return (frameIndex + c->arch->frameFooterSize()) * vm::TargetBytesPerWord;
}
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
assert(c, static_cast<int>
((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize()) >= 0);
assert(c, ((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize())
< totalFrameSize(c));
return (offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize();
}
unsigned frameBase(Context* c) {
return c->alignedFrameSize
- c->arch->frameReturnAddressSize()
- c->arch->frameFooterSize()
+ c->arch->frameHeaderSize();
}
FrameIterator::Element::Element(Value* value, unsigned localIndex):
value(value), localIndex(localIndex)
{ }
int FrameIterator::Element::frameIndex(Context* c) {
return compiler::frameIndex(c, this->localIndex);
}
FrameIterator::FrameIterator(Context* c, Stack* stack, Local* locals,
bool includeEmpty):
stack(stack), locals(locals), localIndex(c->localFootprint - 1),
includeEmpty(includeEmpty)
{ }
bool FrameIterator::hasMore() {
if (not includeEmpty) {
while (stack and stack->value == 0) {
stack = stack->next;
}
while (localIndex >= 0 and locals[localIndex].value == 0) {
-- localIndex;
}
}
return stack != 0 or localIndex >= 0;
}
FrameIterator::Element FrameIterator::next(Context* c) {
Value* v;
unsigned li;
if (stack) {
Stack* s = stack;
v = s->value;
li = s->index + c->localFootprint;
stack = stack->next;
} else {
Local* l = locals + localIndex;
v = l->value;
li = localIndex;
-- localIndex;
}
return Element(v, li);
}
Stack* stack(Context* c, Value* value, Stack* next) {
return new(c->zone) Stack(next ? next->index + 1 : 0, value, next);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,75 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_FRAME_H
#define AVIAN_CODEGEN_COMPILER_FRAME_H
namespace avian {
namespace codegen {
namespace compiler {
unsigned totalFrameSize(Context* c);
int frameIndex(Context* c, int localIndex);
unsigned frameIndexToOffset(Context* c, unsigned frameIndex);
unsigned offsetToFrameIndex(Context* c, unsigned offset);
unsigned frameBase(Context* c);
class FrameIterator {
public:
class Element {
public:
Element(Value* value, unsigned localIndex);
int frameIndex(Context* c);
Value* const value;
const unsigned localIndex;
};
FrameIterator(Context* c, Stack* stack, Local* locals,
bool includeEmpty = false);
bool hasMore();
Element next(Context* c);
Stack* stack;
Local* locals;
int localIndex;
bool includeEmpty;
};
class Local {
public:
Value* value;
};
class Stack {
public:
Stack(unsigned index, Value* value, Stack* next):
index(index), value(value), next(next)
{ }
unsigned index;
Value* value;
Stack* next;
};
Stack* stack(Context* c, Value* value, Stack* next);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_FRAME_H

View File

@ -0,0 +1,48 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "codegen/compiler/context.h"
#include "codegen/compiler/ir.h"
namespace avian {
namespace codegen {
namespace compiler {
LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(0), subroutine(0), index(index)
{ }
LogicalInstruction* LogicalInstruction::next(Context* c) {
LogicalInstruction* i = this;
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
i = c->logicalCode[n];
if (i) return i;
}
return 0;
}
unsigned
machineOffset(Context* c, int logicalIp)
{
return c->logicalCode[logicalIp]->machineOffset->value();
}
Block::Block(Event* head):
head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0)
{ }
Block* block(Context* c, Event* head) {
return new(c->zone) Block(head);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

90
src/codegen/compiler/ir.h Normal file
View File

@ -0,0 +1,90 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_IR_H
#define AVIAN_CODEGEN_COMPILER_IR_H
namespace avian {
namespace codegen {
namespace compiler {
class MultiRead;
class ForkElement {
public:
Value* value;
MultiRead* read;
bool local;
};
class ForkState: public Compiler::State {
public:
ForkState(Stack* stack, Local* locals, Cell<Value>* saved, Event* predecessor,
unsigned logicalIp):
stack(stack),
locals(locals),
saved(saved),
predecessor(predecessor),
logicalIp(logicalIp),
readCount(0)
{ }
Stack* stack;
Local* locals;
Cell<Value>* saved;
Event* predecessor;
unsigned logicalIp;
unsigned readCount;
ForkElement elements[0];
};
class LogicalInstruction {
public:
LogicalInstruction(int index, Stack* stack, Local* locals);
LogicalInstruction* next(Context* c);
Event* firstEvent;
Event* lastEvent;
LogicalInstruction* immediatePredecessor;
Stack* stack;
Local* locals;
Promise* machineOffset;
MySubroutine* subroutine;
int index;
};
class MySubroutine: public Compiler::Subroutine {
public:
MySubroutine(): forkState(0) { }
ForkState* forkState;
};
class Block {
public:
Block(Event* head);
Event* head;
Block* nextBlock;
LogicalInstruction* nextInstruction;
Assembler::Block* assemblerBlock;
unsigned start;
};
Block* block(Context* c, Event* head);
unsigned machineOffset(Context* c, int logicalIp);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_IR_H

View File

@ -0,0 +1,116 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/context.h"
#include "codegen/compiler/promise.h"
#include "codegen/compiler/ir.h"
namespace avian {
namespace codegen {
namespace compiler {
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);
}
class IpPromise: public Promise {
public:
IpPromise(Context* c, int logicalIp):
c(c),
logicalIp(logicalIp)
{ }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<intptr_t>
(c->machineCode + machineOffset(c, logicalIp));
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0
and c->logicalCode[logicalIp]->machineOffset->resolved();
}
Context* c;
int logicalIp;
};
Promise* ipPromise(Context* c, int logicalIp) {
return new (c->zone) IpPromise(c, logicalIp);
}
class PoolPromise: public Promise {
public:
PoolPromise(Context* c, int key): c(c), key(key) { }
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<int64_t>
(c->machineCode + vm::pad(c->machineCodeSize, vm::TargetBytesPerWord)
+ (key * vm::TargetBytesPerWord));
}
abort(c);
}
virtual bool resolved() {
return c->machineCode != 0;
}
Context* c;
int key;
};
Promise* poolPromise(Context* c, int key) {
return new(c->zone) PoolPromise(c, key);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,50 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_PROMISE_H
#define AVIAN_CODEGEN_COMPILER_PROMISE_H
namespace avian {
namespace codegen {
namespace compiler {
class CodePromise: public Promise {
public:
CodePromise(Context* c, CodePromise* next);
CodePromise(Context* c, Promise* offset);
virtual int64_t value();
virtual bool resolved();
Context* c;
Promise* offset;
CodePromise* next;
};
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);
Promise* ipPromise(Context* c, int logicalIp);
Promise* poolPromise(Context* c, int key);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_PROMISE_H

View File

@ -0,0 +1,191 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/context.h"
#include "codegen/compiler/value.h"
#include "codegen/compiler/site.h"
#include "codegen/compiler/resource.h"
#include "codegen/compiler/read.h"
namespace avian {
namespace codegen {
namespace compiler {
SingleRead::SingleRead(const SiteMask& mask, Value* successor):
next_(0), mask(mask), high_(0), successor_(successor)
{ }
bool SingleRead::intersect(SiteMask* mask, unsigned) {
*mask = mask->intersectionWith(this->mask);
return true;
}
Value* SingleRead::high(Context*) {
return high_;
}
Value* SingleRead::successor() {
return successor_;
}
bool SingleRead::valid() {
return true;
}
void SingleRead::append(Context* c UNUSED, Read* r) {
assert(c, next_ == 0);
next_ = r;
}
Read* SingleRead::next(Context*) {
return next_;
}
MultiRead::MultiRead():
reads(0), lastRead(0), firstTarget(0), lastTarget(0), visited(false)
{ }
bool MultiRead::intersect(SiteMask* mask, unsigned depth) {
if (depth > 0) {
// short-circuit recursion to avoid poor performance in
// deeply-nested branches
return reads != 0;
}
bool result = false;
if (not visited) {
visited = true;
for (Cell<Read>** cell = &reads; *cell;) {
Read* r = (*cell)->value;
bool valid = r->intersect(mask, depth + 1);
if (valid) {
result = true;
cell = &((*cell)->next);
} else {
*cell = (*cell)->next;
}
}
visited = false;
}
return result;
}
Value* MultiRead::successor() {
return 0;
}
bool MultiRead::valid() {
bool result = false;
if (not visited) {
visited = true;
for (Cell<Read>** cell = &reads; *cell;) {
Read* r = (*cell)->value;
if (r->valid()) {
result = true;
cell = &((*cell)->next);
} else {
*cell = (*cell)->next;
}
}
visited = false;
}
return result;
}
void MultiRead::append(Context* c, Read* r) {
Cell<Read>* cell = cons<Read>(c, r, 0);
if (lastRead == 0) {
reads = cell;
} else {
lastRead->next = cell;
}
lastRead = cell;
// fprintf(stderr, "append %p to %p for %p\n", r, lastTarget, this);
lastTarget->value = r;
}
Read* MultiRead::next(Context* c) {
abort(c);
}
void MultiRead::allocateTarget(Context* c) {
Cell<Read>* cell = cons<Read>(c, 0, 0);
// fprintf(stderr, "allocate target for %p: %p\n", this, cell);
if (lastTarget) {
lastTarget->next = cell;
} else {
firstTarget = cell;
}
lastTarget = cell;
}
Read* MultiRead::nextTarget() {
// fprintf(stderr, "next target for %p: %p\n", this, firstTarget);
Read* r = firstTarget->value;
firstTarget = firstTarget->next;
return r;
}
StubRead::StubRead():
next_(0), read(0), visited(false), valid_(true)
{ }
bool StubRead::intersect(SiteMask* mask, unsigned depth) {
if (not visited) {
visited = true;
if (read) {
bool valid = read->intersect(mask, depth);
if (not valid) {
read = 0;
}
}
visited = false;
}
return valid_;
}
Value* StubRead::successor() {
return 0;
}
bool StubRead::valid() {
return valid_;
}
void StubRead::append(Context* c UNUSED, Read* r) {
assert(c, next_ == 0);
next_ = r;
}
Read* StubRead::next(Context*) {
return next_;
}
SingleRead* read(Context* c, const SiteMask& mask, Value* successor) {
assert(c, (mask.typeMask != 1 << lir::MemoryOperand) or mask.frameIndex >= 0);
return new(c->zone) SingleRead(mask, successor);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

125
src/codegen/compiler/read.h Normal file
View File

@ -0,0 +1,125 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_READ_H
#define AVIAN_CODEGEN_COMPILER_READ_H
namespace avian {
namespace codegen {
namespace compiler {
class Context;
class SiteMask;
class Value;
class Event;
class Read {
public:
Read():
value(0), event(0), eventNext(0)
{ }
virtual bool intersect(SiteMask* mask, unsigned depth = 0) = 0;
virtual Value* high(Context* c) { abort(c); }
virtual Value* successor() = 0;
virtual bool valid() = 0;
virtual void append(Context* c, Read* r) = 0;
virtual Read* next(Context* c) = 0;
Value* value;
Event* event;
Read* eventNext;
};
inline bool valid(Read* r) {
return r and r->valid();
}
class SingleRead: public Read {
public:
SingleRead(const SiteMask& mask, Value* successor);
virtual bool intersect(SiteMask* mask, unsigned);
virtual Value* high(Context*);
virtual Value* successor();
virtual bool valid();
virtual void append(Context* c UNUSED, Read* r);
virtual Read* next(Context*);
Read* next_;
SiteMask mask;
Value* high_;
Value* successor_;
};
class MultiRead: public Read {
public:
MultiRead();
virtual bool intersect(SiteMask* mask, unsigned depth);
virtual Value* successor();
virtual bool valid();
virtual void append(Context* c, Read* r);
virtual Read* next(Context* c);
void allocateTarget(Context* c);
Read* nextTarget();
Cell<Read>* reads;
Cell<Read>* lastRead;
Cell<Read>* firstTarget;
Cell<Read>* lastTarget;
bool visited;
};
class StubRead: public Read {
public:
StubRead();
virtual bool intersect(SiteMask* mask, unsigned depth);
virtual Value* successor();
virtual bool valid();
virtual void append(Context* c UNUSED, Read* r);
virtual Read* next(Context*);
Read* next_;
Read* read;
bool visited;
bool valid_;
};
SingleRead* read(Context* c, const SiteMask& mask, Value* successor = 0);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_READ_H

View File

@ -0,0 +1,300 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/regalloc.h"
#include "codegen/compiler/context.h"
#include "codegen/compiler/site.h"
#include "codegen/compiler/resource.h"
#include "codegen/compiler/read.h"
namespace avian {
namespace codegen {
namespace compiler {
RegisterAllocator::RegisterAllocator(Aborter* a, const RegisterFile* registerFile):
a(a),
registerFile(registerFile)
{ }
unsigned totalFrameSize(Context* c);
Read* live(Context* c UNUSED, Value* v);
unsigned
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
CostCalculator* costCalculator)
{
if (r->reserved or r->freezeCount or r->referenceCount) {
return Target::Impossible;
} else {
unsigned baseCost =
costCalculator ? costCalculator->cost(c, mask) : 0;
if (r->value) {
assert(c, r->value->findSite(r->site));
if (v and r->value->isBuddyOf(v)) {
return baseCost;
} else if (r->value->uniqueSite(c, r->site)) {
return baseCost + Target::StealUniquePenalty;
} else {
return baseCost = Target::StealPenalty;
}
} else {
return baseCost;
}
}
}
bool
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
unsigned* cost, CostCalculator* costCalculator)
{
if ((1 << i) & mask) {
RegisterResource* r = c->registerResources + i;
unsigned myCost = resourceCost
(c, v, r, SiteMask(1 << lir::RegisterOperand, 1 << i, NoFrameIndex), costCalculator)
+ Target::MinimumRegisterCost;
if ((static_cast<uint32_t>(1) << i) == mask) {
*cost = myCost;
return true;
} else if (myCost < *cost) {
*cost = myCost;
*target = i;
}
}
return false;
}
int
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
CostCalculator* costCalculator)
{
int target = lir::NoRegister;
*cost = Target::Impossible;
if (mask & c->regFile->generalRegisters.mask) {
for (int i = c->regFile->generalRegisters.limit - 1;
i >= c->regFile->generalRegisters.start; --i)
{
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
return i;
}
}
}
if (mask & c->regFile->floatRegisters.mask) {
for (int i = c->regFile->floatRegisters.start;
i < static_cast<int>(c->regFile->floatRegisters.limit); ++i)
{
if (pickRegisterTarget(c, i, v, mask, &target, cost, costCalculator)) {
return i;
}
}
}
return target;
}
Target
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
CostCalculator* costCalculator)
{
unsigned cost;
int number = pickRegisterTarget(c, v, mask, &cost, costCalculator);
return Target(number, lir::RegisterOperand, cost);
}
unsigned
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator)
{
return resourceCost
(c, v, c->frameResources + frameIndex, SiteMask(1 << lir::MemoryOperand, 0, frameIndex),
costCalculator)
+ Target::MinimumFrameCost;
}
Target
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{
Target best;
Value* p = v;
do {
if (p->home >= 0) {
Target mine
(p->home, lir::MemoryOperand, frameCost(c, v, p->home, costCalculator));
if (mine.cost == Target::MinimumFrameCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
p = p->buddy;
} while (p != v);
return best;
}
Target
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator)
{
Target best;
unsigned count = totalFrameSize(c);
for (unsigned i = 0; i < count; ++i) {
Target mine(i, lir::MemoryOperand, frameCost(c, v, i, costCalculator));
if (mine.cost == Target::MinimumFrameCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
return best;
}
Target
pickTarget(Context* c, Value* value, const SiteMask& mask,
unsigned registerPenalty, Target best,
CostCalculator* costCalculator)
{
if (mask.typeMask & (1 << lir::RegisterOperand)) {
Target mine = pickRegisterTarget
(c, value, mask.registerMask, costCalculator);
mine.cost += registerPenalty;
if (mine.cost == Target::MinimumRegisterCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
if (mask.typeMask & (1 << lir::MemoryOperand)) {
if (mask.frameIndex >= 0) {
Target mine(mask.frameIndex, lir::MemoryOperand,
frameCost(c, value, mask.frameIndex, costCalculator));
if (mine.cost == Target::MinimumFrameCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
} else if (mask.frameIndex == AnyFrameIndex) {
Target mine = pickFrameTarget(c, value, costCalculator);
if (mine.cost == Target::MinimumFrameCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
}
return best;
}
Target
pickTarget(Context* c, Read* read, bool intersectRead,
unsigned registerReserveCount, CostCalculator* costCalculator)
{
unsigned registerPenalty
= (c->availableGeneralRegisterCount > registerReserveCount
? 0 : Target::LowRegisterPenalty);
Value* value = read->value;
uint32_t registerMask
= (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask);
SiteMask mask(~0, registerMask, AnyFrameIndex);
read->intersect(&mask);
if (value->type == lir::ValueFloat) {
uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask;
if (floatMask) {
mask.registerMask = floatMask;
}
}
Target best;
Value* successor = read->successor();
if (successor) {
Read* r = live(c, successor);
if (r) {
SiteMask intersection = mask;
if (r->intersect(&intersection)) {
best = pickTarget
(c, value, intersection, registerPenalty, best, costCalculator);
if (best.cost <= Target::MinimumFrameCost) {
return best;
}
}
}
}
best = pickTarget(c, value, mask, registerPenalty, best, costCalculator);
if (best.cost <= Target::MinimumFrameCost) {
return best;
}
if (intersectRead) {
if (best.cost == Target::Impossible) {
fprintf(stderr, "mask type %d reg %d frame %d\n",
mask.typeMask, mask.registerMask, mask.frameIndex);
abort(c);
}
return best;
}
{ Target mine = pickRegisterTarget(c, value, registerMask, costCalculator);
mine.cost += registerPenalty;
if (mine.cost == Target::MinimumRegisterCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
{ Target mine = pickFrameTarget(c, value, costCalculator);
if (mine.cost == Target::MinimumFrameCost) {
return mine;
} else if (mine.cost < best.cost) {
best = mine;
}
}
if (best.cost >= Target::StealUniquePenalty
and c->availableGeneralRegisterCount == 0)
{
// there are no free registers left, so moving from memory to
// memory isn't an option - try harder to find an available frame
// site:
best = pickAnyFrameTarget(c, value, costCalculator);
assert(c, best.cost <= 3);
}
if (best.cost == Target::Impossible) {
abort(c);
}
return best;
}
} // namespace regalloc
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,106 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_REGALLOC_H
#define AVIAN_CODEGEN_COMPILER_REGALLOC_H
#include "common.h"
#include "codegen/lir.h"
#include "codegen/registers.h"
class Aborter;
namespace avian {
namespace codegen {
namespace compiler {
class Context;
class Value;
class SiteMask;
class Resource;
class Read;
class RegisterAllocator {
public:
Aborter* a;
const RegisterFile* registerFile;
RegisterAllocator(Aborter* a, const RegisterFile* registerFile);
};
class Target {
public:
static const unsigned MinimumRegisterCost = 0;
static const unsigned MinimumFrameCost = 1;
static const unsigned StealPenalty = 2;
static const unsigned StealUniquePenalty = 4;
static const unsigned IndirectMovePenalty = 4;
static const unsigned LowRegisterPenalty = 10;
static const unsigned Impossible = 20;
Target(): cost(Impossible) { }
Target(int index, lir::OperandType type, unsigned cost):
index(index), type(type), cost(cost)
{ }
int16_t index;
lir::OperandType type;
uint8_t cost;
};
class CostCalculator {
public:
virtual unsigned cost(Context* c, SiteMask mask) = 0;
};
unsigned
resourceCost(Context* c, Value* v, Resource* r, SiteMask mask,
CostCalculator* costCalculator);
bool
pickRegisterTarget(Context* c, int i, Value* v, uint32_t mask, int* target,
unsigned* cost, CostCalculator* costCalculator = 0);
int
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost,
CostCalculator* costCalculator = 0);
Target
pickRegisterTarget(Context* c, Value* v, uint32_t mask,
CostCalculator* costCalculator = 0);
unsigned
frameCost(Context* c, Value* v, int frameIndex, CostCalculator* costCalculator);
Target
pickFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
Target
pickAnyFrameTarget(Context* c, Value* v, CostCalculator* costCalculator);
Target
pickTarget(Context* c, Value* value, const SiteMask& mask,
unsigned registerPenalty, Target best,
CostCalculator* costCalculator);
Target
pickTarget(Context* c, Read* read, bool intersectRead,
unsigned registerReserveCount, CostCalculator* costCalculator);
} // namespace regalloc
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_REGALLOC_H

View File

@ -0,0 +1,226 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "codegen/compiler/context.h"
#include "codegen/compiler/resource.h"
#include "codegen/compiler/value.h"
namespace avian {
namespace codegen {
namespace compiler {
const bool DebugResources = false;
void steal(Context* c, Resource* r, Value* thief);
void decrementAvailableGeneralRegisterCount(Context* c) {
assert(c, c->availableGeneralRegisterCount);
-- c->availableGeneralRegisterCount;
if (DebugResources) {
fprintf(stderr, "%d registers available\n",
c->availableGeneralRegisterCount);
}
}
void incrementAvailableGeneralRegisterCount(Context* c) {
++ c->availableGeneralRegisterCount;
if (DebugResources) {
fprintf(stderr, "%d registers available\n",
c->availableGeneralRegisterCount);
}
}
void freezeResource(Context* c, Resource* r, Value* v) {
if (DebugResources) {
char buffer[256]; r->toString(c, buffer, 256);
fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1);
}
++ r->freezeCount;
}
void thawResource(Context* c, Resource* r, Value* v) {
if (not r->reserved) {
if (DebugResources) {
char buffer[256]; r->toString(c, buffer, 256);
fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1);
}
assert(c, r->freezeCount);
-- r->freezeCount;
}
}
Resource::Resource(bool reserved):
value(0), site(0), previousAcquired(0), nextAcquired(0), freezeCount(0),
referenceCount(0), reserved(reserved)
{ }
RegisterResource::RegisterResource(bool reserved):
Resource(reserved)
{ }
void RegisterResource::freeze(Context* c, Value* v) {
if (not reserved) {
freezeResource(c, this, v);
if (freezeCount == 1
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
decrementAvailableGeneralRegisterCount(c);
}
}
}
void RegisterResource::thaw(Context* c, Value* v) {
if (not reserved) {
thawResource(c, this, v);
if (freezeCount == 0
and ((1 << index(c)) & c->regFile->generalRegisters.mask))
{
incrementAvailableGeneralRegisterCount(c);
}
}
}
unsigned RegisterResource::toString(Context* c, char* buffer, unsigned bufferSize) {
return vm::snprintf(buffer, bufferSize, "register %d", index(c));
}
unsigned RegisterResource::index(Context* c) {
return this - c->registerResources;
}
void RegisterResource::increment(Context* c) {
if (not this->reserved) {
if (DebugResources) {
char buffer[256]; this->toString(c, buffer, 256);
fprintf(stderr, "increment %s to %d\n", buffer, this->referenceCount + 1);
}
++ this->referenceCount;
if (this->referenceCount == 1
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
{
decrementAvailableGeneralRegisterCount(c);
}
}
}
void RegisterResource::decrement(Context* c) {
if (not this->reserved) {
if (DebugResources) {
char buffer[256]; this->toString(c, buffer, 256);
fprintf(stderr, "decrement %s to %d\n", buffer, this->referenceCount - 1);
}
assert(c, this->referenceCount > 0);
-- this->referenceCount;
if (this->referenceCount == 0
and ((1 << this->index(c)) & c->regFile->generalRegisters.mask))
{
incrementAvailableGeneralRegisterCount(c);
}
}
}
void FrameResource::freeze(Context* c, Value* v) {
freezeResource(c, this, v);
}
void FrameResource::thaw(Context* c, Value* v) {
thawResource(c, this, v);
}
unsigned FrameResource::toString(Context* c, char* buffer, unsigned bufferSize) {
return vm::snprintf(buffer, bufferSize, "frame %d", index(c));
}
unsigned FrameResource::index(Context* c) {
return this - c->frameResources;
}
void acquire(Context* c, Resource* resource, Value* value, Site* site) {
assert(c, value);
assert(c, site);
if (not resource->reserved) {
if (DebugResources) {
char buffer[256]; resource->toString(c, buffer, 256);
fprintf(stderr, "%p acquire %s\n", value, buffer);
}
if (resource->value) {
assert(c, resource->value->findSite(resource->site));
assert(c, not value->findSite(resource->site));
steal(c, resource, value);
}
if (c->acquiredResources) {
c->acquiredResources->previousAcquired = resource;
resource->nextAcquired = c->acquiredResources;
}
c->acquiredResources = resource;
resource->value = value;
resource->site = site;
}
}
void release(Context* c, Resource* resource, Value* value UNUSED, Site* site UNUSED) {
if (not resource->reserved) {
if (DebugResources) {
char buffer[256]; resource->toString(c, buffer, 256);
fprintf(stderr, "%p release %s\n", resource->value, buffer);
}
assert(c, resource->value);
assert(c, resource->site);
assert(c, resource->value->isBuddyOf(value));
assert(c, site == resource->site);
Resource* next = resource->nextAcquired;
if (next) {
next->previousAcquired = resource->previousAcquired;
resource->nextAcquired = 0;
}
Resource* previous = resource->previousAcquired;
if (previous) {
previous->nextAcquired = next;
resource->previousAcquired = 0;
} else {
assert(c, c->acquiredResources == resource);
c->acquiredResources = next;
}
resource->value = 0;
resource->site = 0;
}
}
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,77 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_RESOURCE_H
#define AVIAN_CODEGEN_COMPILER_RESOURCE_H
namespace avian {
namespace codegen {
namespace compiler {
class Context;
class Value;
class Site;
class Resource {
public:
Resource(bool reserved = false);
virtual void freeze(Context*, Value*) = 0;
virtual void thaw(Context*, Value*) = 0;
virtual unsigned toString(Context*, char*, unsigned) = 0;
Value* value;
Site* site;
Resource* previousAcquired;
Resource* nextAcquired;
uint8_t freezeCount;
uint8_t referenceCount;
bool reserved;
};
class RegisterResource: public Resource {
public:
RegisterResource(bool reserved);
virtual void freeze(Context*, Value*);
virtual void thaw(Context*, Value*);
virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize);
virtual unsigned index(Context*);
void increment(Context*);
void decrement(Context*);
};
class FrameResource: public Resource {
public:
virtual void freeze(Context*, Value*);
virtual void thaw(Context*, Value*);
virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize);
virtual unsigned index(Context*);
};
void acquire(Context* c, Resource* resource, Value* value, Site* site);
void release(Context* c, Resource* resource, Value* value, Site* site);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_RESOURCE_H

View File

@ -0,0 +1,628 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/context.h"
#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 {
int intersectFrameIndexes(int a, int b) {
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
if (a == AnyFrameIndex) return b;
if (b == AnyFrameIndex) return a;
if (a == b) return a;
return NoFrameIndex;
}
SiteMask SiteMask::intersectionWith(const SiteMask& b) {
return SiteMask(typeMask & b.typeMask, registerMask & b.registerMask,
intersectFrameIndexes(frameIndex, b.frameIndex));
}
SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
bool includeNextWord):
c(c),
originalValue(v),
currentValue(v),
includeBuddies(includeBuddies),
includeNextWord(includeNextWord),
pass(0),
next_(findNext(&(v->sites))),
previous(0)
{ }
Site** SiteIterator::findNext(Site** p) {
while (true) {
if (*p) {
if (pass == 0 or (*p)->registerSize(c) > vm::TargetBytesPerWord) {
return p;
} else {
p = &((*p)->next);
}
} else {
if (includeBuddies) {
Value* v = currentValue->buddy;
if (v != originalValue) {
currentValue = v;
p = &(v->sites);
continue;
}
}
if (includeNextWord and pass == 0) {
Value* v = originalValue->nextWord;
if (v != originalValue) {
pass = 1;
originalValue = v;
currentValue = v;
p = &(v->sites);
continue;
}
}
return 0;
}
}
}
bool SiteIterator::hasMore() {
if (previous) {
next_ = findNext(&((*previous)->next));
previous = 0;
}
return next_ != 0;
}
Site* SiteIterator::next() {
previous = next_;
return *previous;
}
void SiteIterator::remove(Context* c) {
(*previous)->release(c, originalValue);
*previous = (*previous)->next;
next_ = findNext(previous);
previous = 0;
}
unsigned Site::registerSize(Context*) {
return vm::TargetBytesPerWord;
}
Site* constantSite(Context* c, Promise* value) {
return new(c->zone) ConstantSite(value);
}
Site* constantSite(Context* c, int64_t value) {
return constantSite(c, resolvedPromise(c, value));
}
class AddressSite: public Site {
public:
AddressSite(Promise* address): address(address) { }
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
if (address->resolved()) {
return vm::snprintf
(buffer, bufferSize, "address %" LLD, address->value());
} else {
return vm::snprintf(buffer, bufferSize, "address unresolved");
}
}
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : AddressCopyCost);
}
virtual bool match(Context*, const SiteMask& mask) {
return mask.typeMask & (1 << lir::AddressOperand);
}
virtual bool loneMatch(Context*, const SiteMask&) {
return false;
}
virtual bool matchNextWord(Context* c, Site*, unsigned) {
abort(c);
}
virtual lir::OperandType type(Context*) {
return lir::AddressOperand;
}
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
lir::Operand* result)
{
assert(c, high == this);
new (result) lir::Address(address);
}
virtual Site* copy(Context* c) {
return addressSite(c, address);
}
virtual Site* copyLow(Context* c) {
abort(c);
}
virtual Site* copyHigh(Context* c) {
abort(c);
}
virtual Site* makeNextWord(Context* c, unsigned) {
abort(c);
}
virtual SiteMask mask(Context*) {
return SiteMask(1 << lir::AddressOperand, 0, NoFrameIndex);
}
virtual SiteMask nextWordMask(Context* c, unsigned) {
abort(c);
}
Promise* address;
};
Site* addressSite(Context* c, Promise* address) {
return new(c->zone) AddressSite(address);
}
RegisterSite::RegisterSite(uint32_t mask, int number):
mask_(mask), number(number)
{ }
unsigned RegisterSite::toString(Context*, char* buffer, unsigned bufferSize) {
if (number != lir::NoRegister) {
return vm::snprintf(buffer, bufferSize, "%p register %d", this, number);
} else {
return vm::snprintf(buffer, bufferSize,
"%p register unacquired (mask %d)", this, mask_);
}
}
unsigned RegisterSite::copyCost(Context* c, Site* s) {
assert(c, number != lir::NoRegister);
if (s and
(this == s or
(s->type(c) == lir::RegisterOperand
and (static_cast<RegisterSite*>(s)->mask_ & (1 << number)))))
{
return 0;
} else {
return RegisterCopyCost;
}
}
bool RegisterSite::match(Context* c UNUSED, const SiteMask& mask) {
assert(c, number != lir::NoRegister);
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
return ((static_cast<uint64_t>(1) << number) & mask.registerMask);
} else {
return false;
}
}
bool RegisterSite::loneMatch(Context* c UNUSED, const SiteMask& mask) {
assert(c, number != lir::NoRegister);
if ((mask.typeMask & (1 << lir::RegisterOperand))) {
return ((static_cast<uint64_t>(1) << number) == mask.registerMask);
} else {
return false;
}
}
bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
assert(c, number != lir::NoRegister);
if (s->type(c) != lir::RegisterOperand) {
return false;
}
RegisterSite* rs = static_cast<RegisterSite*>(s);
unsigned size = rs->registerSize(c);
if (size > vm::TargetBytesPerWord) {
assert(c, number != lir::NoRegister);
return number == rs->number;
} else {
uint32_t mask = c->regFile->generalRegisters.mask;
return ((1 << number) & mask) and ((1 << rs->number) & mask);
}
}
void RegisterSite::acquire(Context* c, Value* v) {
Target target;
if (number != lir::NoRegister) {
target = Target(number, lir::RegisterOperand, 0);
} else {
target = pickRegisterTarget(c, v, mask_);
expect(c, target.cost < Target::Impossible);
}
RegisterResource* resource = c->registerResources + target.index;
compiler::acquire(c, resource, v, this);
number = target.index;
}
void RegisterSite::release(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
compiler::release(c, c->registerResources + number, v, this);
}
void RegisterSite::freeze(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
c->registerResources[number].freeze(c, v);
}
void RegisterSite::thaw(Context* c, Value* v) {
assert(c, number != lir::NoRegister);
c->registerResources[number].thaw(c, v);
}
bool RegisterSite::frozen(Context* c UNUSED) {
assert(c, number != lir::NoRegister);
return c->registerResources[number].freezeCount != 0;
}
lir::OperandType RegisterSite::type(Context*) {
return lir::RegisterOperand;
}
void RegisterSite::asAssemblerOperand(Context* c UNUSED, Site* high,
lir::Operand* result)
{
assert(c, number != lir::NoRegister);
int highNumber;
if (high != this) {
highNumber = static_cast<RegisterSite*>(high)->number;
assert(c, highNumber != lir::NoRegister);
} else {
highNumber = lir::NoRegister;
}
new (result) lir::Register(number, highNumber);
}
Site* RegisterSite::copy(Context* c) {
uint32_t mask;
if (number != lir::NoRegister) {
mask = 1 << number;
} else {
mask = mask_;
}
return freeRegisterSite(c, mask);
}
Site* RegisterSite::copyLow(Context* c) {
abort(c);
}
Site* RegisterSite::copyHigh(Context* c) {
abort(c);
}
Site* RegisterSite::makeNextWord(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
assert(c, ((1 << number) & c->regFile->generalRegisters.mask));
return freeRegisterSite(c, c->regFile->generalRegisters.mask);
}
SiteMask RegisterSite::mask(Context* c UNUSED) {
return SiteMask(1 << lir::RegisterOperand, mask_, NoFrameIndex);
}
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
if (registerSize(c) > vm::TargetBytesPerWord) {
return SiteMask
(1 << lir::RegisterOperand, number, NoFrameIndex);
} else {
return SiteMask
(1 << lir::RegisterOperand, c->regFile->generalRegisters.mask, NoFrameIndex);
}
}
unsigned RegisterSite::registerSize(Context* c) {
assert(c, number != lir::NoRegister);
if ((1 << number) & c->regFile->floatRegisters.mask) {
return c->arch->floatRegisterSize();
} else {
return vm::TargetBytesPerWord;
}
}
unsigned RegisterSite::registerMask(Context* c UNUSED) {
assert(c, number != lir::NoRegister);
return 1 << number;
}
Site* registerSite(Context* c, int number) {
assert(c, number >= 0);
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
| c->regFile->floatRegisters.mask));
return new(c->zone) RegisterSite(1 << number, number);
}
Site* freeRegisterSite(Context* c, uint32_t mask) {
return new(c->zone) RegisterSite(mask, lir::NoRegister);
}
MemorySite::MemorySite(int base, int offset, int index, unsigned scale):
acquired(false), base(base), offset(offset), index(index), scale(scale)
{ }
unsigned MemorySite::toString(Context*, char* buffer, unsigned bufferSize) {
if (acquired) {
return vm::snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
base, offset, index, scale);
} else {
return vm::snprintf(buffer, bufferSize, "memory unacquired");
}
}
unsigned MemorySite::copyCost(Context* c, Site* s) {
assert(c, acquired);
if (s and
(this == s or
(s->type(c) == lir::MemoryOperand
and static_cast<MemorySite*>(s)->base == base
and static_cast<MemorySite*>(s)->offset == offset
and static_cast<MemorySite*>(s)->index == index
and static_cast<MemorySite*>(s)->scale == scale)))
{
return 0;
} else {
return MemoryCopyCost;
}
}
bool MemorySite::conflicts(const SiteMask& mask) {
return (mask.typeMask & (1 << lir::RegisterOperand)) != 0
and (((1 << base) & mask.registerMask) == 0
or (index != lir::NoRegister
and ((1 << index) & mask.registerMask) == 0));
}
bool MemorySite::match(Context* c, const SiteMask& mask) {
assert(c, acquired);
if (mask.typeMask & (1 << lir::MemoryOperand)) {
if (mask.frameIndex >= 0) {
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
return static_cast<int>(frameIndexToOffset(c, mask.frameIndex))
== offset;
} else {
return false;
}
} else {
return true;
}
} else {
return false;
}
}
bool MemorySite::loneMatch(Context* c, const SiteMask& mask) {
assert(c, acquired);
if (mask.typeMask & (1 << lir::MemoryOperand)) {
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
if (mask.frameIndex == AnyFrameIndex) {
return false;
} else {
return true;
}
}
}
return false;
}
bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
if (s->type(c) == lir::MemoryOperand) {
MemorySite* ms = static_cast<MemorySite*>(s);
return ms->base == this->base
and ((index == 1 and ms->offset == static_cast<int>
(this->offset + vm::TargetBytesPerWord))
or (index == 0 and this->offset == static_cast<int>
(ms->offset + vm::TargetBytesPerWord)))
and ms->index == this->index
and ms->scale == this->scale;
} else {
return false;
}
}
void MemorySite::acquire(Context* c, Value* v) {
c->registerResources[base].increment(c);
if (index != lir::NoRegister) {
c->registerResources[index].increment(c);
}
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assert
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
compiler::acquire
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
}
acquired = true;
}
void MemorySite::release(Context* c, Value* v) {
if (base == c->arch->stack()) {
assert(c, index == lir::NoRegister);
assert
(c, not c->frameResources[offsetToFrameIndex(c, offset)].reserved);
compiler::release
(c, c->frameResources + offsetToFrameIndex(c, offset), v, this);
}
c->registerResources[base].decrement(c);
if (index != lir::NoRegister) {
c->registerResources[index].decrement(c);
}
acquired = false;
}
void MemorySite::freeze(Context* c, Value* v) {
if (base == c->arch->stack()) {
c->frameResources[offsetToFrameIndex(c, offset)].freeze(c, v);
} else {
c->registerResources[base].increment(c);
if (index != lir::NoRegister) {
c->registerResources[index].increment(c);
}
}
}
void MemorySite::thaw(Context* c, Value* v) {
if (base == c->arch->stack()) {
c->frameResources[offsetToFrameIndex(c, offset)].thaw(c, v);
} else {
c->registerResources[base].decrement(c);
if (index != lir::NoRegister) {
c->registerResources[index].decrement(c);
}
}
}
bool MemorySite::frozen(Context* c) {
return base == c->arch->stack()
and c->frameResources[offsetToFrameIndex(c, offset)].freezeCount != 0;
}
lir::OperandType MemorySite::type(Context*) {
return lir::MemoryOperand;
}
void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
lir::Operand* result)
{
// todo: endianness?
assert(c, high == this
or (static_cast<MemorySite*>(high)->base == base
and static_cast<MemorySite*>(high)->offset
== static_cast<int>(offset + vm::TargetBytesPerWord)
and static_cast<MemorySite*>(high)->index == index
and static_cast<MemorySite*>(high)->scale == scale));
assert(c, acquired);
new (result) lir::Memory(base, offset, index, scale);
}
Site* MemorySite::copy(Context* c) {
return memorySite(c, base, offset, index, scale);
}
Site* MemorySite::copyHalf(Context* c, bool add) {
if (add) {
return memorySite(c, base, offset + vm::TargetBytesPerWord, index, scale);
} else {
return copy(c);
}
}
Site* MemorySite::copyLow(Context* c) {
return copyHalf(c, c->arch->bigEndian());
}
Site* MemorySite::copyHigh(Context* c) {
return copyHalf(c, not c->arch->bigEndian());
}
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
return memorySite
(c, base, offset + ((index == 1) xor c->arch->bigEndian()
? vm::TargetBytesPerWord : -vm::TargetBytesPerWord),
this->index, scale);
}
SiteMask MemorySite::mask(Context* c) {
return SiteMask(1 << lir::MemoryOperand, 0, (base == c->arch->stack())
? static_cast<int>(offsetToFrameIndex(c, offset))
: NoFrameIndex);
}
SiteMask MemorySite::nextWordMask(Context* c, unsigned index) {
int frameIndex;
if (base == c->arch->stack()) {
assert(c, this->index == lir::NoRegister);
frameIndex = static_cast<int>(offsetToFrameIndex(c, offset))
+ ((index == 1) xor c->arch->bigEndian() ? 1 : -1);
} else {
frameIndex = NoFrameIndex;
}
return SiteMask(1 << lir::MemoryOperand, 0, frameIndex);
}
bool MemorySite::isVolatile(Context* c) {
return base != c->arch->stack();
}
MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) {
return new(c->zone) MemorySite(base, offset, index, scale);
}
MemorySite* frameSite(Context* c, int frameIndex) {
assert(c, frameIndex >= 0);
return memorySite
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex), lir::NoRegister, 0);
}
} // namespace compiler
} // namespace codegen
} // namespace avian

311
src/codegen/compiler/site.h Normal file
View File

@ -0,0 +1,311 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_SITE_H
#define AVIAN_CODEGEN_COMPILER_SITE_H
#include "codegen/compiler/value.h"
#include "codegen/compiler/context.h"
namespace avian {
namespace codegen {
namespace compiler {
class Context;
const unsigned RegisterCopyCost = 1;
const unsigned AddressCopyCost = 2;
const unsigned ConstantCopyCost = 3;
const unsigned MemoryCopyCost = 4;
const unsigned CopyPenalty = 10;
class SiteMask {
public:
SiteMask(): typeMask(~0), registerMask(~0), frameIndex(AnyFrameIndex) { }
SiteMask(uint8_t typeMask, uint32_t registerMask, int frameIndex):
typeMask(typeMask), registerMask(registerMask), frameIndex(frameIndex)
{ }
SiteMask intersectionWith(const SiteMask& b);
static SiteMask fixedRegisterMask(int number) {
return SiteMask(1 << lir::RegisterOperand, 1 << number, NoFrameIndex);
}
uint8_t typeMask;
uint32_t registerMask;
int frameIndex;
};
class Site {
public:
Site(): next(0) { }
virtual Site* readTarget(Context*, Read*) { return this; }
virtual unsigned toString(Context*, char*, unsigned) = 0;
virtual unsigned copyCost(Context*, Site*) = 0;
virtual bool match(Context*, const SiteMask&) = 0;
virtual bool loneMatch(Context*, const SiteMask&) = 0;
virtual bool matchNextWord(Context*, Site*, unsigned) = 0;
virtual void acquire(Context*, Value*) { }
virtual void release(Context*, Value*) { }
virtual void freeze(Context*, Value*) { }
virtual void thaw(Context*, Value*) { }
virtual bool frozen(Context*) { return false; }
virtual lir::OperandType type(Context*) = 0;
virtual void asAssemblerOperand(Context*, Site*, lir::Operand*) = 0;
virtual Site* copy(Context*) = 0;
virtual Site* copyLow(Context*) = 0;
virtual Site* copyHigh(Context*) = 0;
virtual Site* makeNextWord(Context*, unsigned) = 0;
virtual SiteMask mask(Context*) = 0;
virtual SiteMask nextWordMask(Context*, unsigned) = 0;
virtual unsigned registerSize(Context*);
virtual unsigned registerMask(Context*) { return 0; }
virtual bool isVolatile(Context*) { return false; }
Site* next;
};
class SiteIterator {
public:
SiteIterator(Context* c, Value* v, bool includeBuddies = true,
bool includeNextWord = true);
Site** findNext(Site** p);
bool hasMore();
Site* next();
void remove(Context* c);
Context* c;
Value* originalValue;
Value* currentValue;
bool includeBuddies;
bool includeNextWord;
uint8_t pass;
Site** next_;
Site** previous;
};
Site* constantSite(Context* c, Promise* value);
Site* constantSite(Context* c, int64_t value);
Promise* combinedPromise(Context* c, Promise* low, Promise* high);
Promise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask);
class ConstantSite: public Site {
public:
ConstantSite(Promise* value): value(value) { }
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
if (value->resolved()) {
return vm::snprintf
(buffer, bufferSize, "constant %" LLD, value->value());
} else {
return vm::snprintf(buffer, bufferSize, "constant unresolved");
}
}
virtual unsigned copyCost(Context*, Site* s) {
return (s == this ? 0 : ConstantCopyCost);
}
virtual bool match(Context*, const SiteMask& mask) {
return mask.typeMask & (1 << lir::ConstantOperand);
}
virtual bool loneMatch(Context*, const SiteMask&) {
return true;
}
virtual bool matchNextWord(Context* c, Site* s, unsigned) {
return s->type(c) == lir::ConstantOperand;
}
virtual lir::OperandType type(Context*) {
return lir::ConstantOperand;
}
virtual void asAssemblerOperand(Context* c, Site* high,
lir::Operand* result)
{
Promise* v = value;
if (high != this) {
v = combinedPromise(c, value, static_cast<ConstantSite*>(high)->value);
}
new (result) lir::Constant(v);
}
virtual Site* copy(Context* c) {
return constantSite(c, value);
}
virtual Site* copyLow(Context* c) {
return constantSite(c, shiftMaskPromise(c, value, 0, 0xFFFFFFFF));
}
virtual Site* copyHigh(Context* c) {
return constantSite(c, shiftMaskPromise(c, value, 32, 0xFFFFFFFF));
}
virtual Site* makeNextWord(Context* c, unsigned) {
abort(c);
}
virtual SiteMask mask(Context*) {
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
}
virtual SiteMask nextWordMask(Context*, unsigned) {
return SiteMask(1 << lir::ConstantOperand, 0, NoFrameIndex);
}
Promise* value;
};
Site* addressSite(Context* c, Promise* address);
class RegisterSite: public Site {
public:
RegisterSite(uint32_t mask, int number);
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize);
virtual unsigned copyCost(Context* c, Site* s);
virtual bool match(Context* c UNUSED, const SiteMask& mask);
virtual bool loneMatch(Context* c UNUSED, const SiteMask& mask);
virtual bool matchNextWord(Context* c, Site* s, unsigned);
virtual void acquire(Context* c, Value* v);
virtual void release(Context* c, Value* v);
virtual void freeze(Context* c, Value* v);
virtual void thaw(Context* c, Value* v);
virtual bool frozen(Context* c UNUSED);
virtual lir::OperandType type(Context*);
virtual void asAssemblerOperand(Context* c UNUSED, Site* high,
lir::Operand* result);
virtual Site* copy(Context* c);
virtual Site* copyLow(Context* c);
virtual Site* copyHigh(Context* c);
virtual Site* makeNextWord(Context* c, unsigned);
virtual SiteMask mask(Context* c UNUSED);
virtual SiteMask nextWordMask(Context* c, unsigned);
virtual unsigned registerSize(Context* c);
virtual unsigned registerMask(Context* c UNUSED);
uint32_t mask_;
int number;
};
Site* registerSite(Context* c, int number);
Site* freeRegisterSite(Context* c, uint32_t mask);
class MemorySite: public Site {
public:
MemorySite(int base, int offset, int index, unsigned scale);
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize);
virtual unsigned copyCost(Context* c, Site* s);
bool conflicts(const SiteMask& mask);
virtual bool match(Context* c, const SiteMask& mask);
virtual bool loneMatch(Context* c, const SiteMask& mask);
virtual bool matchNextWord(Context* c, Site* s, unsigned index);
virtual void acquire(Context* c, Value* v);
virtual void release(Context* c, Value* v);
virtual void freeze(Context* c, Value* v);
virtual void thaw(Context* c, Value* v);
virtual bool frozen(Context* c);
virtual lir::OperandType type(Context*);
virtual void asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
lir::Operand* result);
virtual Site* copy(Context* c);
Site* copyHalf(Context* c, bool add);
virtual Site* copyLow(Context* c);
virtual Site* copyHigh(Context* c);
virtual Site* makeNextWord(Context* c, unsigned index);
virtual SiteMask mask(Context* c);
virtual SiteMask nextWordMask(Context* c, unsigned index);
virtual bool isVolatile(Context* c);
bool acquired;
int base;
int offset;
int index;
unsigned scale;
};
MemorySite* memorySite(Context* c, int base, int offset = 0, int index = lir::NoRegister, unsigned scale = 1);
MemorySite* frameSite(Context* c, int frameIndex);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_SITE_H

View File

@ -0,0 +1,164 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "target.h"
#include "codegen/compiler/regalloc.h"
#include "codegen/compiler/site.h"
namespace avian {
namespace codegen {
namespace compiler {
Value::Value(Site* site, Site* target, lir::ValueType type):
reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this),
nextWord(this), home(NoFrameIndex), type(type), wordIndex(0)
{ }
bool Value::findSite(Site* site) {
for (Site* s = this->sites; s; s = s->next) {
if (s == site) return true;
}
return false;
}
bool Value::isBuddyOf(Value* b) {
Value* a = this;
if (a == b) return true;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) return true;
}
return false;
}
void Value::addSite(Context* c, Site* s) {
if (not this->findSite(s)) {
if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "add site %s to %p\n", buffer, this);
}
s->acquire(c, this);
s->next = this->sites;
this->sites = s;
}
}
void Value::grow(Context* c) {
assert(c, this->nextWord == this);
Value* next = value(c, this->type);
this->nextWord = next;
next->nextWord = this;
next->wordIndex = 1;
}
void Value::maybeSplit(Context* c) {
if (this->nextWord == this) {
this->split(c);
}
}
void Value::split(Context* c) {
this->grow(c);
for (SiteIterator it(c, this); it.hasMore();) {
Site* s = it.next();
this->removeSite(c, s);
this->addSite(c, s->copyLow(c));
this->nextWord->addSite(c, s->copyHigh(c));
}
}
void Value::removeSite(Context* c, Site* s) {
for (SiteIterator it(c, this); it.hasMore();) {
if (s == it.next()) {
if (DebugSites) {
char buffer[256]; s->toString(c, buffer, 256);
fprintf(stderr, "remove site %s from %p\n", buffer, this);
}
it.remove(c);
break;
}
}
if (DebugSites) {
fprintf(stderr, "%p has more: %d\n", this, this->hasSite(c));
}
assert(c, not this->findSite(s));
}
bool Value::hasSite(Context* c) {
SiteIterator it(c, this);
return it.hasMore();
}
bool Value::uniqueSite(Context* c, Site* s) {
SiteIterator it(c, this);
Site* p UNUSED = it.next();
if (it.hasMore()) {
// the site is not this word's only site, but if the site is
// shared with the next word, it may be that word's only site
if (this->nextWord != this and s->registerSize(c) > vm::TargetBytesPerWord) {
SiteIterator nit(c, this->nextWord);
Site* p = nit.next();
if (nit.hasMore()) {
return false;
} else {
return p == s;
}
} else {
return false;
}
} else {
assert(c, p == s);
return true;
}
}
void Value::clearSites(Context* c) {
if (DebugSites) {
fprintf(stderr, "clear sites for %p\n", this);
}
for (SiteIterator it(c, this); it.hasMore();) {
it.next();
it.remove(c);
}
}
#ifndef NDEBUG
bool Value::hasBuddy(Context* c, Value* b) {
Value* a = this;
if (a == b) {
return true;
}
int i = 0;
for (Value* p = a->buddy; p != a; p = p->buddy) {
if (p == b) {
return true;
}
if (++i > 1000) {
abort(c);
}
}
return false;
}
#endif // not NDEBUG
Value* value(Context* c, lir::ValueType type, Site* site, Site* target) {
return new(c->zone) Value(site, target, type);
}
} // namespace regalloc
} // namespace codegen
} // namespace avian

View File

@ -0,0 +1,78 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_COMPILER_VALUE_H
#define AVIAN_CODEGEN_COMPILER_VALUE_H
#include "codegen/lir.h"
#include "codegen/compiler.h"
namespace avian {
namespace codegen {
namespace compiler {
class Read;
class Site;
const int AnyFrameIndex = -2;
const int NoFrameIndex = -1;
const bool DebugSites = false;
class Value: public Compiler::Operand {
public:
Read* reads;
Read* lastRead;
Site* sites;
Site* source;
Site* target;
Value* buddy;
Value* nextWord;
int16_t home;
lir::ValueType type;
uint8_t wordIndex;
Value(Site* site, Site* target, lir::ValueType type);
bool findSite(Site* site);
bool isBuddyOf(Value* b);
void addSite(Context* c, Site* s);
void grow(Context* c);
void maybeSplit(Context* c);
void split(Context* c);
void removeSite(Context* c, Site* s);
bool hasSite(Context* c);
bool uniqueSite(Context* c, Site* s);
void clearSites(Context* c);
#ifndef NDEBUG
bool hasBuddy(Context* c, Value* b);
#endif // not NDEBUG
};
Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0);
} // namespace compiler
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_COMPILER_VALUE_H

View File

@ -0,0 +1,62 @@
LIR_OP_0(Return)
LIR_OP_0(LoadBarrier)
LIR_OP_0(StoreStoreBarrier)
LIR_OP_0(StoreLoadBarrier)
LIR_OP_0(Trap)
LIR_OP_1(Call)
LIR_OP_1(LongCall)
LIR_OP_1(AlignedLongCall)
LIR_OP_1(AlignedCall)
LIR_OP_1(Jump)
LIR_OP_1(LongJump)
LIR_OP_1(AlignedLongJump)
LIR_OP_1(AlignedJump)
LIR_OP_2(Move)
LIR_OP_2(MoveLow)
LIR_OP_2(MoveHigh)
LIR_OP_2(MoveZ)
LIR_OP_2(Negate)
LIR_OP_2(FloatNegate)
LIR_OP_2(Float2Float)
LIR_OP_2(Float2Int)
LIR_OP_2(Int2Float)
LIR_OP_2(FloatSquareRoot)
LIR_OP_2(FloatAbsolute)
LIR_OP_2(Absolute)
LIR_OP_3(Add)
LIR_OP_3(Subtract)
LIR_OP_3(Multiply)
LIR_OP_3(Divide)
LIR_OP_3(Remainder)
LIR_OP_3(ShiftLeft)
LIR_OP_3(ShiftRight)
LIR_OP_3(UnsignedShiftRight)
LIR_OP_3(And)
LIR_OP_3(Or)
LIR_OP_3(Xor)
LIR_OP_3(FloatAdd)
LIR_OP_3(FloatSubtract)
LIR_OP_3(FloatMultiply)
LIR_OP_3(FloatDivide)
LIR_OP_3(FloatRemainder)
LIR_OP_3(FloatMax)
LIR_OP_3(FloatMin)
LIR_OP_3(JumpIfLess)
LIR_OP_3(JumpIfGreater)
LIR_OP_3(JumpIfLessOrEqual)
LIR_OP_3(JumpIfGreaterOrEqual)
LIR_OP_3(JumpIfEqual)
LIR_OP_3(JumpIfNotEqual)
LIR_OP_3(JumpIfFloatEqual)
LIR_OP_3(JumpIfFloatNotEqual)
LIR_OP_3(JumpIfFloatLess)
LIR_OP_3(JumpIfFloatGreater)
LIR_OP_3(JumpIfFloatLessOrEqual)
LIR_OP_3(JumpIfFloatGreaterOrEqual)
LIR_OP_3(JumpIfFloatLessOrUnordered)
LIR_OP_3(JumpIfFloatGreaterOrUnordered)
LIR_OP_3(JumpIfFloatLessOrEqualOrUnordered)
LIR_OP_3(JumpIfFloatGreaterOrEqualOrUnordered)

35
src/codegen/lir.cpp Normal file
View File

@ -0,0 +1,35 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "lir.h"
namespace {
const char* lirOpcodeNames[] = {
#define LIR_OP_0(x) #x
#define LIR_OP_1(x) #x
#define LIR_OP_2(x) #x
#define LIR_OP_3(x) #x
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
};
}
namespace vm {
const char* LirInstr::opcodeName(Opcode op) {
return lirOpcodeNames[op];
}
}

174
src/codegen/lir.h Normal file
View File

@ -0,0 +1,174 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_LIR_H
#define AVIAN_CODEGEN_LIR_H
namespace avian {
namespace codegen {
class Promise;
namespace lir {
enum Operation {
#define LIR_OP_0(x) x,
#define LIR_OP_1(x)
#define LIR_OP_2(x)
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
};
const unsigned OperationCount = Trap + 1;
enum UnaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x) x,
#define LIR_OP_2(x)
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoUnaryOperation = -1
};
const unsigned UnaryOperationCount = AlignedJump + 1;
enum BinaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x)
#define LIR_OP_2(x) x,
#define LIR_OP_3(x)
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoBinaryOperation = -1
};
const unsigned BinaryOperationCount = Absolute + 1;
enum TernaryOperation {
#define LIR_OP_0(x)
#define LIR_OP_1(x)
#define LIR_OP_2(x)
#define LIR_OP_3(x) x,
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
NoTernaryOperation = -1
};
const unsigned TernaryOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered + 1;
const unsigned NonBranchTernaryOperationCount = FloatMin + 1;
const unsigned BranchOperationCount
= JumpIfFloatGreaterOrEqualOrUnordered - FloatMin;
enum OperandType {
ConstantOperand,
AddressOperand,
RegisterOperand,
MemoryOperand
};
enum ValueType {
ValueGeneral,
ValueFloat
};
const unsigned OperandTypeCount = MemoryOperand + 1;
const int NoRegister = -1;
inline bool isBranch(lir::TernaryOperation op) {
return op > FloatMin;
}
inline bool isFloatBranch(lir::TernaryOperation op) {
return op > JumpIfNotEqual;
}
class Operand { };
class Constant: public Operand {
public:
Constant(Promise* value): value(value) { }
Promise* value;
};
class Address: public Operand {
public:
Address(Promise* address): address(address) { }
Promise* address;
};
class Register: public Operand {
public:
Register(int low, int high = NoRegister): low(low), high(high) { }
int low;
int high;
};
class Memory: public Operand {
public:
Memory(int base, int offset, int index = NoRegister, unsigned scale = 1):
base(base), offset(offset), index(index), scale(scale)
{ }
int base;
int offset;
int index;
unsigned scale;
};
class Instr {
public:
enum Opcode {
#define LIR_OP_0(x) OP_##x,
#define LIR_OP_1(x) OP_##x,
#define LIR_OP_2(x) OP_##x,
#define LIR_OP_3(x) OP_##x,
#include "lir-ops.inc.cpp"
#undef LIR_OP_0
#undef LIR_OP_1
#undef LIR_OP_2
#undef LIR_OP_3
};
static const char* opcodeName(Opcode op);
static Opcode opcodeFromNullary(Operation op);
static Opcode opcodeFromUnary(UnaryOperation op);
static Opcode opcodeFromBinary(BinaryOperation op);
static Opcode opcodeFromTernary(TernaryOperation op);
};
} // namespace lir
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_LIR_H

File diff suppressed because it is too large Load Diff

159
src/codegen/promise.h Normal file
View File

@ -0,0 +1,159 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_PROMISE_H
#define AVIAN_CODEGEN_PROMISE_H
#include "allocator.h"
namespace avian {
namespace codegen {
class Promise {
public:
class Listener {
public:
virtual bool resolve(int64_t value, void** location) = 0;
Listener* next;
};
virtual int64_t value() = 0;
virtual bool resolved() = 0;
virtual Listener* listen(unsigned) { return 0; }
};
class ResolvedPromise: public Promise {
public:
ResolvedPromise(int64_t value): value_(value) { }
virtual int64_t value() {
return value_;
}
virtual bool resolved() {
return true;
}
int64_t value_;
};
class ShiftMaskPromise: public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
virtual int64_t value() {
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
unsigned shift;
int64_t mask;
};
class CombinedPromise: public Promise {
public:
CombinedPromise(Promise* low, Promise* high):
low(low), high(high)
{ }
virtual int64_t value() {
return low->value() | (high->value() << 32);
}
virtual bool resolved() {
return low->resolved() and high->resolved();
}
Promise* low;
Promise* high;
};
class OffsetPromise: public Promise {
public:
OffsetPromise(Promise* base, int64_t offset):
base(base), offset(offset)
{ }
virtual int64_t value() {
return base->value() + offset;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
int64_t offset;
};
class ListenPromise: public Promise {
public:
ListenPromise(vm::System* s, vm::Allocator* allocator):
s(s), allocator(allocator), listener(0)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
vm::System* s;
vm::Allocator* allocator;
Listener* listener;
Promise* promise;
};
class DelayedPromise: public ListenPromise {
public:
DelayedPromise(vm::System* s, vm::Allocator* allocator, Promise* basis,
DelayedPromise* next):
ListenPromise(s, allocator), basis(basis), next(next)
{ }
virtual int64_t value() {
abort(s);
}
virtual bool resolved() {
return false;
}
virtual Listener* listen(unsigned sizeInBytes) {
Listener* l = static_cast<Listener*>(allocator->allocate(sizeInBytes));
l->next = listener;
listener = l;
return l;
}
Promise* basis;
DelayedPromise* next;
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_PROMISE_H

35
src/codegen/registers.cpp Normal file
View File

@ -0,0 +1,35 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include "codegen/registers.h"
namespace avian {
namespace codegen {
unsigned
RegisterMask::maskStart(uint32_t mask)
{
for (int i = 0; i <= 31; ++i) {
if (mask & (1 << i)) return i;
}
return 32;
}
unsigned
RegisterMask::maskLimit(uint32_t mask)
{
for (int i = 31; i >= 0; --i) {
if (mask & (1 << i)) return i + 1;
}
return 0;
}
} // namespace codegen
} // namespace avian

51
src/codegen/registers.h Normal file
View File

@ -0,0 +1,51 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_REGISTERS_H
#define AVIAN_CODEGEN_REGISTERS_H
#include "common.h"
namespace avian {
namespace codegen {
class RegisterMask {
public:
uint32_t mask;
uint8_t start;
uint8_t limit;
static unsigned maskStart(uint32_t mask);
static unsigned maskLimit(uint32_t mask);
inline RegisterMask(uint32_t mask):
mask(mask),
start(maskStart(mask)),
limit(maskLimit(mask))
{ }
};
class RegisterFile {
public:
RegisterMask allRegisters;
RegisterMask generalRegisters;
RegisterMask floatRegisters;
inline RegisterFile(uint32_t generalRegisterMask, uint32_t floatRegisterMask):
allRegisters(generalRegisterMask | floatRegisterMask),
generalRegisters(generalRegisterMask),
floatRegisters(floatRegisterMask)
{ }
};
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_REGISTERS_H

View File

@ -14,7 +14,7 @@
namespace avian {
namespace codegen {
vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) {
Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures UNUSED) {
#ifndef AVIAN_TARGET_ARCH
#error "Must specify native target!"
#endif

View File

@ -16,11 +16,11 @@
namespace avian {
namespace codegen {
vm::Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
Assembler::Architecture* makeArchitectureNative(vm::System* system, bool useNativeFeatures);
vm::Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
vm::Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
vm::Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures);
Assembler::Architecture* makeArchitectureX86(vm::System* system, bool useNativeFeatures);
Assembler::Architecture* makeArchitectureArm(vm::System* system, bool useNativeFeatures);
Assembler::Architecture* makeArchitecturePowerpc(vm::System* system, bool useNativeFeatures);
} // namespace codegen
} // namespace avian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -55,10 +55,7 @@ class MutexLock {
class Context;
void NO_RETURN abort(Context*);
#ifndef NDEBUG
void assert(Context*, bool);
#endif
Aborter* getAborter(Context* c);
void* tryAllocate(Context* c, unsigned size);
void* allocate(Context* c, unsigned size);
@ -745,20 +742,10 @@ segment(Context* c, void* p)
}
}
inline void NO_RETURN
abort(Context* c)
{
abort(c->system);
inline Aborter* getAborter(Context* c) {
return c->system;
}
#ifndef NDEBUG
inline void
assert(Context* c, bool v)
{
assert(c->system, v);
}
#endif
inline unsigned
minimumNextGen1Capacity(Context* c)
{

View File

@ -3966,7 +3966,7 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size,
Client(Thread* t): t(t) { }
virtual void NO_RETURN handleError() {
vm::abort(t);
abort(t);
}
private:
@ -4853,11 +4853,11 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
virtual bool visit(Processor::StackWalker* walker) {
if (trace == 0) {
trace = makeObjectArray(t, walker->count());
vm_assert(t, trace);
assert(t, trace);
}
object e = makeTraceElement(t, walker->method(), walker->ip());
vm_assert(t, index < objectArrayLength(t, trace));
assert(t, index < objectArrayLength(t, trace));
set(t, trace, ArrayBody + (index * BytesPerWord), e);
++ index;
return true;

View File

@ -1761,24 +1761,8 @@ class RawMonitorResource: public Thread::Resource {
System::Monitor* m;
};
inline void NO_RETURN
abort(Thread* t)
{
abort(t->m->system);
}
#ifndef NDEBUG
inline void
assert(Thread* t, bool v)
{
assert(t->m->system, v);
}
#endif // not NDEBUG
inline void
expect(Thread* t, bool v)
{
expect(t->m->system, v);
inline Aborter* getAborter(Thread* t) {
return t->m->system;
}
class FixedAllocator: public Allocator {

View File

@ -18,9 +18,13 @@
#include "heapwalk.h"
#include "zone.h"
namespace vm {
namespace avian {
namespace codegen {
class DelayedPromise;
}
}
namespace vm {
class Processor {
public:
@ -143,7 +147,7 @@ class Processor {
virtual void
compileMethod(Thread* t, Zone* zone, object* constants, object* calls,
DelayedPromise** addresses, object method,
avian::codegen::DelayedPromise** addresses, object method,
OffsetResolver* resolver) = 0;
virtual void

View File

@ -13,10 +13,11 @@
#include "common.h"
#include "allocator.h"
#include "util/abort.h"
namespace vm {
class System {
class System : public Aborter {
public:
typedef intptr_t Status;
@ -150,7 +151,6 @@ class System {
virtual int64_t now() = 0;
virtual void yield() = 0;
virtual void exit(int code) = 0;
virtual void abort() = 0;
virtual void dispose() = 0;
};
@ -165,11 +165,8 @@ allocate(System* s, unsigned size)
#define ACQUIRE_MONITOR(t, m) \
System::MonitorResource MAKE_NAME(monitorResource_) (t, m)
inline void NO_RETURN
abort(System* s)
{
s->abort(); // this should not return
::abort();
inline Aborter* getAborter(System* s) {
return s;
}
inline void NO_RETURN
@ -178,28 +175,22 @@ sysAbort(System* s)
abort(s);
}
inline void
expect(System* s, bool v)
{
if (UNLIKELY(not v)) abort(s);
}
// #ifdef NDEBUG
#ifdef NDEBUG
// # define assert(a, b)
// # define vm_assert(a, b)
# define assert(a, b)
# define vm_assert(a, b)
// #else // not NDEBUG
#else // not NDEBUG
// inline void
// assert(System* s, bool v)
// {
// expect(s, v);
// }
inline void
assert(System* s, bool v)
{
expect(s, v);
}
// # define vm_assert(a, b) vm::assert(a, b)
# define vm_assert(a, b) vm::assert(a, b)
#endif // not NDEBUG
// #endif // not NDEBUG
JNIEXPORT System*
makeSystem(const char* crashDumpDirectory);

41
src/util/abort.h Normal file
View File

@ -0,0 +1,41 @@
/* Copyright (c) 2008-2012, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_UTIL_ABORT_H
#define AVIAN_UTIL_ABORT_H
class Aborter {
public:
virtual void NO_RETURN abort() = 0;
};
template<class T>
inline void NO_RETURN abort(T t) {
getAborter(t)->abort();
::abort();
}
template<class T>
inline void expect(T t, bool v) {
if(UNLIKELY(!v)) {
abort(t);
}
}
#ifdef NDEBUG
#define assert(t, v)
#else
template<class T>
inline void assert(T t, bool v) {
expect(t, v);
}
#endif
#endif // AVIAN_UTIL_ABORT_H

View File

@ -8,8 +8,8 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef UTIL_RUNTIME_ARRAY_H
#define UTIL_RUNTIME_ARRAY_H
#ifndef AVIAN_UTIL_RUNTIME_ARRAY_H
#define AVIAN_UTIL_RUNTIME_ARRAY_H
#ifdef _MSC_VER
@ -37,4 +37,4 @@ class RuntimeArray {
#endif
#endif
#endif // AVIAN_UTIL_RUNTIME_ARRAY_H