diff --git a/src/assembler.h b/src/assembler.h index 0bfb16836f..0b9470a605 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -75,7 +75,6 @@ enum OperandType { const unsigned OperandTypeCount = MemoryOperand + 1; const int NoRegister = -1; -const int AnyRegister = -2; class Promise { public: diff --git a/src/compile.cpp b/src/compile.cpp index a0a9ad536c..2ccca41e48 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -342,7 +342,7 @@ alignedFrameSize(MyThread* t, object method) - methodParameterFootprint(t, method) + codeMaxStack(t, methodCode(t, method)) + MaxNativeCallFootprint - - t->arch->argumentRegisterCount()); + - min(MaxNativeCallFootprint, t->arch->argumentRegisterCount())); } unsigned diff --git a/src/compiler.cpp b/src/compiler.cpp index d136e5f0ca..d6b737c367 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -28,6 +28,7 @@ class Value; class Stack; class Site; class RegisterSite; +class MemorySite; class Event; class PushEvent; class Read; @@ -158,7 +159,7 @@ class Register { public: Register(int number): value(0), site(0), number(number), size(0), refCount(0), - freezeCount(0), reserved(false), pushed(false) + freezeCount(0), reserved(false) { } Value* value; @@ -168,7 +169,14 @@ class Register { unsigned refCount; unsigned freezeCount; bool reserved; - bool pushed; +}; + +class FrameResource { + public: + Value* value; + MemorySite* site; + unsigned size; + unsigned freezeCount; }; class ConstantPoolNode { @@ -256,6 +264,7 @@ class Context { registers (static_cast (zone->allocate(sizeof(Register*) * arch->registerCount()))), + frameResources(0), firstConstant(0), lastConstant(0), machineCode(0), @@ -293,6 +302,7 @@ class Context { Event* predecessor; LogicalInstruction** logicalCode; Register** registers; + FrameResource* frameResources; ConstantPoolNode* firstConstant; ConstantPoolNode* lastConstant; uint8_t* machineCode; @@ -508,27 +518,52 @@ class Event { }; int -localOffset(Context* c, int v) +localOffset(Context* c, int frameIndex) { int parameterFootprint = c->parameterFootprint; int frameSize = c->alignedFrameSize; - int offset = ((v < parameterFootprint) ? + int offset = ((frameIndex < parameterFootprint) ? (frameSize + parameterFootprint + (c->arch->frameFooterSize() * 2) + c->arch->frameHeaderSize() - - v - 1) : + - frameIndex - 1) : (frameSize + parameterFootprint + c->arch->frameFooterSize() - - v - 1)) * BytesPerWord; + - frameIndex - 1)) * BytesPerWord; assert(c, offset >= 0); return offset; } +int +localOffsetToFrameIndex(Context* c, int offset) +{ + int parameterFootprint = c->parameterFootprint; + int frameSize = c->alignedFrameSize; + + int normalizedOffset = offset / BytesPerWord; + + int frameIndex = ((normalizedOffset > frameSize) ? + (frameSize + + parameterFootprint + + (c->arch->frameFooterSize() * 2) + + c->arch->frameHeaderSize() + - normalizedOffset - 1) : + (frameSize + + parameterFootprint + + c->arch->frameFooterSize() + - normalizedOffset - 1)); + + assert(c, frameIndex >= 0); + assert(c, localOffset(c, frameIndex) == offset); + + return frameIndex; +} + bool findSite(Context*, Value* v, Site* site) { @@ -872,6 +907,14 @@ decrement(Context* c UNUSED, Register* r) -- r->refCount; } +void +acquireFrameIndex(Context* c, int index, Stack* stack, Local* locals, + unsigned newSize, Value* newValue, MemorySite* newSite, + bool recurse = true); + +void +releaseFrameIndex(Context* c, int index, bool recurse = true); + class MemorySite: public Site { public: MemorySite(int base, int offset, int index, unsigned scale): @@ -918,14 +961,28 @@ class MemorySite: public Site { } } - virtual void acquire(Context* c, Stack*, Local*, unsigned, Value*) { + virtual void acquire(Context* c, Stack* stack, Local* locals, unsigned size, + Value* v) + { base = increment(c, value.base); if (value.index != NoRegister) { index = increment(c, value.index); } + + if (value.base == c->arch->stack()) { + assert(c, value.index == NoRegister); + acquireFrameIndex + (c, localOffsetToFrameIndex(c, value.offset), stack, locals, size, v, + this); + } } virtual void release(Context* c) { + if (value.base == c->arch->stack()) { + assert(c, value.index == NoRegister); + releaseFrameIndex(c, localOffsetToFrameIndex(c, value.offset)); + } + decrement(c, base); if (index) { decrement(c, index); @@ -1014,6 +1071,7 @@ allocateSite(Context* c, uint8_t typeMask, uint64_t registerMask, } else if (frameIndex >= 0) { return frameSite(c, frameIndex); } else { + fprintf(stderr, "type mask %02x reg mask %016lx frame index %d\n", typeMask, registerMask, frameIndex); return 0; } } @@ -1066,6 +1124,7 @@ Read* read(Context* c, unsigned size, uint8_t typeMask, uint64_t registerMask, int frameIndex) { + assert(c, (typeMask != 1 << MemoryOperand) or frameIndex >= 0); return new (c->zone->allocate(sizeof(SingleRead))) SingleRead(size, typeMask, registerMask, frameIndex); } @@ -1535,6 +1594,70 @@ validate(Context* c, uint32_t mask, Stack* stack, Local* locals, return r; } +bool +trySteal(Context* c, FrameResource* r, Stack*, Local*) +{ + Value* v = r->value; + assert(c, v->reads); + + if (v->sites->next == 0) { + return false; // todo + } + + removeSite(c, v, r->site); + + return true; +} + +void +acquireFrameIndex(Context* c, int index, Stack* stack, Local* locals, + unsigned newSize, Value* newValue, MemorySite* newSite, + bool recurse) +{ + assert(c, index >= 0); + assert(c, index < static_cast + (c->alignedFrameSize + c->parameterFootprint)); + + FrameResource* r = c->frameResources + index; + + if (recurse and newSize > BytesPerWord) { + acquireFrameIndex + (c, index + 1, stack, locals, newSize, newValue, newSite, false); + } + + Value* oldValue = r->value; + if (oldValue + and oldValue != newValue + and findSite(c, oldValue, r->site)) + { + if (not trySteal(c, r, stack, locals)) { + abort(c); + } + } + + r->size = newSize; + r->value = newValue; + r->site = 0; +} + +void +releaseFrameIndex(Context* c, int index, bool recurse) +{ + assert(c, index >= 0); + assert(c, index < static_cast + (c->alignedFrameSize + c->parameterFootprint)); + + FrameResource* r = c->frameResources + index; + + if (recurse and r->size > BytesPerWord) { + releaseFrameIndex(c, index + 1, false); + } + + r->size = 0; + r->value = 0; + r->site = 0; +} + void apply(Context* c, UnaryOperation op, unsigned s1Size, Site* s1) @@ -3018,6 +3141,14 @@ class MyCompiler: public Compiler { c.localFootprint = localFootprint; c.alignedFrameSize = alignedFrameSize; + unsigned frameResourceSize = sizeof(FrameResource) + * (alignedFrameSize + parameterFootprint); + + c.frameResources = static_cast + (c.zone->allocate(frameResourceSize)); + + memset(c.frameResources, 0, frameResourceSize); + c.logicalCode = static_cast (c.zone->allocate(sizeof(LogicalInstruction*) * logicalCodeLength)); memset(c.logicalCode, 0, sizeof(LogicalInstruction*) * logicalCodeLength);