more JIT compiler progress

This commit is contained in:
Joel Dice 2007-12-09 15:45:43 -07:00
parent 5b5a4fe8d7
commit f8cda0cd85
7 changed files with 8503 additions and 8339 deletions

View File

@ -161,6 +161,12 @@ interpreter-sources = \
interpreter-asm-sources = $(src)/$(asm).S interpreter-asm-sources = $(src)/$(asm).S
ifeq ($(process),compile) ifeq ($(process),compile)
interpreter-depends += \
$(src)/compiler.h \
$(src)/vector.h
interpreter-sources += $(src)/compiler.cpp
interpreter-asm-sources += $(src)/compile.S interpreter-asm-sources += $(src)/compile.S
endif endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,25 @@ using namespace vm;
namespace { namespace {
enum Register {
rax = 0,
rcx = 1,
rdx = 2,
rbx = 3,
rsp = 4,
rbp = 5,
rsi = 6,
rdi = 7,
r8 = 8,
r9 = 9,
r10 = 10,
r11 = 11,
r12 = 12,
r13 = 13,
r14 = 14,
r15 = 15,
};
class IpMapping { class IpMapping {
public: public:
IpMapping(unsigned ip, unsigned offset): ip(ip), offset(offset) { } IpMapping(unsigned ip, unsigned offset): ip(ip), offset(offset) { }
@ -24,7 +43,8 @@ class Context {
constantPool(s, BytesPerWord * 32), constantPool(s, BytesPerWord * 32),
registerPool(s, BytesPerWord * 8), registerPool(s, BytesPerWord * 8),
promises(s, 1024), promises(s, 1024),
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)) indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
stackIndex(- BytesPerWord)
{ } { }
void dispose() { void dispose() {
@ -39,13 +59,14 @@ class Context {
System* s; System* s;
Vector code; Vector code;
Vector<MyOperand*> virtualStack; Vector virtualStack;
Vector operands; Vector operands;
Vector<IpMapping> ipTable; Vector ipTable;
Vector<MyOperand*> constantPool; Vector constantPool;
Vector<MyOperand*> registerPool; Vector registerPool;
Vector promises; Vector promises;
intptr_t indirectCaller; intptr_t indirectCaller;
int stackIndex;
}; };
inline void NO_RETURN inline void NO_RETURN
@ -65,7 +86,7 @@ assert(Context* c, bool v)
inline void inline void
expect(Context* c, bool v) expect(Context* c, bool v)
{ {
expect(c->system, v); expect(c->s, v);
} }
class MyPromise: public Promise { class MyPromise: public Promise {
@ -78,7 +99,7 @@ class MyPromise: public Promise {
MyPromise(intptr_t value): resolved(false), value_(value) { } MyPromise(intptr_t value): resolved(false), value_(value) { }
virtual unsigned value(System* s) { virtual unsigned value(System* s UNUSED) {
assert(s, resolved); assert(s, resolved);
return value_; return value_;
} }
@ -100,7 +121,7 @@ class PoolPromise: public MyPromise {
class CodePromise: public MyPromise { class CodePromise: public MyPromise {
public: public:
PoolPromise(intptr_t value): MyPromise(value) { } CodePromise(intptr_t value): MyPromise(value) { }
virtual PromiseType type() { virtual PromiseType type() {
return CodePromiseType; return CodePromiseType;
@ -109,7 +130,7 @@ class CodePromise: public MyPromise {
class IpPromise: public MyPromise { class IpPromise: public MyPromise {
public: public:
PoolPromise(intptr_t value): MyPromise(value) { } IpPromise(intptr_t value): MyPromise(value) { }
virtual PromiseType type() { virtual PromiseType type() {
return IpPromiseType; return IpPromiseType;
@ -120,8 +141,10 @@ class MyOperand: public Operand {
public: public:
enum OperandType { enum OperandType {
ImmediateOperandType, ImmediateOperandType,
AbsoluteOperandType,
RegisterOperandType, RegisterOperandType,
MemoryOperandType MemoryOperandType,
SelectionOperandType
}; };
virtual ~MyOperand() { } virtual ~MyOperand() { }
@ -136,10 +159,16 @@ class MyOperand: public Operand {
virtual void push(Context* c) { abort(c); } virtual void push(Context* c) { abort(c); }
virtual void pop(Context* c) { abort(c); }
virtual void mov(Context* c, MyOperand*) { abort(c); } virtual void mov(Context* c, MyOperand*) { abort(c); }
virtual void cmp(Context* c, MyOperand*) { abort(c); } virtual void cmp(Context* c, MyOperand*) { abort(c); }
virtual void call(Context* c) { abort(c); }
virtual void alignedCall(Context* c) { abort(c); }
virtual void jl(Context* c) { abort(c); } virtual void jl(Context* c) { abort(c); }
virtual void jg(Context* c) { abort(c); } virtual void jg(Context* c) { abort(c); }
@ -179,6 +208,141 @@ class MyOperand: public Operand {
virtual void neg(Context* c) { abort(c); } virtual void neg(Context* c) { abort(c); }
}; };
inline bool
isInt8(intptr_t v)
{
return v == static_cast<int8_t>(v);
}
inline bool
isInt32(intptr_t v)
{
return v == static_cast<int32_t>(v);
}
Register
registerValue(Context* c, MyOperand* v);
Promise*
absoluteValue(Context* c, MyOperand* v);
void
setAbsoluteValue(Context* c, MyOperand* v, Promise* value);
MyOperand*
memoryBase(Context* c, MyOperand* v);
int
memoryDisplacement(Context* c, MyOperand* v);
MyOperand*
memoryIndex(Context* c, MyOperand* v);
unsigned
memoryScale(Context* c, MyOperand* v);
Register
asRegister(Context* c, MyOperand* v);
void
rex(Context* c)
{
if (BytesPerWord == 8) {
c->code.append(0x48);
}
}
void
ret(Context* c)
{
c->code.append(0xc3);
}
void
encode(Context* c, uint8_t instruction, uint8_t zeroPrefix,
uint8_t bytePrefix, uint8_t wordPrefix,
Register a, Register b, int32_t offset)
{
c->code.append(instruction);
uint8_t prefix;
if (offset == 0 and b != rbp) {
prefix = zeroPrefix;
} else if (isInt8(offset)) {
prefix = bytePrefix;
} else {
prefix = wordPrefix;
}
c->code.append(prefix | (a << 3) | b);
if (b == rsp) {
c->code.append(0x24);
}
if (offset == 0 and b != rbp) {
// do nothing
} else if (isInt8(offset)) {
c->code.append(offset);
} else {
c->code.append4(offset);
}
}
class RegisterOperand: public MyOperand {
public:
RegisterOperand(Register value):
value(value)
{ }
virtual OperandType type() {
return RegisterOperandType;
}
virtual unsigned size() {
return sizeof(RegisterOperand);
}
virtual void push(Context* c) {
c->code.append(0x50 | value);
}
virtual void mov(Context* c, MyOperand* dst) {
switch (dst->type()) {
case RegisterOperandType:
if (value != registerValue(c, dst)) {
rex(c);
c->code.append(0x89);
c->code.append(0xc0 | (value << 3) | registerValue(c, dst));
}
break;
case MemoryOperandType:
rex(c);
encode(c, 0x89, 0, 0x40, 0x80, value,
asRegister(c, memoryBase(c, dst)),
memoryDisplacement(c, dst));
break;
default: abort(c);
}
}
Register value;
};
RegisterOperand*
temporary(Context* c)
{
return c->registerPool.pop<RegisterOperand*>();
}
void
release(Context* c, RegisterOperand* v)
{
c->registerPool.push(v);
}
class ImmediateOperand: public MyOperand { class ImmediateOperand: public MyOperand {
public: public:
ImmediateOperand(intptr_t value): ImmediateOperand(intptr_t value):
@ -219,9 +383,9 @@ class ImmediateOperand: public MyOperand {
case MemoryOperandType: case MemoryOperandType:
rex(c); rex(c);
encode(c, 0xc7, 0, 0x40, 0x80, rax, encode(c, 0xc7, 0, 0x40, 0x80, rax,
asRegister(memoryBase(c, dst)), asRegister(c, memoryBase(c, dst)),
memoryDisplacement(c, dst)); memoryDisplacement(c, dst));
c->code.append4(v); c->code.append4(value);
break; break;
default: abort(c); default: abort(c);
@ -248,98 +412,13 @@ class AbsoluteOperand: public MyOperand {
Promise* value; Promise* value;
}; };
class RegisterOperand: public MyOperand {
public:
RegisterOperand(Register value):
value(value)
{ }
virtual OperandType type() {
return RegisterOperandType;
}
virtual unsigned size() {
return sizeof(RegisterOperand);
}
virtual void push(Context* c) {
c->code.append(0x50 | value);
}
virtual void mov(Context* c, MyOperand* dst) {
switch (dst->type()) {
case RegisterOperandType:
if (value != registerValue(c, dst)) {
rex(c);
c->code.append(0x89);
c->code.append(0xc0 | (value << 3) | registerValue(c, dst));
}
break;
case MemoryOperandType:
rex(c);
encode(c, 0x89, 0, 0x40, 0x80, src,
asRegister(memoryBase(c, dst)),
memoryDisplacement(c, dst));
break;
default: abort(c);
}
}
Register value;
};
RegisterOperand*
temporary(Context* c)
{
return c->registerPool.pop<RegisterOperand*>();
}
void
release(Context* c, RegisterOperand* v)
{
return c->registerPool.push(v);
}
void
encode(Context* c, uint8_t instruction, uint8_t zeroPrefix,
uint8_t bytePrefix, uint8_t wordPrefix,
Register a, Register b, int32_t offset)
{
c->code.append(instruction);
uint8_t prefix;
if (offset == 0 and b != rbp) {
prefix = zeroPrefix;
} else if (isByte(offset)) {
prefix = bytePrefix;
} else {
prefix = wordPrefix;
}
c->code.append(prefix | (a << 3) | b);
if (b == rsp) {
c->code.append(0x24);
}
if (offset == 0 and b != rbp) {
// do nothing
} else if (isInt8(offset)) {
c->code.append(offset);
} else {
c->code.append4(offset);
}
}
Register Register
asRegister(Context* c, MyOperand* v) asRegister(Context* c, MyOperand* v)
{ {
if (v->type() == RegisterOperandType) { if (v->type() == MyOperand::RegisterOperandType) {
return registerValue(v); return registerValue(c, v);
} else { } else {
assert(c, v->type() == MemoryOperandType); assert(c, v->type() == MyOperand::MemoryOperandType);
RegisterOperand* tmp = temporary(c); RegisterOperand* tmp = temporary(c);
v->mov(c, tmp); v->mov(c, tmp);
@ -383,7 +462,7 @@ class MemoryOperand: public MyOperand {
case RegisterOperandType: case RegisterOperandType:
rex(c); rex(c);
encode(c, 0x8b, 0, 0x40, 0x80, registerValue(c, dst), encode(c, 0x8b, 0, 0x40, 0x80, registerValue(c, dst),
base, displacement); asRegister(c, base), displacement);
break; break;
case MemoryOperandType: { case MemoryOperandType: {
@ -393,7 +472,7 @@ class MemoryOperand: public MyOperand {
release(c, tmp); release(c, tmp);
} break; } break;
default: abort(t); default: abort(c);
} }
} }
@ -420,8 +499,16 @@ class StackOperand: public MemoryOperand {
class SelectionOperand: public MyOperand { class SelectionOperand: public MyOperand {
public: public:
SelectionOperand(Compiler::SelectionType type, MyOperand* base): enum SelectionType {
type(type), base(base) S1Selection,
S2Selection,
Z2Selection,
S4Selection,
S8Selection
};
SelectionOperand(SelectionType type, MyOperand* base):
selectionType(type), base(base)
{ } { }
virtual OperandType type() { virtual OperandType type() {
@ -429,7 +516,7 @@ class SelectionOperand: public MyOperand {
} }
virtual unsigned footprint() { virtual unsigned footprint() {
if (type == Compiler::S8Selection) { if (selectionType == S8Selection) {
return 8; return 8;
} else { } else {
return 4; return 4;
@ -440,7 +527,7 @@ class SelectionOperand: public MyOperand {
return sizeof(SelectionOperand); return sizeof(SelectionOperand);
} }
Compiler::SelectionType type; SelectionType selectionType;
MyOperand* base; MyOperand* base;
}; };
@ -451,7 +538,7 @@ immediate(Context* c, intptr_t v)
} }
AbsoluteOperand* AbsoluteOperand*
absolute(Context* c, intptr_t v) absolute(Context* c, Promise* v)
{ {
return c->operands.push(AbsoluteOperand(v)); return c->operands.push(AbsoluteOperand(v));
} }
@ -476,10 +563,10 @@ stack(Context* c, int displacement)
} }
MyOperand* MyOperand*
selection(Context* c, Compiler::SelectionType type, MyOperand* base) selection(Context* c, SelectionOperand::SelectionType type, MyOperand* base)
{ {
if ((type == S4Selection and BytesPerWord == 4) if ((type == SelectionOperand::S4Selection and BytesPerWord == 4)
or (type == S8Selection and BytesPerWord == 8)) or (type == SelectionOperand::S8Selection and BytesPerWord == 8))
{ {
return base; return base;
} else { } else {
@ -488,18 +575,18 @@ selection(Context* c, Compiler::SelectionType type, MyOperand* base)
} }
bool bool
isStackReference(Context* c, MyOperand* v) isStackReference(Context*, MyOperand* v)
{ {
return v->type() == MemoryOperandType return v->type() == MyOperand::MemoryOperandType
and static_cast<MemoryOperand*>(v)->isStackReference(); and static_cast<MemoryOperand*>(v)->isStackReference();
} }
void void
flushStack(Context* c) flushStack(Context* c)
{ {
Stack newVirtualStack; Vector newVirtualStack(c->s, c->virtualStack.length() * 2);
for (unsigned i = 0; i < c->virtualStack.length();) { for (unsigned i = 0; i < c->virtualStack.length();) {
MyOperand* v = c->virtualStack.peek<MyOperand*>(i); MyOperand* v = c->virtualStack.peek<MyOperand>(i);
if (not isStackReference(c, v)) { if (not isStackReference(c, v)) {
v->push(c); v->push(c);
@ -510,13 +597,30 @@ flushStack(Context* c)
newVirtualStack.push(stack(c, c->stackIndex)); newVirtualStack.push(stack(c, c->stackIndex));
} }
} else { } else {
newVirtualStack.push(v, v->size()); newVirtualStack.append(v, v->size());
} }
i += v->size(); i += v->size();
} }
c->virtualStack.swap(&newVirtualStack); c->virtualStack.update(&newVirtualStack);
}
unsigned
pushArguments(Context* c, unsigned count, va_list list)
{
MyOperand* arguments[count];
unsigned footprint = 0;
for (unsigned i = 0; i < count; ++i) {
arguments[i] = va_arg(list, MyOperand*);
footprint += pad(arguments[i]->footprint());
}
for (int i = count - 1; i >= 0; --i) {
arguments[i]->push(c);
}
return footprint;
} }
class MyCompiler: public Compiler { class MyCompiler: public Compiler {
@ -526,16 +630,17 @@ class MyCompiler: public Compiler {
{ } { }
virtual Promise* poolOffset() { virtual Promise* poolOffset() {
return c.promises.push(PoolPromise(constantPool.length() / BytesPerWord)); return c.promises.push
(PoolPromise(c.constantPool.length() / BytesPerWord));
} }
virtual Promise* codeOffset() { virtual Promise* codeOffset() {
return c.promises.push(CodePromise(code.length())); return c.promises.push(CodePromise(c.code.length()));
} }
virtual Operand* poolAppend(Operand* v) { virtual Operand* poolAppend(Operand* v) {
Operand* r = absolute(&c, poolOffset()); Operand* r = absolute(&c, poolOffset());
constantPool.push(static_cast<MyOperand*>(v)); c.constantPool.push(static_cast<MyOperand*>(v));
return r; return r;
} }
@ -553,15 +658,16 @@ class MyCompiler: public Compiler {
} }
virtual Operand* stack(unsigned index) { virtual Operand* stack(unsigned index) {
return c.virtualStack.peek(stack.size() - index - 1); return c.virtualStack.peek<MyOperand>
(c.virtualStack.length() - ((index + 1) * BytesPerWord));
} }
virtual Operand* stack2(unsigned index) { virtual Operand* stack2(unsigned index) {
return c.virtualStack.peek(stack.size() - index - 1); return stack(index);
} }
virtual Operand* pop() { virtual Operand* pop() {
return pop(c); return c.virtualStack.pop<MyOperand*>();
} }
virtual Operand* pop2() { virtual Operand* pop2() {
@ -570,7 +676,7 @@ class MyCompiler: public Compiler {
} }
virtual void pop(Operand* dst) { virtual void pop(Operand* dst) {
pop(c)->mov(&c, static_cast<MyOperand*>(dst)); c.virtualStack.pop<MyOperand*>()->mov(&c, static_cast<MyOperand*>(dst));
} }
virtual void pop2(Operand* dst) { virtual void pop2(Operand* dst) {
@ -628,45 +734,49 @@ class MyCompiler: public Compiler {
(Operand* address, unsigned argumentCount, ...) (Operand* address, unsigned argumentCount, ...)
{ {
va_list a; va_start(a, argumentCount); va_list a; va_start(a, argumentCount);
pushArguments(&c, argumentCount, a); unsigned footprint = pushArguments(&c, argumentCount, a);
va_end(a); va_end(a);
static_cast<MyOperand*>(address)->mov(&c, register_(rax)); static_cast<MyOperand*>(address)->mov(&c, register_(&c, rax));
immediate(&c, indirectCaller)->call(&c); immediate(&c, c.indirectCaller)->call(&c);
popArguments(&c, argumentCount); immediate(&c, footprint)->sub(&c, register_(&c, rsp));
return register_(&c, rax);
} }
virtual Operand* indirectCallNoReturn virtual void indirectCallNoReturn
(Operand* address, unsigned argumentCount, ...) (Operand* address, unsigned argumentCount, ...)
{ {
va_list a; va_start(a, argumentCount); va_list a; va_start(a, argumentCount);
pushArguments(&c, argumentCount, a); pushArguments(&c, argumentCount, a);
va_end(a); va_end(a);
static_cast<MyOperand*>(address)->mov(&c, register_(rax)); static_cast<MyOperand*>(address)->mov(&c, register_(&c, rax));
immediate(&c, indirectCaller)->call(&c); immediate(&c, c.indirectCaller)->call(&c);
} }
virtual Operand* directCall virtual Operand* directCall
(Operand* address, unsigned argumentCount, ...) (Operand* address, unsigned argumentCount, ...)
{ {
va_list a; va_start(a, argumentCount); va_list a; va_start(a, argumentCount);
pushArguments(&c, argumentCount, a); unsigned footprint = pushArguments(&c, argumentCount, a);
va_end(a); va_end(a);
static_cast<MyOperand*>(address)->call(&c); static_cast<MyOperand*>(address)->call(&c);
popArguments(&c, argumentCount); immediate(&c, footprint)->sub(&c, register_(&c, rsp));
return register_(&c, rax);
} }
virtual void return_(Operand* v) { virtual void return_(Operand* v) {
static_cast<MyOperand*>(v)->mov(&c, register_(rax)); static_cast<MyOperand*>(v)->mov(&c, register_(&c, rax));
ret(c); ret();
} }
virtual void ret() { virtual void ret() {
ret(c); ::ret(&c);
} }
virtual void mov(Operand* src, Operand* dst) { virtual void mov(Operand* src, Operand* dst) {
@ -757,11 +867,33 @@ class MyCompiler: public Compiler {
virtual Operand* memory(Operand* base, int displacement, virtual Operand* memory(Operand* base, int displacement,
Operand* index, unsigned scale) Operand* index, unsigned scale)
{ {
return memory(&c, base, displacement, index, scale); return ::memory(&c, static_cast<MyOperand*>(base), displacement,
static_cast<MyOperand*>(index), scale);
} }
virtual Operand* select(SelectionType type, Operand* v) { virtual Operand* select1(Operand* v) {
return selection(&c, type, v); return selection(&c, SelectionOperand::S1Selection,
static_cast<MyOperand*>(v));
}
virtual Operand* select2(Operand* v) {
return selection(&c, SelectionOperand::S2Selection,
static_cast<MyOperand*>(v));
}
virtual Operand* select2z(Operand* v) {
return selection(&c, SelectionOperand::Z2Selection,
static_cast<MyOperand*>(v));
}
virtual Operand* select4(Operand* v) {
return selection(&c, SelectionOperand::S4Selection,
static_cast<MyOperand*>(v));
}
virtual Operand* select8(Operand* v) {
return selection(&c, SelectionOperand::S8Selection,
static_cast<MyOperand*>(v));
} }
virtual void prologue() { virtual void prologue() {
@ -775,19 +907,20 @@ class MyCompiler: public Compiler {
} }
virtual void startLogicalIp(unsigned ip) { virtual void startLogicalIp(unsigned ip) {
c.ipTable.push(IpMapping(ip, code.length())); c.ipTable.push(IpMapping(ip, c.code.length()));
} }
virtual Operand* logicalIp(unsigned ip) { virtual Operand* logicalIp(unsigned ip) {
return absolute(&c, promises.push(IpPromise(ip))); return absolute(&c, c.promises.push(IpPromise(ip)));
} }
virtual unsigned logicalIpToOffset(unsigned ip) { virtual unsigned logicalIpToOffset(unsigned ip) {
unsigned bottom = 0; unsigned bottom = 0;
unsigned top = c.ipTable.size(); unsigned top = c.ipTable.length() / sizeof(IpMapping);
for (unsigned span = top - bottom; span; span = top - bottom) { for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2); unsigned middle = bottom + (span / 2);
IpMapping* mapping = c.ipTable.get(middle); IpMapping* mapping = c.ipTable.peek<IpMapping>
(middle * sizeof(IpMapping));
if (ip == mapping->ip) { if (ip == mapping->ip) {
return mapping->offset; return mapping->offset;
@ -798,25 +931,25 @@ class MyCompiler: public Compiler {
} }
} }
abort(s); abort(&c);
} }
virtual unsigned size() { virtual unsigned size() {
return c.code.length(); return c.code.length();
} }
virtual void writeTo(void* out) { virtual void writeTo(void*) {
// todo // todo
} }
virtual void updateCall(void* returnAddress, void* newTarget) { virtual void updateCall(void*, void*) {
// todo // todo
} }
virtual void dispose() { virtual void dispose() {
c.dispose(); c.dispose();
s->free(this); c.s->free(this);
} }
Context c; Context c;

View File

@ -16,14 +16,6 @@ class Promise {
class Compiler { class Compiler {
public: public:
enum SelectionType {
S1Selection,
S2Selection,
Z2Selection,
S4Selection,
S8Selection
};
virtual ~Compiler() { } virtual ~Compiler() { }
virtual Promise* poolOffset() = 0; virtual Promise* poolOffset() = 0;
@ -56,7 +48,7 @@ class Compiler {
virtual Operand* alignedCall(Operand*) = 0; virtual Operand* alignedCall(Operand*) = 0;
virtual Operand* indirectCall virtual Operand* indirectCall
(Operand* address, unsigned argumentCount, ...) = 0; (Operand* address, unsigned argumentCount, ...) = 0;
virtual Operand* indirectCallNoReturn virtual void indirectCallNoReturn
(Operand* address, unsigned argumentCount, ...) = 0; (Operand* address, unsigned argumentCount, ...) = 0;
virtual Operand* directCall virtual Operand* directCall
(Operand* address, unsigned argumentCount, ...) = 0; (Operand* address, unsigned argumentCount, ...) = 0;
@ -89,7 +81,11 @@ class Compiler {
virtual Operand* memory(Operand* base, int displacement = 0, virtual Operand* memory(Operand* base, int displacement = 0,
Operand* index = 0, unsigned scale = 1) = 0; Operand* index = 0, unsigned scale = 1) = 0;
virtual Operand* select(SelectionType, Operand*) = 0; virtual Operand* select1(Operand*) = 0;
virtual Operand* select2(Operand*) = 0;
virtual Operand* select2z(Operand*) = 0;
virtual Operand* select4(Operand*) = 0;
virtual Operand* select8(Operand*) = 0;
virtual void prologue() = 0; virtual void prologue() = 0;
virtual void epilogue() = 0; virtual void epilogue() = 0;

5198
src/old-compile.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
namespace vm { namespace vm {
template <class T = uint8_t>
class Vector { class Vector {
public: public:
Vector(System* s, unsigned minimumCapacity): Vector(System* s, unsigned minimumCapacity):
@ -40,15 +39,13 @@ class Vector {
} }
void get(unsigned offset, void* dst, unsigned size) { void get(unsigned offset, void* dst, unsigned size) {
assert(s, offset >= 0);
assert(s, offset + size <= position); assert(s, offset + size <= position);
mempcy(dst, data + offset, size); memcpy(dst, data + offset, size);
} }
void set(unsigned offset, const void* src, unsigned size) { void set(unsigned offset, const void* src, unsigned size) {
assert(s, offset >= 0);
assert(s, offset + size <= position); assert(s, offset + size <= position);
mempcy(data + offset, src, size); memcpy(data + offset, src, size);
} }
void pop(void* dst, unsigned size) { void pop(void* dst, unsigned size) {
@ -56,14 +53,19 @@ class Vector {
position -= size; position -= size;
} }
void* append(const void* p, unsigned size) { void* allocate(unsigned size) {
ensure(size); ensure(size);
void* r = data + position; void* r = data + position;
memcpy(r, p, size);
position += size; position += size;
return r; return r;
} }
void* append(const void* p, unsigned size) {
void* r = allocate(size);
memcpy(r, p, size);
return r;
}
void append(uint8_t v) { void append(uint8_t v) {
append(&v, 1); append(&v, 1);
} }
@ -80,16 +82,35 @@ class Vector {
append(&v, BytesPerWord); append(&v, BytesPerWord);
} }
template <class C = T> unsigned length() {
C* push(const C& v) { return position;
return static_cast<C*>(append(&v, sizeof(C)));
} }
template <class C = T> template <class T>
C pop() { T* peek(unsigned offset) {
C r; pop(&r, sizeof(C)); assert(s, offset + sizeof(T) <= position);
return reinterpret_cast<T*>(data + offset);
}
template <class T>
T* push(const T& v) {
return static_cast<T*>(append(&v, sizeof(T)));
}
template <class T>
T pop() {
T r; pop(&r, sizeof(T));
return r; return r;
} }
void update(Vector* v) {
dispose();
data = v->data;
position = v->position;
capacity = v->capacity;
minimumCapacity = v->minimumCapacity;
}
System* s; System* s;
uint8_t* data; uint8_t* data;