diff --git a/makefile b/makefile index 5e14ad1d7e..1dd25da9a6 100755 --- a/makefile +++ b/makefile @@ -961,6 +961,7 @@ ifeq ($(process),compile) $(src)/codegen/compiler/read.cpp \ $(src)/codegen/compiler/event.cpp \ $(src)/codegen/compiler/promise.cpp \ + $(src)/codegen/compiler/frame.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d44426b46f..e8bba8e44f 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -22,8 +22,8 @@ #include "codegen/compiler/site.h" #include "codegen/compiler/read.h" #include "codegen/compiler/event.h" -#include "codegen/compiler/stack.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" using namespace vm; @@ -67,11 +67,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -class Local { - public: - Value* value; -}; - class ForkElement { public: Value* value; @@ -220,118 +215,6 @@ countSuccessors(Link* link) return c; } -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(c->parameterFootprint)) { - index += c->arch->frameHeaderSize(); - } else { - index -= c->arch->frameFooterSize(); - } - - assert(c, index >= 0); - assert(c, static_cast(index) < totalFrameSize(c)); - - return index; -} - -unsigned -frameIndexToOffset(Context* c, unsigned frameIndex) -{ - assert(c, frameIndex < totalFrameSize(c)); - - return (frameIndex + c->arch->frameFooterSize()) * TargetBytesPerWord; -} - -unsigned -offsetToFrameIndex(Context* c, unsigned offset) -{ - assert(c, static_cast - ((offset / TargetBytesPerWord) - c->arch->frameFooterSize()) >= 0); - assert(c, ((offset / TargetBytesPerWord) - c->arch->frameFooterSize()) - < totalFrameSize(c)); - - return (offset / TargetBytesPerWord) - c->arch->frameFooterSize(); -} - -unsigned -frameBase(Context* c) -{ - return c->alignedFrameSize - - c->arch->frameReturnAddressSize() - - c->arch->frameFooterSize() - + c->arch->frameHeaderSize(); -} - -class FrameIterator { - public: - class Element { - public: - Element(Value* value, unsigned localIndex): - value(value), localIndex(localIndex) - { } - - Value* const value; - const unsigned localIndex; - }; - - FrameIterator(Context* c, Stack* stack, Local* locals, - bool includeEmpty = false): - stack(stack), locals(locals), localIndex(c->localFootprint - 1), - includeEmpty(includeEmpty) - { } - - bool 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; - } - - Element 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; - Local* locals; - int localIndex; - bool includeEmpty; -}; - -int -frameIndex(Context* c, FrameIterator::Element* element) -{ - return frameIndex(c, element->localIndex); -} - void clearSites(Context* c, Value* v) { @@ -1021,44 +904,6 @@ apply(Context* c, lir::TernaryOperation op, OperandInfo(s3Size, s3Type, &s3Union)); } -void -clean(Context* c, Value* v, unsigned popIndex) -{ - for (SiteIterator it(c, v); it.hasMore();) { - Site* s = it.next(); - if (not (s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)) - and offsetToFrameIndex - (c, static_cast(s)->offset) - >= popIndex)) - { - if (false and - s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))) - { - char buffer[256]; s->toString(c, buffer, 256); - fprintf(stderr, "remove %s from %p at %d pop offset 0x%x\n", - buffer, v, offsetToFrameIndex - (c, static_cast(s)->offset), - frameIndexToOffset(c, popIndex)); - } - it.remove(c); - } - } -} - -void -clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, - unsigned popIndex) -{ - for (FrameIterator it(c, stack, locals); it.hasMore();) { - FrameIterator::Element e = it.next(c); - clean(c, e.value, popIndex); - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, e, r->value); - } -} - void append(Context* c, Event* e); @@ -1366,12 +1211,6 @@ makeSnapshots(Context* c, Value* value, Snapshot* next) return next; } -Stack* -stack(Context* c, Value* value, Stack* next) -{ - return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); -} - Value* maybeBuddy(Context* c, Value* v); @@ -1586,63 +1425,6 @@ register_(Context* c, int number) return value(c, type, s, s); } -class JumpEvent: public Event { - public: - JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, - bool cleanLocals): - Event(c), type(type), address(address), exit(exit), - cleanLocals(cleanLocals) - { - bool thunk; - uint8_t typeMask; - uint64_t registerMask; - c->arch->plan(type, TargetBytesPerWord, &typeMask, ®isterMask, &thunk); - - assert(c, not thunk); - - this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); - } - - virtual const char* name() { - return "JumpEvent"; - } - - virtual void compile(Context* c) { - if (not this->isUnreachable()) { - apply(c, type, TargetBytesPerWord, address->source, address->source); - } - - for (Read* r = reads; r; r = r->eventNext) { - popRead(c, this, r->value); - } - - if (cleanLocals) { - for (FrameIterator it(c, 0, c->locals); it.hasMore();) { - FrameIterator::Element e = it.next(c); - clean(c, e.value, 0); - } - } - } - - virtual bool isBranch() { return true; } - - virtual bool allExits() { - return exit or this->isUnreachable(); - } - - lir::UnaryOperation type; - Value* address; - bool exit; - bool cleanLocals; -}; - -void -appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, - bool cleanLocals = false) -{ - append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); -} - class BoundsCheckEvent: public Event { public: BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, @@ -2053,7 +1835,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "resolve original %s for %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } Site* target = pickSiteOrMove @@ -2068,7 +1850,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "freeze original %s for %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } Value dummy(0, 0, lir::ValueGeneral); @@ -2101,7 +1883,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (DebugControl) { char buffer[256]; s->toString(c, buffer, 256); fprintf(stderr, "resolve source %s from %p local %d frame %d\n", - buffer, v, el.localIndex, frameIndex(c, &el)); + buffer, v, el.localIndex, el.frameIndex(c)); } freeze(c, frozen, s, v); @@ -2142,7 +1924,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites) if (DebugControl) { char buffer[256]; sites[el.localIndex]->toString(c, buffer, 256); fprintf(stderr, "resolve target %s for %p local %d frame %d\n", - buffer, el.value, el.localIndex, frameIndex(c, &el)); + buffer, el.value, el.localIndex, el.frameIndex(c)); } } } @@ -2258,11 +2040,11 @@ setSites(Context* c, Event* e, Site** sites) } else if (DebugControl) { char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256); fprintf(stderr, "skip sites %s for %p local %d frame %d\n", - buffer, el.value, el.localIndex, frameIndex(c, &el)); + buffer, el.value, el.localIndex, el.frameIndex(c)); } } else if (DebugControl) { fprintf(stderr, "no sites for %p local %d frame %d\n", - el.value, el.localIndex, frameIndex(c, &el)); + el.value, el.localIndex, el.frameIndex(c)); } } } diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 1722714df4..93f12c62b1 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -13,21 +13,16 @@ #include "codegen/compiler/context.h" #include "codegen/compiler/event.h" -#include "codegen/compiler/stack.h" #include "codegen/compiler/site.h" #include "codegen/compiler/read.h" #include "codegen/compiler/value.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/frame.h" namespace avian { namespace codegen { namespace compiler { - -unsigned frameBase(Context* c); -unsigned totalFrameSize(Context* c); -int frameIndex(Context* c, int localIndex); - SiteMask generalRegisterMask(Context* c); SiteMask generalRegisterOrConstantMask(Context* c); @@ -1409,6 +1404,96 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first } } +void clean(Context* c, Value* v, unsigned popIndex) { + for (SiteIterator it(c, v); it.hasMore();) { + Site* s = it.next(); + if (not (s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex)) + and offsetToFrameIndex + (c, static_cast(s)->offset) + >= popIndex)) + { + if (false and + s->match(c, SiteMask(1 << lir::MemoryOperand, 0, AnyFrameIndex))) + { + char buffer[256]; s->toString(c, buffer, 256); + fprintf(stderr, "remove %s from %p at %d pop offset 0x%x\n", + buffer, v, offsetToFrameIndex + (c, static_cast(s)->offset), + frameIndexToOffset(c, popIndex)); + } + it.remove(c); + } + } +} + +void +clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, + unsigned popIndex) +{ + for (FrameIterator it(c, stack, locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, popIndex); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, e, r->value); + } +} + +class JumpEvent: public Event { + public: + JumpEvent(Context* c, lir::UnaryOperation type, Value* address, bool exit, + bool cleanLocals): + Event(c), type(type), address(address), exit(exit), + cleanLocals(cleanLocals) + { + bool thunk; + uint8_t typeMask; + uint64_t registerMask; + c->arch->plan(type, vm::TargetBytesPerWord, &typeMask, ®isterMask, &thunk); + + assert(c, not thunk); + + this->addRead(c, address, SiteMask(typeMask, registerMask, AnyFrameIndex)); + } + + virtual const char* name() { + return "JumpEvent"; + } + + virtual void compile(Context* c) { + if (not this->isUnreachable()) { + apply(c, type, vm::TargetBytesPerWord, address->source, address->source); + } + + for (Read* r = reads; r; r = r->eventNext) { + popRead(c, this, r->value); + } + + if (cleanLocals) { + for (FrameIterator it(c, 0, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, 0); + } + } + } + + virtual bool isBranch() { return true; } + + virtual bool allExits() { + return exit or this->isUnreachable(); + } + + lir::UnaryOperation type; + Value* address; + bool exit; + bool cleanLocals; +}; + +void appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit, bool cleanLocals) { + append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 97686c22cf..d3a171baee 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -143,6 +143,10 @@ 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); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/frame.cpp b/src/codegen/compiler/frame.cpp new file mode 100644 index 0000000000..e879238b79 --- /dev/null +++ b/src/codegen/compiler/frame.cpp @@ -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(c->parameterFootprint)) { + index += c->arch->frameHeaderSize(); + } else { + index -= c->arch->frameFooterSize(); + } + + assert(c, index >= 0); + assert(c, static_cast(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 + ((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 diff --git a/src/codegen/compiler/frame.h b/src/codegen/compiler/frame.h new file mode 100644 index 0000000000..3ae47dfae9 --- /dev/null +++ b/src/codegen/compiler/frame.h @@ -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 diff --git a/src/codegen/compiler/stack.h b/src/codegen/compiler/stack.h deleted file mode 100644 index 7ae8c4f7c1..0000000000 --- a/src/codegen/compiler/stack.h +++ /dev/null @@ -1,35 +0,0 @@ -/* 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_STACK_H -#define AVIAN_CODEGEN_COMPILER_STACK_H - -namespace avian { -namespace codegen { -namespace compiler { - -class Value; - -class Stack { - public: - Stack(unsigned index, Value* value, Stack* next): - index(index), value(value), next(next) - { } - - unsigned index; - Value* value; - Stack* next; -}; - -} // namespace compiler -} // namespace codegen -} // namespace avian - -#endif // AVIAN_CODEGEN_COMPILER_STACK_H