diff --git a/include/avian/codegen/architecture.h b/include/avian/codegen/architecture.h index e3b2c3d27e..0c82fbc207 100644 --- a/include/avian/codegen/architecture.h +++ b/include/avian/codegen/architecture.h @@ -11,6 +11,8 @@ #ifndef AVIAN_CODEGEN_ARCHITECTURE_H #define AVIAN_CODEGEN_ARCHITECTURE_H +#include "ir.h" + namespace vm { class Zone; } @@ -57,6 +59,8 @@ virtual int returnHigh() = 0; virtual int virtualCallTarget() = 0; virtual int virtualCallIndex() = 0; +virtual ir::TargetInfo targetInfo() = 0; + virtual bool bigEndian() = 0; virtual uintptr_t maximumImmediateJump() = 0; diff --git a/include/avian/codegen/compiler.h b/include/avian/codegen/compiler.h index f31d5fc320..099ae15ca5 100644 --- a/include/avian/codegen/compiler.h +++ b/include/avian/codegen/compiler.h @@ -12,8 +12,10 @@ #define AVIAN_CODEGEN_COMPILER_H #include +#include #include "avian/zone.h" #include "assembler.h" +#include "ir.h" namespace avian { namespace codegen { @@ -33,35 +35,22 @@ class Compiler { virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size, unsigned resultSize, bool* threadParameter) = 0; }; - + static const unsigned Aligned = 1 << 0; static const unsigned NoReturn = 1 << 1; static const unsigned TailJump = 1 << 2; static const unsigned LongJumpOrCall = 1 << 3; - enum OperandType { - ObjectType, - AddressType, - IntegerType, - FloatType, - VoidType - }; - - class Operand { }; class State { }; - class Subroutine { }; virtual State* saveState() = 0; virtual void restoreState(State* state) = 0; - virtual Subroutine* startSubroutine() = 0; - virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) - = 0; - virtual void linkSubroutine(Subroutine* subroutine) = 0; - virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint, unsigned localFootprint, unsigned alignedFrameSize) = 0; + virtual void extendLogicalCode(unsigned more) = 0; + virtual void visitLogicalIp(unsigned logicalIp) = 0; virtual void startLogicalIp(unsigned logicalIp) = 0; @@ -70,73 +59,82 @@ class Compiler { virtual Promise* poolAppend(intptr_t value) = 0; virtual Promise* poolAppendPromise(Promise* value) = 0; - virtual Operand* constant(int64_t value, OperandType type) = 0; - virtual Operand* promiseConstant(Promise* value, OperandType type) = 0; - virtual Operand* address(Promise* address) = 0; - virtual Operand* memory(Operand* base, - OperandType type, - int displacement = 0, - Operand* index = 0, - unsigned scale = 1) = 0; + virtual ir::Value* constant(int64_t value, ir::Type type) = 0; + virtual ir::Value* promiseConstant(Promise* value, ir::Type type) = 0; + virtual ir::Value* address(ir::Type type, Promise* address) = 0; + virtual ir::Value* memory(ir::Value* base, + ir::Type type, + int displacement = 0, + ir::Value* index = 0) = 0; - virtual Operand* register_(int number) = 0; + virtual ir::Value* threadRegister() = 0; - virtual void push(unsigned footprint) = 0; - virtual void push(unsigned footprint, Operand* value) = 0; - virtual void save(unsigned footprint, Operand* value) = 0; - virtual Operand* pop(unsigned footprint) = 0; - virtual void pushed() = 0; + virtual void push(ir::Type type, ir::Value* value) = 0; + virtual void save(ir::Type type, ir::Value* value) = 0; + virtual ir::Value* pop(ir::Type type) = 0; + virtual void pushed(ir::Type type) = 0; virtual void popped(unsigned footprint) = 0; virtual unsigned topOfStack() = 0; - virtual Operand* peek(unsigned footprint, unsigned index) = 0; + virtual ir::Value* peek(unsigned footprint, unsigned index) = 0; - virtual Operand* call(Operand* address, - unsigned flags, - TraceHandler* traceHandler, - unsigned resultSize, - OperandType resultType, - unsigned argumentCount, - ...) = 0; + virtual ir::Value* call(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + unsigned argumentCount, + ...) = 0; - virtual Operand* stackCall(Operand* address, - unsigned flags, - TraceHandler* traceHandler, - unsigned resultSize, - OperandType resultType, - unsigned argumentFootprint) = 0; + virtual ir::Value* stackCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + util::Slice arguments) = 0; - virtual void return_(unsigned size, Operand* value) = 0; + virtual void return_(ir::Value* value) = 0; + virtual void return_() = 0; - virtual void initLocal(unsigned size, unsigned index, OperandType type) = 0; + virtual void initLocal(unsigned index, ir::Type type) = 0; virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0; - virtual void storeLocal(unsigned footprint, Operand* src, - unsigned index) = 0; - virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0; + virtual void storeLocal(ir::Value* src, unsigned index) = 0; + virtual ir::Value* loadLocal(ir::Type type, unsigned index) = 0; virtual void saveLocals() = 0; - virtual void checkBounds(Operand* object, unsigned lengthOffset, - Operand* index, intptr_t handler) = 0; + virtual void checkBounds(ir::Value* object, + unsigned lengthOffset, + ir::Value* index, + intptr_t handler) = 0; - virtual void store(unsigned srcSize, Operand* src, unsigned dstSize, - Operand* dst) = 0; - virtual Operand* load(unsigned srcSize, unsigned srcSelectSize, Operand* src, - unsigned dstSize) = 0; - virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src, - unsigned dstSize) = 0; + virtual ir::Value* truncateThenExtend(ir::SignExtendMode signExtend, + ir::Type extendType, + ir::Type truncateType, + ir::Value* src) = 0; + virtual ir::Value* truncate(ir::Type type, ir::Value* src) = 0; - virtual void condJump(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b, Operand* address) = 0; + virtual void store(ir::Value* src, ir::Value* dst) = 0; + virtual ir::Value* load(ir::SignExtendMode signExtend, + ir::Value* src, + ir::Type dstType) = 0; - virtual void jmp(Operand* address) = 0; - virtual void exit(Operand* address) = 0; + virtual void condJump(lir::TernaryOperation op, + ir::Value* a, + ir::Value* b, + ir::Value* address) = 0; - virtual Operand* binaryOp(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b) = 0; - virtual Operand* unaryOp(lir::BinaryOperation type, unsigned size, Operand* a) = 0; - virtual void nullaryOp(lir::Operation type) = 0; + virtual void jmp(ir::Value* address) = 0; + virtual void exit(ir::Value* address) = 0; - virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0; - virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0; - virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0; + virtual ir::Value* binaryOp(lir::TernaryOperation op, + ir::Type type, + ir::Value* a, + ir::Value* b) = 0; + virtual ir::Value* unaryOp(lir::BinaryOperation op, + ir::Value* a) = 0; + virtual void nullaryOp(lir::Operation op) = 0; + + virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0; + virtual ir::Value* f2i(ir::Type resType, ir::Value* a) = 0; + virtual ir::Value* i2f(ir::Type resType, ir::Value* a) = 0; virtual void compile(uintptr_t stackOverflowHandler, unsigned stackLimitOffset) = 0; diff --git a/include/avian/codegen/ir.h b/include/avian/codegen/ir.h new file mode 100644 index 0000000000..8b2b48aa9d --- /dev/null +++ b/include/avian/codegen/ir.h @@ -0,0 +1,157 @@ +/* Copyright (c) 2008-2014, 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_IR_H +#define AVIAN_CODEGEN_IR_H + +namespace avian { +namespace codegen { +namespace ir { + +class TargetInfo { + public: + unsigned pointerSize; + + explicit TargetInfo(unsigned pointerSize) : pointerSize(pointerSize) + { + } +}; + +class Type { + public: + enum Flavor { + // A GC-visiible reference + Object, + + // GC-invisible types + Integer, + Float, + Address, + + // Represents individual halves of two-word types + // (double/long on 32-bit systems) + // TODO: remove when possible + Half, + + // Represents the lack of a return value + // TODO: remove when possible + Void, + }; + + typedef int16_t TypeDesc; + +#define TY_DESC(flavor, size) ((flavor & 0xff) | ((size & 0xff) << 8)) + // TODO: once we upgrade to c++11, these should become plain constants (rather + // than function calls). + // The constructor will need to be declared 'constexpr'. + static inline Type void_() + { + return TY_DESC(Void, 0); + } + static inline Type object() + { + return TY_DESC(Object, -1); + } + static inline Type iptr() + { + return TY_DESC(Integer, -1); + } + static inline Type i1() + { + return TY_DESC(Integer, 1); + } + static inline Type i2() + { + return TY_DESC(Integer, 2); + } + static inline Type i4() + { + return TY_DESC(Integer, 4); + } + static inline Type i8() + { + return TY_DESC(Integer, 8); + } + static inline Type f4() + { + return TY_DESC(Float, 4); + } + static inline Type f8() + { + return TY_DESC(Float, 8); + } + static inline Type addr() + { + return TY_DESC(Address, -1); + } +#undef TY_DESC + + private: + TypeDesc desc; + + friend class Types; + + // TODO: once we move to c++11, declare this 'constexpr', to allow + // compile-time constants of this type. + /* constexpr */ Type(TypeDesc desc) : desc(desc) + { + } + + public: + inline Flavor flavor() const + { + return (Flavor)(desc & 0xff); + } + + // If the size isn't known without inspecting the TargetInfo, returns -1. + // Otherwise, matches size(TargetInfo). + inline int rawSize() const + { + return desc >> 8; + } + + inline unsigned size(const TargetInfo& t) const + { + int s = rawSize(); + if (s < 0) { + return t.pointerSize; + } + return (unsigned)s; + } + + inline bool operator==(const Type& other) const + { + return desc == other.desc; + } + + inline bool operator!=(const Type& other) const + { + return !(*this == other); + } +}; + +enum SignExtendMode { SignExtend, ZeroExtend }; + +enum CallingConvention { NativeCallingConvention, AvianCallingConvention }; + +class Value { + public: + ir::Type type; + + Value(ir::Type type) : type(type) + { + } +}; + +} // namespace ir +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_IR_H diff --git a/include/avian/util/assert.h b/include/avian/util/assert.h new file mode 100644 index 0000000000..ab6cee63ed --- /dev/null +++ b/include/avian/util/assert.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2008-2013, 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_ASSERT_H +#define AVIAN_UTIL_ASSERT_H + +#include + +namespace avian { +namespace util { + +#define UNREACHABLE_ ::abort() + +// TODO: print msg in debug mode +#define UNREACHABLE(msg) ::abort() + +#define ASSERT(that) \ + if (!(that)) { \ + UNREACHABLE(#that); \ + } + +} // namespace util +} // namespace avian + +#endif // AVIAN_UTIL_ASSERT_H diff --git a/include/avian/util/slice.h b/include/avian/util/slice.h index b4936e0a06..51b1ad918e 100644 --- a/include/avian/util/slice.h +++ b/include/avian/util/slice.h @@ -13,6 +13,7 @@ #include "allocator.h" #include "math.h" +#include "assert.h" namespace avian { namespace util { @@ -33,6 +34,7 @@ class Slice { inline T& operator[](size_t index) { + ASSERT(index < count); return items[index]; } @@ -51,20 +53,36 @@ class Slice { return Slice((T*)a->allocate(sizeof(T) * count), count); } - Slice clone(Allocator* a) + static Slice allocAndSet(Allocator* a, size_t count, const T& item) { - Slice ret((T*)a->allocate(count * sizeof(T)), count); - memcpy(ret.items, items, count * sizeof(T)); - return ret; + Slice slice(alloc(a, count)); + for (size_t i = 0; i < count; i++) { + slice[i] = item; + } + return slice; + } + + Slice clone(Allocator* a, size_t newCount) + { + T* newItems = (T*)a->allocate(newCount * sizeof(T)); + memcpy(newItems, items, min(count, newCount) * sizeof(T)); + return Slice(newItems, newCount); + } + + Slice cloneAndSet(Allocator* a, size_t newCount, const T& item) + { + Slice slice(clone(a, newCount)); + for (size_t i = count; i < newCount; i++) { + slice[i] = item; + } + return slice; } void resize(Allocator* a, size_t newCount) { - T* newItems = (T*)a->allocate(newCount * sizeof(T)); - memcpy(newItems, items, min(count, newCount)); + Slice slice(clone(a, newCount)); a->free(items, count); - items = newItems; - count = newCount; + *this = slice; } }; diff --git a/makefile b/makefile index be60f70694..82e08e1981 100755 --- a/makefile +++ b/makefile @@ -1125,6 +1125,7 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed)) compiler-sources = \ $(src)/codegen/compiler.cpp \ $(wildcard $(src)/codegen/compiler/*.cpp) \ + $(src)/debug-util.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/runtime.cpp \ $(src)/codegen/targets.cpp \ diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index d987912257..16972c61c7 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -156,7 +156,7 @@ popRead(Context* c, Event* e UNUSED, Value* v) if (valid(nextWord->reads)) { deadWord(c, v); } else { - deadWord(c, nextWord); + deadWord(c, nextWord); } } @@ -186,22 +186,6 @@ addBuddy(Value* original, Value* buddy) } } -lir::ValueType -valueType(Context* c, Compiler::OperandType type) -{ - switch (type) { - case Compiler::ObjectType: - case Compiler::AddressType: - case Compiler::IntegerType: - case Compiler::VoidType: - return lir::ValueGeneral; - case Compiler::FloatType: - return lir::ValueFloat; - default: - abort(c); - } -} - void move(Context* c, Value* value, Site* src, Site* dst); @@ -751,10 +735,14 @@ saveLocals(Context* c, Event* e) } } -void -maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue, - const SiteMask& dstMask) +void maybeMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue, + const SiteMask& dstMask) { Read* read = live(c, dstValue); bool isStore = read == 0; @@ -806,8 +794,14 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, srcValue->source->freeze(c, srcValue); - apply(c, type, min(srcSelectSize, dstSize), srcValue->source, srcValue->source, - dstSize, target, target); + apply(c, + op, + min(srcSelectSize, dstSize), + srcValue->source, + srcValue->source, + dstSize, + target, + target); srcValue->source->thaw(c, srcValue); } else { @@ -819,9 +813,9 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, bool thunk; OperandMask src; - c->arch->planSource(type, dstSize, src, dstSize, &thunk); + c->arch->planSource(op, dstSize, src, dstSize, &thunk); - if (srcValue->type == lir::ValueGeneral) { + if (isGeneralValue(srcValue)) { src.registerMask &= c->regFile->generalRegisters.mask; } @@ -844,8 +838,14 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, srcb, dstb, srcValue, dstValue); } - apply(c, type, srcSelectSize, srcValue->source, srcValue->source, - dstSize, tmpTarget, tmpTarget); + apply(c, + op, + srcSelectSize, + srcValue->source, + srcValue->source, + dstSize, + tmpTarget, + tmpTarget); tmpTarget->thaw(c, dstValue); @@ -1214,9 +1214,27 @@ storeLocal(Context* c, unsigned footprint, Value* v, unsigned index, bool copy) return v; } -Value* -loadLocal(Context* c, unsigned footprint, unsigned index) +unsigned typeFootprint(Context* c, ir::Type type) { + // TODO: this function is very Java-specific in nature. Generalize. + switch (type.flavor()) { + case ir::Type::Float: + case ir::Type::Integer: + return type.rawSize() / 4; + case ir::Type::Object: + case ir::Type::Address: + case ir::Type::Half: + return 1; + case ir::Type::Void: + return 0; + default: + abort(c); + } +} + +Value* loadLocal(Context* c, ir::Type type, unsigned index) +{ + unsigned footprint = typeFootprint(c, type); assert(c, index + footprint <= c->localFootprint); if (footprint > 1) { @@ -1237,17 +1255,10 @@ loadLocal(Context* c, unsigned footprint, unsigned index) return c->locals[index].value; } -Value* -register_(Context* c, int number) +Value* threadRegister(Context* c) { - assert(c, (1 << number) & (c->regFile->generalRegisters.mask - | c->regFile->floatRegisters.mask)); - - Site* s = registerSite(c, number); - lir::ValueType type = ((1 << number) & c->regFile->floatRegisters.mask) - ? lir::ValueFloat: lir::ValueGeneral; - - return value(c, type, s, s); + Site* s = registerSite(c, c->arch->thread()); + return value(c, ir::Type::addr(), s, s); } unsigned @@ -1506,8 +1517,8 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen, fprintf(stderr, "freeze original %s for %p local %d frame %d\n", buffer, v, el.localIndex, el.frameIndex(c)); } - - Value dummy(0, 0, lir::ValueGeneral); + + Value dummy(0, 0, ir::Type::addr()); dummy.addSite(c, s); dummy.removeSite(c, s); freeze(c, frozen, s, 0); @@ -2129,26 +2140,9 @@ class MyCompiler: public Compiler { compiler::restoreState(&c, static_cast(state)); } - virtual Subroutine* startSubroutine() { - return c.subroutine = new(c.zone) MySubroutine; - } - - virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { - appendSaveLocals(&c); - appendJump(&c, lir::Jump, static_cast(address), false, true); - static_cast(subroutine)->forkState = compiler::saveState(&c); - } - - virtual void linkSubroutine(Subroutine* subroutine) { - Local* oldLocals = c.locals; - restoreState(static_cast(subroutine)->forkState); - linkLocals(&c, oldLocals, c.locals); - } - virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint, unsigned localFootprint, unsigned alignedFrameSize) { - c.logicalCodeLength = logicalCodeLength; c.parameterFootprint = parameterFootprint; c.localFootprint = localFootprint; c.alignedFrameSize = alignedFrameSize; @@ -2167,23 +2161,23 @@ class MyCompiler: public Compiler { c.frameResources[base + c.arch->framePointerOffset()].reserved = UseFramePointer; - // leave room for logical instruction -1 - unsigned codeSize = sizeof(LogicalInstruction*) * (logicalCodeLength + 1); - c.logicalCode = static_cast - (c.zone->allocate(codeSize)); - memset(c.logicalCode, 0, codeSize); - c.logicalCode++; + c.logicalCode.init(c.zone, logicalCodeLength); + + c.logicalCode[-1] = new (c.zone) LogicalInstruction(-1, c.stack, c.locals); c.locals = static_cast (c.zone->allocate(sizeof(Local) * localFootprint)); memset(c.locals, 0, sizeof(Local) * localFootprint); + } - c.logicalCode[-1] = new(c.zone) LogicalInstruction(-1, c.stack, c.locals); + virtual void extendLogicalCode(unsigned more) + { + c.logicalCode.extend(c.zone, more); } virtual void visitLogicalIp(unsigned logicalIp) { - assert(&c, logicalIp < c.logicalCodeLength); + assert(&c, logicalIp < c.logicalCode.count()); if (c.logicalCode[c.logicalIp]->lastEvent == 0) { appendDummy(&c); @@ -2215,17 +2209,11 @@ class MyCompiler: public Compiler { populateJunctionReads(&c, link); } - if (c.subroutine) { - c.subroutine->forkState - = c.logicalCode[logicalIp]->subroutine->forkState; - c.subroutine = 0; - } - c.forkState = 0; } virtual void startLogicalIp(unsigned logicalIp) { - assert(&c, logicalIp < c.logicalCodeLength); + assert(&c, logicalIp < c.logicalCode.count()); assert(&c, c.logicalCode[logicalIp] == 0); if (c.logicalCode[c.logicalIp]->lastEvent == 0) { @@ -2240,30 +2228,7 @@ class MyCompiler: public Compiler { c.logicalCode[logicalIp] = new(c.zone) LogicalInstruction(logicalIp, c.stack, c.locals); - bool startSubroutine = c.subroutine != 0; - if (startSubroutine) { - c.logicalCode[logicalIp]->subroutine = c.subroutine; - c.subroutine = 0; - } - c.logicalIp = logicalIp; - - if (startSubroutine) { - // assume all local variables are initialized on entry to a - // subroutine, since other calls to the subroutine may - // initialize them: - unsigned sizeInBytes = sizeof(Local) * c.localFootprint; - Local* newLocals = static_cast(c.zone->allocate(sizeInBytes)); - memcpy(newLocals, c.locals, sizeInBytes); - c.locals = newLocals; - - for (unsigned li = 0; li < c.localFootprint; ++li) { - Local* local = c.locals + li; - if (local->value == 0) { - initLocal(1, li, IntegerType); - } - } - } } virtual Promise* machineIp(unsigned logicalIp) { @@ -2290,71 +2255,82 @@ class MyCompiler: public Compiler { return p; } - virtual Operand* constant(int64_t value, Compiler::OperandType type) { + virtual ir::Value* constant(int64_t value, ir::Type type) + { return promiseConstant(resolvedPromise(&c, value), type); } - virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) { - return compiler::value - (&c, valueType(&c, type), compiler::constantSite(&c, value)); - } - - virtual Operand* address(Promise* address) { - return value(&c, lir::ValueGeneral, compiler::addressSite(&c, address)); - } - - virtual Operand* memory(Operand* base, - OperandType type, - int displacement = 0, - Operand* index = 0, - unsigned scale = 1) + virtual ir::Value* promiseConstant(Promise* value, ir::Type type) { - Value* result = value(&c, valueType(&c, type)); + return compiler::value(&c, type, compiler::constantSite(&c, value)); + } - appendMemory(&c, static_cast(base), displacement, - static_cast(index), scale, result); + virtual ir::Value* address(ir::Type type, Promise* address) + { + return value(&c, type, compiler::addressSite(&c, address)); + } + + virtual ir::Value* memory(ir::Value* base, + ir::Type type, + int displacement = 0, + ir::Value* index = 0) + { + Value* result = value(&c, type); + + appendMemory(&c, + static_cast(base), + displacement, + static_cast(index), + index == 0 ? 1 : type.size(c.targetInfo), + result); return result; } - virtual Operand* register_(int number) { - return compiler::register_(&c, number); + virtual ir::Value* threadRegister() + { + return compiler::threadRegister(&c); } Promise* machineIp() { return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c); } - virtual void push(unsigned footprint UNUSED) { - assert(&c, footprint == 1); - - Value* v = value(&c, lir::ValueGeneral); - Stack* s = compiler::stack(&c, v, c.stack); - - v->home = frameIndex(&c, s->index + c.localFootprint); - c.stack = s; + virtual void push(ir::Type type, ir::Value* value) + { + // TODO: once type information is flowed properly, enable this assert. + // Some time later, we can remove the parameter. + // assert(&c, value->type == type); + compiler::push(&c, typeFootprint(&c, type), static_cast(value)); } - virtual void push(unsigned footprint, Operand* value) { - compiler::push(&c, footprint, static_cast(value)); - } - - virtual void save(unsigned footprint, Operand* value) { + virtual void save(ir::Type type, ir::Value* value) + { + // TODO: once type information is flowed properly, enable this assert. + // Some time later, we can remove the parameter. + // assert(&c, value->type == type); + unsigned footprint = typeFootprint(&c, type); c.saved = cons(&c, static_cast(value), c.saved); if (TargetBytesPerWord == 4 and footprint > 1) { assert(&c, footprint == 2); assert(&c, static_cast(value)->nextWord); - save(1, static_cast(value)->nextWord); + save(ir::Type::i4(), static_cast(value)->nextWord); } } - virtual Operand* pop(unsigned footprint) { - return compiler::pop(&c, footprint); + virtual ir::Value* pop(ir::Type type) + { + ir::Value* value = compiler::pop(&c, typeFootprint(&c, type)); + // TODO: once type information is flowed properly, enable this assert. + // Some time later, we can remove the parameter. + // assert(&c, static_cast(value)->type == type); + return value; } - virtual void pushed() { - Value* v = value(&c, lir::ValueGeneral); + virtual void pushed(ir::Type type) + { + Value* v = value(&c, type); appendFrameSite (&c, v, frameIndex (&c, (c.stack ? c.stack->index : 0) + c.localFootprint)); @@ -2380,7 +2356,8 @@ class MyCompiler: public Compiler { return c.stack->index; } - virtual Operand* peek(unsigned footprint, unsigned index) { + virtual ir::Value* peek(unsigned footprint, unsigned index) + { Stack* s = c.stack; for (unsigned i = index; i > 0; --i) { s = s->next; @@ -2416,13 +2393,12 @@ class MyCompiler: public Compiler { return s->value; } - virtual Operand* call(Operand* address, - unsigned flags, - TraceHandler* traceHandler, - unsigned resultSize, - OperandType resultType, - unsigned argumentCount, - ...) + virtual ir::Value* call(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + unsigned argumentCount, + ...) { va_list a; va_start(a, argumentCount); @@ -2430,7 +2406,7 @@ class MyCompiler: public Compiler { unsigned footprint = 0; unsigned size = TargetBytesPerWord; - RUNTIME_ARRAY(Value*, arguments, argumentCount); + RUNTIME_ARRAY(ir::Value*, arguments, argumentCount); int index = 0; for (unsigned i = 0; i < argumentCount; ++i) { Value* o = va_arg(a, Value*); @@ -2452,41 +2428,74 @@ class MyCompiler: public Compiler { va_end(a); - Stack* argumentStack = c.stack; - for (int i = index - 1; i >= 0; --i) { - argumentStack = compiler::stack - (&c, RUNTIME_ARRAY_BODY(arguments)[i], argumentStack); + Value* result = value(&c, resultType); + appendCall(&c, + static_cast(address), + ir::NativeCallingConvention, + flags, + traceHandler, + result, + util::Slice(RUNTIME_ARRAY_BODY(arguments), index)); + + return result; + } + + virtual ir::Value* stackCall(ir::Value* address, + unsigned flags, + TraceHandler* traceHandler, + ir::Type resultType, + Slice arguments) + { + Value* result = value(&c, resultType); + Stack* b UNUSED = c.stack; + appendCall(&c, + static_cast(address), + ir::AvianCallingConvention, + flags, + traceHandler, + result, + arguments); + assert(&c, c.stack == b); + return result; + } + + virtual void return_(ir::Value* a) + { + assert(&c, a); + appendReturn(&c, static_cast(a)); + } + + virtual void return_() + { + appendReturn(&c, 0); + } + + void initLocalPart(unsigned index, ir::Type type) + { + Value* v = value(&c, type); + + if (DebugFrame) { + fprintf(stderr, + "init local %p at %d (%d)\n", + v, + index, + frameIndex(&c, index)); } - Value* result = value(&c, valueType(&c, resultType)); - appendCall(&c, static_cast(address), flags, traceHandler, result, - resultSize, argumentStack, index, 0); + appendFrameSite(&c, v, frameIndex(&c, index)); - return result; + Local* local = c.locals + index; + local->value = v; + v->home = frameIndex(&c, index); } - virtual Operand* stackCall(Operand* address, - unsigned flags, - TraceHandler* traceHandler, - unsigned resultSize, - OperandType resultType, - unsigned argumentFootprint) + virtual void initLocal(unsigned index, ir::Type type) { - Value* result = value(&c, valueType(&c, resultType)); - appendCall(&c, static_cast(address), flags, traceHandler, result, - resultSize, c.stack, 0, argumentFootprint); - return result; - } + unsigned footprint = typeFootprint(&c, type); - virtual void return_(unsigned size, Operand* value) { - appendReturn(&c, size, static_cast(value)); - } - - virtual void initLocal(unsigned footprint, unsigned index, OperandType type) - { assert(&c, index + footprint <= c.localFootprint); - Value* v = value(&c, valueType(&c, type)); + Value* v = value(&c, type); if (footprint > 1) { assert(&c, footprint == 2); @@ -2498,11 +2507,11 @@ class MyCompiler: public Compiler { lowIndex = index; } else { lowIndex = index + 1; - highIndex = index; + highIndex = index; } if (TargetBytesPerWord == 4) { - initLocal(1, highIndex, type); + initLocalPart(highIndex, type); Value* next = c.locals[highIndex].value; v->nextWord = next; next->nextWord = v; @@ -2525,7 +2534,7 @@ class MyCompiler: public Compiler { } virtual void initLocalsFromLogicalIp(unsigned logicalIp) { - assert(&c, logicalIp < c.logicalCodeLength); + assert(&c, logicalIp < c.logicalCode.count()); unsigned footprint = sizeof(Local) * c.localFootprint; Local* newLocals = static_cast(c.zone->allocate(footprint)); @@ -2536,127 +2545,203 @@ class MyCompiler: public Compiler { for (int i = 0; i < static_cast(c.localFootprint); ++i) { Local* local = e->locals() + i; if (local->value) { - initLocal - (1, i, local->value->type == lir::ValueGeneral ? IntegerType : FloatType); + initLocalPart(i, local->value->type); } } linkLocals(&c, e->locals(), newLocals); } - virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) { - compiler::storeLocal(&c, footprint, static_cast(src), index, true); + virtual void storeLocal(ir::Value* src, unsigned index) + { + compiler::storeLocal(&c, typeFootprint(&c, src->type), static_cast(src), index, true); } - virtual Operand* loadLocal(unsigned footprint, unsigned index) { - return compiler::loadLocal(&c, footprint, index); + virtual ir::Value* loadLocal(ir::Type type, unsigned index) + { + return compiler::loadLocal(&c, type, index); } virtual void saveLocals() { + int oldIp UNUSED = c.logicalIp; appendSaveLocals(&c); + assert(&c, oldIp == c.logicalIp); } - virtual void checkBounds(Operand* object, unsigned lengthOffset, - Operand* index, intptr_t handler) + virtual void checkBounds(ir::Value* object, + unsigned lengthOffset, + ir::Value* index, + intptr_t handler) { appendBoundsCheck(&c, static_cast(object), lengthOffset, static_cast(index), handler); } - virtual void store(unsigned srcSize, Operand* src, unsigned dstSize, - Operand* dst) + virtual ir::Value* truncate(ir::Type type, ir::Value* src) { - appendMove(&c, lir::Move, srcSize, srcSize, static_cast(src), - dstSize, static_cast(dst)); - } - - virtual Operand* load(unsigned srcSize, unsigned srcSelectSize, Operand* src, - unsigned dstSize) - { - assert(&c, dstSize >= TargetBytesPerWord); - - Value* dst = value(&c, static_cast(src)->type); - appendMove(&c, lir::Move, srcSize, srcSelectSize, static_cast(src), - dstSize, dst); + assert(&c, src->type.flavor() == type.flavor()); + assert(&c, type.flavor() != ir::Type::Float); + assert(&c, type.rawSize() < src->type.rawSize()); + Value* dst = value(&c, type); + appendMove(&c, + lir::Move, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + type.size(c.targetInfo), + dst); return dst; } - virtual Operand* loadz(unsigned srcSize, unsigned srcSelectSize, - Operand* src, unsigned dstSize) + virtual ir::Value* truncateThenExtend(ir::SignExtendMode signExtend, + ir::Type extendType, + ir::Type truncateType, + ir::Value* src) { - assert(&c, dstSize >= TargetBytesPerWord); - - Value* dst = value(&c, static_cast(src)->type); - appendMove(&c, lir::MoveZ, srcSize, srcSelectSize, static_cast(src), - dstSize, dst); + Value* dst = value(&c, extendType); + appendMove(&c, + signExtend == ir::SignExtend ? lir::Move : lir::MoveZ, + TargetBytesPerWord, + truncateType.size(c.targetInfo), + static_cast(src), + extendType.size(c.targetInfo) < TargetBytesPerWord + ? TargetBytesPerWord + : extendType.size(c.targetInfo), + dst); return dst; } - virtual void condJump(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b, - Operand* address) + virtual void store(ir::Value* src, ir::Value* dst) + { + assert(&c, src->type.flavor() == dst->type.flavor()); + + appendMove(&c, + lir::Move, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + dst->type.size(c.targetInfo), + static_cast(dst)); + } + + virtual ir::Value* load(ir::SignExtendMode signExtend, + ir::Value* src, + ir::Type dstType) + { + assert(&c, src->type.flavor() == dstType.flavor()); + + Value* dst = value(&c, dstType); + appendMove(&c, + signExtend == ir::SignExtend ? lir::Move : lir::MoveZ, + src->type.size(c.targetInfo), + src->type.size(c.targetInfo), + static_cast(src), + dstType.size(c.targetInfo) < TargetBytesPerWord + ? TargetBytesPerWord + : dstType.size(c.targetInfo), + dst); + return dst; + } + + virtual void condJump(lir::TernaryOperation op, + ir::Value* a, + ir::Value* b, + ir::Value* addr) { assert(&c, - (isGeneralBranch(type) and isGeneralValue(a) and isGeneralValue(b)) - or (isFloatBranch(type) and isFloatValue(a) and isFloatValue(b))); + (isGeneralBranch(op) and isGeneralValue(a) and isGeneralValue(b))or( + isFloatBranch(op) and isFloatValue(a) and isFloatValue(b))); - appendBranch(&c, type, size, static_cast(a), - static_cast(b), static_cast(address)); + assert(&c, a->type == b->type); + assert(&c, addr->type == ir::Type::iptr()); + + appendBranch(&c, + op, + static_cast(a), + static_cast(b), + static_cast(addr)); } - virtual void jmp(Operand* address) { - appendJump(&c, lir::Jump, static_cast(address)); + virtual void jmp(ir::Value* addr) + { + appendJump(&c, lir::Jump, static_cast(addr)); } - virtual void exit(Operand* address) { - appendJump(&c, lir::Jump, static_cast(address), true); + virtual void exit(ir::Value* addr) + { + appendJump(&c, lir::Jump, static_cast(addr), true); } - virtual Operand* binaryOp(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b) { + virtual ir::Value* binaryOp(lir::TernaryOperation op, + ir::Type type, + ir::Value* a, + ir::Value* b) + { assert(&c, - (isGeneralBinaryOp(type) and isGeneralValue(a) and isGeneralValue(b)) - or (isFloatBinaryOp(type) and isFloatValue(a) and isFloatValue(b))); + (isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b)) + or(isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b))); - Value* result = value(&c, static_cast(a)->type); - - appendCombine(&c, type, size, static_cast(a), - size, static_cast(b), size, result); + Value* result = value(&c, type); + + appendCombine(&c, + op, + static_cast(a), + static_cast(b), + result); return result; } - virtual Operand* unaryOp(lir::BinaryOperation type, unsigned size, Operand* a) { - assert(&c, (isGeneralUnaryOp(type) and isGeneralValue(a))or( - isFloatUnaryOp(type) and isFloatValue(a))); - Value* result = value(&c, static_cast(a)->type); - appendTranslate(&c, type, size, static_cast(a), size, result); - return result; - } - - virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == lir::ValueFloat); - Value* result = value(&c, lir::ValueFloat); - appendTranslate - (&c, lir::Float2Float, aSize, static_cast(a), resSize, result); - return result; - } - - virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == lir::ValueFloat); - Value* result = value(&c, lir::ValueGeneral); - appendTranslate - (&c, lir::Float2Int, aSize, static_cast(a), resSize, result); - return result; - } - - virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) { - assert(&c, static_cast(a)->type == lir::ValueGeneral); - Value* result = value(&c, lir::ValueFloat); - appendTranslate - (&c, lir::Int2Float, aSize, static_cast(a), resSize, result); + virtual ir::Value* unaryOp(lir::BinaryOperation op, + ir::Value* a) + { + assert(&c, + (isGeneralUnaryOp(op) and isGeneralValue(a))or(isFloatUnaryOp(op) + and isFloatValue(a))); + Value* result = value(&c, a->type); + appendTranslate( + &c, op, static_cast(a), result); return result; } - virtual void nullaryOp(lir::Operation type) { - appendOperation(&c, type); + virtual ir::Value* f2f(ir::Type resType, ir::Value* a) + { + assert(&c, isFloatValue(a)); + assert(&c, resType.flavor() == ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, + lir::Float2Float, + static_cast(a), + result); + return result; + } + + virtual ir::Value* f2i(ir::Type resType, ir::Value* a) + { + assert(&c, isFloatValue(a)); + assert(&c, resType.flavor() != ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, + lir::Float2Int, + static_cast(a), + result); + return result; + } + + virtual ir::Value* i2f(ir::Type resType, ir::Value* a) + { + assert(&c, isGeneralValue(a)); + assert(&c, resType.flavor() == ir::Type::Float); + Value* result = value(&c, resType); + appendTranslate(&c, + lir::Int2Float, + static_cast(a), + result); + return result; + } + + virtual void nullaryOp(lir::Operation op) + { + appendOperation(&c, op); } virtual void compile(uintptr_t stackOverflowHandler, diff --git a/src/codegen/compiler/context.cpp b/src/codegen/compiler/context.cpp index be316d0330..404b9aba28 100644 --- a/src/codegen/compiler/context.cpp +++ b/src/codegen/compiler/context.cpp @@ -17,41 +17,41 @@ 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 - (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) +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), + regFile(arch->registerFile()), + regAlloc(system, arch->registerFile()), + registerResources(static_cast(zone->allocate( + sizeof(RegisterResource) * regFile->allRegisters.limit))), + frameResources(0), + acquiredResources(0), + firstConstant(0), + lastConstant(0), + machineCode(0), + firstEvent(0), + lastEvent(0), + forkState(0), + firstBlock(0), + logicalIp(-1), + constantCount(0), + parameterFootprint(0), + localFootprint(0), + machineCodeSize(0), + alignedFrameSize(0), + availableGeneralRegisterCount(regFile->generalRegisters.limit + - regFile->generalRegisters.start), + targetInfo(arch->targetInfo()) { for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) { new (registerResources + i) RegisterResource(arch->reserved(i)); diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 47404eefbc..03708f39c1 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -35,7 +35,6 @@ class FrameResource; class ConstantPoolNode; class ForkState; -class MySubroutine; class Block; template @@ -50,6 +49,48 @@ List* reverseDestroy(List* cell) { return previous; } +class LogicalCode { + private: + util::Slice logicalCode; + + public: + LogicalCode() : logicalCode(0, 0) + { + } + + void init(vm::Zone* zone, size_t count) + { + // leave room for logical instruction -1 + size_t realCount = count + 1; + + logicalCode + = util::Slice::allocAndSet(zone, realCount, 0); + } + + void extend(vm::Zone* zone, size_t more) + { + util::Slice newCode + = logicalCode.cloneAndSet(zone, logicalCode.count + more, 0); + + for (size_t i = 0; i < logicalCode.count; i++) { + assert((vm::System*)0, logicalCode[i] == newCode[i]); + } + + logicalCode = newCode; + } + + size_t count() + { + return logicalCode.count - 1; + } + + LogicalInstruction*& operator[](int index) + { + // leave room for logical instruction -1 + return logicalCode[index + 1]; + } +}; + class Context { public: Context(vm::System* system, Assembler* assembler, vm::Zone* zone, @@ -64,7 +105,7 @@ class Context { Local* locals; List* saved; Event* predecessor; - LogicalInstruction** logicalCode; + LogicalCode logicalCode; const RegisterFile* regFile; RegisterAllocator regAlloc; RegisterResource* registerResources; @@ -76,16 +117,15 @@ class Context { 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; + ir::TargetInfo targetInfo; }; inline Aborter* getAborter(Context* c) { diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 51eaff85c7..44685f3cc0 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -60,10 +60,14 @@ Read* live(Context* c UNUSED, Value* v); void popRead(Context* c, Event* e UNUSED, Value* v); -void -maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst, - const SiteMask& dstMask); +void maybeMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* src, + unsigned dstSize, + Value* dst, + const SiteMask& dstMask); Site* maybeMove(Context* c, Value* v, const SiteMask& mask, bool intersectMask, @@ -76,14 +80,11 @@ Site* pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, unsigned index); -void push(Context* c, unsigned footprint, Value* v); - Site* pickTargetSite(Context* c, Read* read, bool intersectRead = false, unsigned registerReserveCount = 0, CostCalculator* costCalculator = 0); -Value* -register_(Context* c, int number); +Value* threadRegister(Context* c); Event::Event(Context* c): next(0), stackBefore(c->stack), localsBefore(c->locals), @@ -129,7 +130,7 @@ void Event::addReads(Context* c, Value* v, unsigned size, { SingleRead* r = read(c, lowMask, lowSuccessor); this->addRead(c, v, r); - if (size > vm::TargetBytesPerWord) { + if (size > c->targetInfo.pointerSize) { r->high_ = v->nextWord; this->addRead(c, v->nextWord, highMask, highSuccessor); } @@ -185,40 +186,149 @@ Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* success (predecessor, nextPredecessor, successor, nextSuccessor, forkState); } +Value* maybeBuddySlice(Context* c, Value* v) +{ + if (v->home >= 0) { + Value* n = value(c, v->type); + appendBuddy(c, v, n); + return n; + } else { + return v; + } +} + +template +struct SliceStack : public Slice { + size_t capacity; + + SliceStack(T* items, size_t capacity) + : Slice(items + capacity, 0), capacity(capacity) + { + } + + void push(const T& item) + { + ASSERT(Slice::count < capacity); + --Slice::items; + ++Slice::count; + *Slice::items = item; + } +}; + +template +struct FixedSliceStack : public SliceStack { + T itemArray[Capacity]; + + FixedSliceStack() : SliceStack(&itemArray[0], Capacity) + { + } +}; + +Value* slicePushWord(Context* c, + Value* v, + size_t stackBase UNUSED, + SliceStack& slice) +{ + if (v) { + v = maybeBuddySlice(c, v); + } + + size_t index UNUSED = slice.count; + + assert(c, slice.count < slice.capacity); + slice.push(v); + + // if (DebugFrame) { + // fprintf(stderr, "push %p\n", v); + // } + + if (v) { + v->home = frameIndex(c, index + stackBase + c->localFootprint); + } + + return v; +} + +void slicePush(Context* c, + unsigned footprint, + Value* v, + size_t stackBase, + SliceStack& slice) +{ + assert(c, footprint); + + bool bigEndian = c->arch->bigEndian(); + + Value* low = v; + + if (bigEndian) { + v = slicePushWord(c, v, stackBase, slice); + } + + Value* high; + if (footprint > 1) { + assert(c, footprint == 2); + + if (c->targetInfo.pointerSize == 4) { + low->maybeSplit(c); + high = slicePushWord(c, low->nextWord, stackBase, slice); + } else { + high = slicePushWord(c, 0, stackBase, slice); + } + } else { + high = 0; + } + + if (not bigEndian) { + v = slicePushWord(c, v, stackBase, slice); + } + + if (high) { + v->nextWord = high; + high->nextWord = v; + high->wordIndex = 1; + } +} class CallEvent: public Event { public: - CallEvent(Context* c, Value* address, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, - Stack* argumentStack, unsigned argumentCount, - unsigned stackArgumentFootprint): - Event(c), - address(address), - traceHandler(traceHandler), - result(result), - returnAddressSurrogate(0), - framePointerSurrogate(0), - popIndex(0), - stackArgumentIndex(0), - flags(flags), - resultSize(resultSize), - stackArgumentFootprint(stackArgumentFootprint) + CallEvent(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* resultValue, + util::Slice arguments) + : Event(c), + address(address), + traceHandler(traceHandler), + resultValue(resultValue), + returnAddressSurrogate(0), + framePointerSurrogate(0), + popIndex(0), + stackArgumentIndex(0), + flags(flags), + stackArgumentFootprint(callingConvention == ir::AvianCallingConvention + ? arguments.count + : 0) { uint32_t registerMask = c->regFile->generalRegisters.mask; - if (argumentCount) { + if (callingConvention == ir::NativeCallingConvention) { assert(c, (flags & Compiler::TailJump) == 0); assert(c, stackArgumentFootprint == 0); - Stack* s = argumentStack; unsigned index = 0; unsigned argumentIndex = 0; while (true) { + Value* v = static_cast(arguments[index]); + unsigned footprint - = (argumentIndex + 1 < argumentCount - and s->value->nextWord == s->next->value) - ? 2 : 1; + = (argumentIndex + 1 < arguments.count and v->nextWord + == arguments[index + 1]) + ? 2 + : 1; if (index % (c->arch->argumentAlignment() ? footprint : 1)) { ++ index; @@ -229,9 +339,9 @@ class CallEvent: public Event { <= c->arch->argumentRegisterCount()) { int number = c->arch->argumentRegister(index); - + if (DebugReads) { - fprintf(stderr, "reg %d arg read %p\n", number, s->value); + fprintf(stderr, "reg %d arg read %p\n", number, v); } targetMask = SiteMask::fixedRegisterMask(number); @@ -244,19 +354,17 @@ class CallEvent: public Event { unsigned frameIndex = index - c->arch->argumentRegisterCount(); if (DebugReads) { - fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value); + fprintf(stderr, "stack %d arg read %p\n", frameIndex, v); } targetMask = SiteMask(1 << lir::MemoryOperand, 0, frameIndex); } - this->addRead(c, s->value, targetMask); + this->addRead(c, v, targetMask); ++ index; - if ((++ argumentIndex) < argumentCount) { - s = s->next; - } else { + if ((++argumentIndex) >= arguments.count) { break; } } @@ -268,9 +376,10 @@ class CallEvent: public Event { { bool thunk; OperandMask op; - c->arch->plan - ((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, vm::TargetBytesPerWord, - op, &thunk); + c->arch->plan((flags & Compiler::Aligned) ? lir::AlignedCall : lir::Call, + c->targetInfo.pointerSize, + op, + &thunk); assert(c, not thunk); @@ -280,22 +389,24 @@ class CallEvent: public Event { Stack* stack = stackBefore; - if (stackArgumentFootprint) { - RUNTIME_ARRAY(Value*, arguments, stackArgumentFootprint); - for (int i = stackArgumentFootprint - 1; i >= 0; --i) { - Value* v = stack->value; + if (callingConvention == ir::AvianCallingConvention) { + for (size_t i = 0; i < arguments.count; i++) { stack = stack->next; + } + for (int i = stackArgumentFootprint - 1; i >= 0; --i) { + Value* v = static_cast(arguments[i]); - if ((vm::TargetBytesPerWord == 8 - and (v == 0 or (i >= 1 and stack->value == 0))) - or (vm::TargetBytesPerWord == 4 and v->nextWord != v)) - { - assert(c, vm::TargetBytesPerWord == 8 or v->nextWord == stack->value); + if ((c->targetInfo.pointerSize == 8 + && (v == 0 || (i >= 1 && arguments[i - 1] == 0))) + || (c->targetInfo.pointerSize == 4 && v->nextWord != v)) { + assert(c, + c->targetInfo.pointerSize == 8 + or v->nextWord == arguments[i - 1]); - RUNTIME_ARRAY_BODY(arguments)[i--] = stack->value; - stack = stack->next; + arguments[i] = arguments[i - 1]; + --i; } - RUNTIME_ARRAY_BODY(arguments)[i] = v; + arguments[i] = v; } int returnAddressIndex; @@ -303,7 +414,7 @@ class CallEvent: public Event { int frameOffset; if (TailCalls and (flags & Compiler::TailJump)) { - assert(c, argumentCount == 0); + assert(c, arguments.count == 0); int base = frameBase(c); returnAddressIndex = base + c->arch->returnAddressOffset(); @@ -322,7 +433,7 @@ class CallEvent: public Event { } for (unsigned i = 0; i < stackArgumentFootprint; ++i) { - Value* v = RUNTIME_ARRAY_BODY(arguments)[i]; + Value* v = static_cast(arguments[i]); if (v) { int frameIndex = i + frameOffset; @@ -386,6 +497,8 @@ class CallEvent: public Event { virtual void compile(Context* c) { lir::UnaryOperation op; + unsigned footprint = c->arch->argumentFootprint(stackArgumentFootprint); + if (TailCalls and (flags & Compiler::TailJump)) { if (flags & Compiler::LongJumpOrCall) { if (flags & Compiler::Aligned) { @@ -424,9 +537,9 @@ class CallEvent: public Event { fps = lir::NoRegister; } - int offset - = static_cast(c->arch->argumentFootprint(stackArgumentFootprint)) - - static_cast(c->arch->argumentFootprint(c->parameterFootprint)); + int offset = static_cast(footprint) + - static_cast( + c->arch->argumentFootprint(c->parameterFootprint)); c->assembler->popFrameForTailCall(c->alignedFrameSize, offset, ras, fps); } else if (flags & Compiler::LongJumpOrCall) { @@ -441,7 +554,7 @@ class CallEvent: public Event { op = lir::Call; } - apply(c, op, vm::TargetBytesPerWord, address->source, address->source); + apply(c, op, c->targetInfo.pointerSize, address->source, address->source); if (traceHandler) { traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)), @@ -457,23 +570,19 @@ class CallEvent: public Event { if (framePointerSurrogate) { framePointerSurrogate->source->thaw(c, framePointerSurrogate); } - } else { - unsigned footprint = c->arch->argumentFootprint - (stackArgumentFootprint); - - if (footprint > c->arch->stackAlignmentInWords()) { - c->assembler->adjustFrame - (footprint - c->arch->stackAlignmentInWords()); - } + } else if (footprint > c->arch->stackAlignmentInWords()) { + c->assembler->adjustFrame(footprint - c->arch->stackAlignmentInWords()); } } clean(c, this, stackBefore, localsBefore, reads, popIndex); - if (resultSize and live(c, result)) { - result->addSite(c, registerSite(c, c->arch->returnLow())); - if (resultSize > vm::TargetBytesPerWord and live(c, result->nextWord)) { - result->nextWord->addSite(c, registerSite(c, c->arch->returnHigh())); + if (resultValue->type.size(c->targetInfo) and live(c, resultValue)) { + resultValue->addSite(c, registerSite(c, c->arch->returnLow())); + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize + and live(c, resultValue->nextWord)) { + resultValue->nextWord->addSite(c, + registerSite(c, c->arch->returnHigh())); } } } @@ -484,38 +593,44 @@ class CallEvent: public Event { Value* address; TraceHandler* traceHandler; - Value* result; + Value* resultValue; Value* returnAddressSurrogate; Value* framePointerSurrogate; unsigned popIndex; unsigned stackArgumentIndex; unsigned flags; - unsigned resultSize; unsigned stackArgumentFootprint; }; -void -appendCall(Context* c, Value* address, unsigned flags, - TraceHandler* traceHandler, Value* result, unsigned resultSize, - Stack* argumentStack, unsigned argumentCount, - unsigned stackArgumentFootprint) +void appendCall(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* result, + util::Slice arguments) { - append(c, new(c->zone) - CallEvent(c, address, flags, traceHandler, result, - resultSize, argumentStack, argumentCount, - stackArgumentFootprint)); + append(c, + new (c->zone) CallEvent(c, + address, + callingConvention, + flags, + traceHandler, + result, + arguments)); } class ReturnEvent: public Event { public: - ReturnEvent(Context* c, unsigned size, Value* value): - Event(c), value(value) + ReturnEvent(Context* c, Value* value) : Event(c), value(value) { if (value) { - this->addReads(c, value, size, - SiteMask::fixedRegisterMask(c->arch->returnLow()), - SiteMask::fixedRegisterMask(c->arch->returnHigh())); + this->addReads(c, + value, + value->type.size(c->targetInfo), + SiteMask::fixedRegisterMask(c->arch->returnLow()), + SiteMask::fixedRegisterMask(c->arch->returnHigh())); } } @@ -538,33 +653,50 @@ class ReturnEvent: public Event { Value* value; }; -void appendReturn(Context* c, unsigned size, Value* value) { - append(c, new(c->zone) ReturnEvent(c, size, value)); +void appendReturn(Context* c, Value* value) +{ + append(c, new (c->zone) ReturnEvent(c, value)); } class MoveEvent: public Event { public: - MoveEvent(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue, - const SiteMask& srcLowMask, const SiteMask& srcHighMask): - Event(c), type(type), srcSize(srcSize), srcSelectSize(srcSelectSize), - srcValue(srcValue), dstSize(dstSize), dstValue(dstValue) + MoveEvent(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue, + const SiteMask& srcLowMask, + const SiteMask& srcHighMask) + : Event(c), + op(op), + srcSize(srcSize), + srcSelectSize(srcSelectSize), + srcValue(srcValue), + dstSize(dstSize), + dstValue(dstValue) { assert(c, srcSelectSize <= srcSize); bool noop = srcSelectSize >= dstSize; - - if (dstSize > vm::TargetBytesPerWord) { + + if (dstSize > c->targetInfo.pointerSize) { dstValue->grow(c); } - if (srcSelectSize > vm::TargetBytesPerWord) { + if (srcSelectSize > c->targetInfo.pointerSize) { srcValue->maybeSplit(c); } - this->addReads(c, srcValue, srcSelectSize, srcLowMask, noop ? dstValue : 0, - srcHighMask, - noop and dstSize > vm::TargetBytesPerWord ? dstValue->nextWord : 0); + this->addReads( + c, + srcValue, + srcSelectSize, + srcLowMask, + noop ? dstValue : 0, + srcHighMask, + noop and dstSize > c->targetInfo.pointerSize ? dstValue->nextWord : 0); } virtual const char* name() { @@ -574,64 +706,85 @@ class MoveEvent: public Event { virtual void compile(Context* c) { OperandMask dst; - c->arch->planDestination - (type, - srcSelectSize, - OperandMask( - 1 << srcValue->source->type(c), - (static_cast(srcValue->nextWord->source->registerMask(c)) << 32) - | static_cast(srcValue->source->registerMask(c))), - dstSize, dst); + c->arch->planDestination( + op, + srcSelectSize, + OperandMask( + 1 << srcValue->source->type(c), + (static_cast(srcValue->nextWord->source->registerMask(c)) + << 32) | static_cast(srcValue->source->registerMask(c))), + dstSize, + dst); SiteMask dstLowMask = SiteMask::lowPart(dst); SiteMask dstHighMask = SiteMask::highPart(dst); - if (srcSelectSize >= vm::TargetBytesPerWord - and dstSize >= vm::TargetBytesPerWord - and srcSelectSize >= dstSize) - { + if (srcSelectSize >= c->targetInfo.pointerSize + and dstSize >= c->targetInfo.pointerSize and srcSelectSize >= dstSize) { if (dstValue->target) { - if (dstSize > vm::TargetBytesPerWord) { - if (srcValue->source->registerSize(c) > vm::TargetBytesPerWord) { + if (dstSize > c->targetInfo.pointerSize) { + if (srcValue->source->registerSize(c) > c->targetInfo.pointerSize) { apply(c, lir::Move, srcSelectSize, srcValue->source, srcValue->source, dstSize, dstValue->target, dstValue->target); if (live(c, dstValue) == 0) { dstValue->removeSite(c, dstValue->target); - if (dstSize > vm::TargetBytesPerWord) { + if (dstSize > c->targetInfo.pointerSize) { dstValue->nextWord->removeSite(c, dstValue->nextWord->target); } } } else { srcValue->nextWord->source->freeze(c, srcValue->nextWord); - maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue, - vm::TargetBytesPerWord, dstValue, dstLowMask); + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue, + c->targetInfo.pointerSize, + dstValue, + dstLowMask); srcValue->nextWord->source->thaw(c, srcValue->nextWord); - maybeMove - (c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue->nextWord, - vm::TargetBytesPerWord, dstValue->nextWord, dstHighMask); + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue->nextWord, + c->targetInfo.pointerSize, + dstValue->nextWord, + dstHighMask); } } else { - maybeMove(c, lir::Move, vm::TargetBytesPerWord, vm::TargetBytesPerWord, srcValue, - vm::TargetBytesPerWord, dstValue, dstLowMask); + maybeMove(c, + lir::Move, + c->targetInfo.pointerSize, + c->targetInfo.pointerSize, + srcValue, + c->targetInfo.pointerSize, + dstValue, + dstLowMask); } } else { Site* low = pickSiteOrMove(c, srcValue, dstValue, 0, 0); - if (dstSize > vm::TargetBytesPerWord) { + if (dstSize > c->targetInfo.pointerSize) { pickSiteOrMove(c, srcValue->nextWord, dstValue->nextWord, low, 1); } } - } else if (srcSelectSize <= vm::TargetBytesPerWord - and dstSize <= vm::TargetBytesPerWord) - { - maybeMove(c, type, srcSize, srcSelectSize, srcValue, dstSize, dstValue, + } else if (srcSelectSize <= c->targetInfo.pointerSize + and dstSize <= c->targetInfo.pointerSize) { + maybeMove(c, + op, + srcSize, + srcSelectSize, + srcValue, + dstSize, + dstValue, dstLowMask); } else { - assert(c, srcSize == vm::TargetBytesPerWord); - assert(c, srcSelectSize == vm::TargetBytesPerWord); + assert(c, srcSize == c->targetInfo.pointerSize); + assert(c, srcSelectSize == c->targetInfo.pointerSize); if (dstValue->nextWord->target or live(c, dstValue->nextWord)) { assert(c, dstLowMask.typeMask & (1 << lir::RegisterOperand)); @@ -651,8 +804,14 @@ class MoveEvent: public Event { srcb, dstb, srcValue); } - apply(c, lir::Move, vm::TargetBytesPerWord, srcValue->source, srcValue->source, - vm::TargetBytesPerWord, low, low); + apply(c, + lir::Move, + c->targetInfo.pointerSize, + srcValue->source, + srcValue->source, + c->targetInfo.pointerSize, + low, + low); low->thaw(c, dstValue); @@ -675,7 +834,14 @@ class MoveEvent: public Event { srcb, dstb, dstValue, dstValue->nextWord); } - apply(c, lir::Move, vm::TargetBytesPerWord, low, low, dstSize, low, high); + apply(c, + lir::Move, + c->targetInfo.pointerSize, + low, + low, + dstSize, + low, + high); high->thaw(c, dstValue->nextWord); @@ -690,7 +856,7 @@ class MoveEvent: public Event { } } - lir::BinaryOperation type; + lir::BinaryOperation op; unsigned srcSize; unsigned srcSelectSize; Value* srcValue; @@ -698,23 +864,31 @@ class MoveEvent: public Event { Value* dstValue; }; -void -appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue) +void appendMove(Context* c, + lir::BinaryOperation op, + unsigned srcSize, + unsigned srcSelectSize, + Value* srcValue, + unsigned dstSize, + Value* dstValue) { bool thunk; OperandMask src; - c->arch->planSource - (type, srcSelectSize, src, dstSize, &thunk); + c->arch->planSource(op, srcSelectSize, src, dstSize, &thunk); assert(c, not thunk); - append(c, new(c->zone) - MoveEvent - (c, type, srcSize, srcSelectSize, srcValue, dstSize, dstValue, - SiteMask::lowPart(src), - SiteMask::highPart(src))); + append(c, + new (c->zone) MoveEvent(c, + op, + srcSize, + srcSelectSize, + srcValue, + dstSize, + dstValue, + SiteMask::lowPart(src), + SiteMask::highPart(src))); } @@ -722,7 +896,7 @@ void freezeSource(Context* c, unsigned size, Value* v) { v->source->freeze(c, v); - if (size > vm::TargetBytesPerWord) { + if (size > c->targetInfo.pointerSize) { v->nextWord->source->freeze(c, v->nextWord); } } @@ -731,7 +905,7 @@ void thawSource(Context* c, unsigned size, Value* v) { v->source->thaw(c, v); - if (size > vm::TargetBytesPerWord) { + if (size > c->targetInfo.pointerSize) { v->nextWord->source->thaw(c, v->nextWord); } } @@ -789,29 +963,40 @@ Site* getTarget(Context* c, Value* value, Value* result, const SiteMask& resultM class CombineEvent: public Event { public: - CombineEvent(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* firstValue, - unsigned secondSize, Value* secondValue, - unsigned resultSize, Value* resultValue, + CombineEvent(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* resultValue, const SiteMask& firstLowMask, const SiteMask& firstHighMask, const SiteMask& secondLowMask, - const SiteMask& secondHighMask): - Event(c), type(type), firstSize(firstSize), firstValue(firstValue), - secondSize(secondSize), secondValue(secondValue), resultSize(resultSize), - resultValue(resultValue) + const SiteMask& secondHighMask) + : Event(c), + op(op), + firstValue(firstValue), + secondValue(secondValue), + resultValue(resultValue) { - this->addReads(c, firstValue, firstSize, firstLowMask, firstHighMask); + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + firstLowMask, + firstHighMask); - if (resultSize > vm::TargetBytesPerWord) { + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { resultValue->grow(c); } - bool condensed = c->arch->alwaysCondensed(type); + bool condensed = c->arch->alwaysCondensed(op); - this->addReads(c, secondValue, secondSize, - secondLowMask, condensed ? resultValue : 0, - secondHighMask, condensed ? resultValue->nextWord : 0); + this->addReads(c, + secondValue, + secondValue->type.size(c->targetInfo), + secondLowMask, + condensed ? resultValue : 0, + secondHighMask, + condensed ? resultValue->nextWord : 0); } virtual const char* name() { @@ -829,147 +1014,182 @@ class CombineEvent: public Event { // } assert(c, secondValue->source->type(c) == secondValue->nextWord->source->type(c)); - - freezeSource(c, firstSize, firstValue); - + + freezeSource(c, firstValue->type.size(c->targetInfo), firstValue); + OperandMask cMask; - c->arch->planDestination - (type, - firstSize, - OperandMask( - 1 << firstValue->source->type(c), - (static_cast(firstValue->nextWord->source->registerMask(c)) << 32) + c->arch->planDestination( + op, + firstValue->type.size(c->targetInfo), + OperandMask( + 1 << firstValue->source->type(c), + (static_cast( + firstValue->nextWord->source->registerMask(c)) + << 32) | static_cast(firstValue->source->registerMask(c))), - secondSize, - OperandMask( - 1 << secondValue->source->type(c), - (static_cast(secondValue->nextWord->source->registerMask(c)) << 32) + secondValue->type.size(c->targetInfo), + OperandMask( + 1 << secondValue->source->type(c), + (static_cast( + secondValue->nextWord->source->registerMask(c)) + << 32) | static_cast(secondValue->source->registerMask(c))), - resultSize, - cMask); + resultValue->type.size(c->targetInfo), + cMask); SiteMask resultLowMask = SiteMask::lowPart(cMask); SiteMask resultHighMask = SiteMask::highPart(cMask); Site* low = getTarget(c, secondValue, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); - Site* high - = (resultSize > lowSize - ? getTarget(c, secondValue->nextWord, resultValue->nextWord, resultHighMask) - : low); + Site* high = (resultValue->type.size(c->targetInfo) > lowSize + ? getTarget(c, + secondValue->nextWord, + resultValue->nextWord, + resultHighMask) + : low); // fprintf(stderr, "combine %p:%p and %p:%p into %p:%p\n", // firstValue, firstValue->nextWord, // secondValue, secondValue->nextWord, // resultValue, resultValue->nextWord); - apply(c, type, - firstSize, firstValue->source, firstValue->nextWord->source, - secondSize, secondValue->source, secondValue->nextWord->source, - resultSize, low, high); + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + secondValue->type.size(c->targetInfo), + secondValue->source, + secondValue->nextWord->source, + resultValue->type.size(c->targetInfo), + low, + high); - thawSource(c, firstSize, firstValue); + thawSource(c, firstValue->type.size(c->targetInfo), firstValue); for (Read* r = reads; r; r = r->eventNext) { popRead(c, this, r->value); } low->thaw(c, secondValue); - if (resultSize > lowSize) { + if (resultValue->type.size(c->targetInfo) > lowSize) { high->thaw(c, secondValue->nextWord); } if (live(c, resultValue)) { resultValue->addSite(c, low); - if (resultSize > lowSize and live(c, resultValue->nextWord)) { + if (resultValue->type.size(c->targetInfo) > lowSize + and live(c, resultValue->nextWord)) { resultValue->nextWord->addSite(c, high); } } } - lir::TernaryOperation type; - unsigned firstSize; + lir::TernaryOperation op; Value* firstValue; - unsigned secondSize; Value* secondValue; - unsigned resultSize; Value* resultValue; }; -void -appendCombine(Context* c, lir::TernaryOperation type, - unsigned firstSize, Value* firstValue, - unsigned secondSize, Value* secondValue, - unsigned resultSize, Value* resultValue) +void appendCombine(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* resultValue) { bool thunk; OperandMask firstMask; OperandMask secondMask; - - c->arch->planSource(type, - firstSize, firstMask, - secondSize, secondMask, - resultSize, + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + firstMask, + secondValue->type.size(c->targetInfo), + secondMask, + resultValue->type.size(c->targetInfo), &thunk); if (thunk) { - Stack* oldStack = c->stack; + const size_t MaxValueCount = 6; + FixedSliceStack slice; + size_t stackBase = c->stack ? c->stack->index + 1 : 0; bool threadParameter; - intptr_t handler = c->client->getThunk - (type, firstSize, resultSize, &threadParameter); + intptr_t handler + = c->client->getThunk(op, + firstValue->type.size(c->targetInfo), + resultValue->type.size(c->targetInfo), + &threadParameter); - unsigned stackSize = ceilingDivide(secondSize, vm::TargetBytesPerWord) - + ceilingDivide(firstSize, vm::TargetBytesPerWord); + unsigned stackSize = ceilingDivide(secondValue->type.size(c->targetInfo), + c->targetInfo.pointerSize) + + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize); - compiler::push(c, ceilingDivide(secondSize, vm::TargetBytesPerWord), secondValue); - compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); + slicePush(c, + ceilingDivide(secondValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + secondValue, + stackBase, + slice); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); if (threadParameter) { ++ stackSize; - compiler::push(c, 1, register_(c, c->arch->thread())); + slicePush(c, 1, threadRegister(c), stackBase, slice); } - Stack* argumentStack = c->stack; - c->stack = oldStack; - - appendCall - (c, value(c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, resultValue, - resultSize, argumentStack, stackSize, 0); + appendCall(c, + value(c, ir::Type::addr(), constantSite(c, handler)), + ir::NativeCallingConvention, + 0, + 0, + resultValue, + slice); } else { - append - (c, new(c->zone) - CombineEvent - (c, type, - firstSize, firstValue, - secondSize, secondValue, - resultSize, resultValue, - SiteMask::lowPart(firstMask), - SiteMask::highPart(firstMask), - SiteMask::lowPart(secondMask), - SiteMask::highPart(secondMask))); + append(c, + new (c->zone) CombineEvent(c, + op, + firstValue, + secondValue, + resultValue, + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); } } class TranslateEvent: public Event { public: - TranslateEvent(Context* c, lir::BinaryOperation type, unsigned valueSize, - Value* value, unsigned resultSize, Value* resultValue, + TranslateEvent(Context* c, + lir::BinaryOperation op, + Value* firstValue, + Value* resultValue, const SiteMask& valueLowMask, - const SiteMask& valueHighMask): - Event(c), type(type), valueSize(valueSize), resultSize(resultSize), - value(value), resultValue(resultValue) + const SiteMask& valueHighMask) + : Event(c), op(op), firstValue(firstValue), resultValue(resultValue) { - bool condensed = c->arch->alwaysCondensed(type); + bool condensed = c->arch->alwaysCondensed(op); - if (resultSize > vm::TargetBytesPerWord) { + if (resultValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { resultValue->grow(c); } - this->addReads(c, value, valueSize, valueLowMask, condensed ? resultValue : 0, - valueHighMask, condensed ? resultValue->nextWord : 0); + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + valueLowMask, + condensed ? resultValue : 0, + valueHighMask, + condensed ? resultValue->nextWord : 0); } virtual const char* name() { @@ -977,90 +1197,122 @@ class TranslateEvent: public Event { } virtual void compile(Context* c) { - assert(c, value->source->type(c) == value->nextWord->source->type(c)); + assert(c, firstValue->source->type(c) == firstValue->nextWord->source->type(c)); OperandMask bMask; - - c->arch->planDestination - (type, - valueSize, - OperandMask( - 1 << value->source->type(c), - (static_cast(value->nextWord->source->registerMask(c)) << 32) - | static_cast(value->source->registerMask(c))), - resultSize, - bMask); + + c->arch->planDestination( + op, + firstValue->type.size(c->targetInfo), + OperandMask( + 1 << firstValue->source->type(c), + (static_cast( + firstValue->nextWord->source->registerMask(c)) + << 32) + | static_cast(firstValue->source->registerMask(c))), + resultValue->type.size(c->targetInfo), + bMask); SiteMask resultLowMask = SiteMask::lowPart(bMask); SiteMask resultHighMask = SiteMask::highPart(bMask); - Site* low = getTarget(c, value, resultValue, resultLowMask); + Site* low = getTarget(c, firstValue, resultValue, resultLowMask); unsigned lowSize = low->registerSize(c); - Site* high - = (resultSize > lowSize - ? getTarget(c, value->nextWord, resultValue->nextWord, resultHighMask) - : low); + Site* high = (resultValue->type.size(c->targetInfo) > lowSize + ? getTarget(c, + firstValue->nextWord, + resultValue->nextWord, + resultHighMask) + : low); - apply(c, type, valueSize, value->source, value->nextWord->source, - resultSize, low, high); + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + resultValue->type.size(c->targetInfo), + low, + high); for (Read* r = reads; r; r = r->eventNext) { popRead(c, this, r->value); } - low->thaw(c, value); - if (resultSize > lowSize) { - high->thaw(c, value->nextWord); + low->thaw(c, firstValue); + if (resultValue->type.size(c->targetInfo) > lowSize) { + high->thaw(c, firstValue->nextWord); } if (live(c, resultValue)) { resultValue->addSite(c, low); - if (resultSize > lowSize and live(c, resultValue->nextWord)) { + if (resultValue->type.size(c->targetInfo) > lowSize + and live(c, resultValue->nextWord)) { resultValue->nextWord->addSite(c, high); } } } - lir::BinaryOperation type; - unsigned valueSize; - unsigned resultSize; - Value* value; + lir::BinaryOperation op; + Value* firstValue; Value* resultValue; Read* resultRead; SiteMask resultLowMask; SiteMask resultHighMask; }; -void -appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, - Value* firstValue, unsigned resultSize, Value* resultValue) +void appendTranslate(Context* c, + lir::BinaryOperation op, + Value* firstValue, + Value* resultValue) { + assert(c, + firstValue->type.size(c->targetInfo) + == firstValue->type.size(c->targetInfo)); + assert(c, + resultValue->type.size(c->targetInfo) + == resultValue->type.size(c->targetInfo)); + bool thunk; OperandMask first; - c->arch->planSource(type, firstSize, first, - resultSize, &thunk); + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + first, + resultValue->type.size(c->targetInfo), + &thunk); if (thunk) { - Stack* oldStack = c->stack; + size_t stackBase = c->stack ? c->stack->index + 1 : 0; + FixedSliceStack slice; - compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); - Stack* argumentStack = c->stack; - c->stack = oldStack; - - appendCall - (c, value - (c, lir::ValueGeneral, constantSite - (c, c->client->getThunk(type, firstSize, resultSize))), - 0, 0, resultValue, resultSize, argumentStack, - ceilingDivide(firstSize, vm::TargetBytesPerWord), 0); + appendCall(c, + value(c, + ir::Type::addr(), + constantSite(c, + c->client->getThunk( + op, + firstValue->type.size(c->targetInfo), + resultValue->type.size(c->targetInfo)))), + ir::NativeCallingConvention, + 0, + 0, + resultValue, + slice); } else { - append(c, new(c->zone) - TranslateEvent - (c, type, firstSize, firstValue, resultSize, resultValue, - SiteMask::lowPart(first), - SiteMask::highPart(first))); + append(c, + new (c->zone) TranslateEvent(c, + op, + firstValue, + resultValue, + SiteMask::lowPart(first), + SiteMask::highPart(first))); } } @@ -1150,7 +1402,7 @@ class MemoryEvent: public Event { popRead(c, this, base); if (index) { - if (vm::TargetBytesPerWord == 8 and indexRegister != lir::NoRegister) { + if (c->targetInfo.pointerSize == 8 and indexRegister != lir::NoRegister) { apply(c, lir::Move, 4, index->source, index->source, 8, index->source, index->source); } @@ -1207,11 +1459,13 @@ unordered(double a, double b) return not (a >= b or a < b); } -bool -shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b, - int64_t a) +bool shouldJump(Context* c, + lir::TernaryOperation op, + unsigned size, + int64_t b, + int64_t a) { - switch (type) { + switch (op) { case lir::JumpIfEqual: return a == b; @@ -1269,10 +1523,9 @@ shouldJump(Context* c, lir::TernaryOperation type, unsigned size, int64_t b, } } -lir::TernaryOperation -thunkBranch(Context* c, lir::TernaryOperation type) +lir::TernaryOperation thunkBranch(Context* c, lir::TernaryOperation op) { - switch (type) { + switch (op) { case lir::JumpIfFloatEqual: return lir::JumpIfEqual; @@ -1302,23 +1555,40 @@ thunkBranch(Context* c, lir::TernaryOperation type) class BranchEvent: public Event { public: - BranchEvent(Context* c, lir::TernaryOperation type, unsigned size, - Value* firstValue, Value* secondValue, Value* addressValue, + BranchEvent(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* addressValue, const SiteMask& firstLowMask, const SiteMask& firstHighMask, const SiteMask& secondLowMask, - const SiteMask& secondHighMask): - Event(c), type(type), size(size), firstValue(firstValue), secondValue(secondValue), - addressValue(addressValue) + const SiteMask& secondHighMask) + : Event(c), + op(op), + firstValue(firstValue), + secondValue(secondValue), + addressValue(addressValue) { - this->addReads(c, firstValue, size, firstLowMask, firstHighMask); - this->addReads(c, secondValue, size, secondLowMask, secondHighMask); + this->addReads(c, + firstValue, + firstValue->type.size(c->targetInfo), + firstLowMask, + firstHighMask); + this->addReads(c, + secondValue, + firstValue->type.size(c->targetInfo), + secondLowMask, + secondHighMask); OperandMask dstMask; - c->arch->planDestination(type, - size, OperandMask(0, 0), - size, OperandMask(0, 0), - vm::TargetBytesPerWord, dstMask); + c->arch->planDestination(op, + firstValue->type.size(c->targetInfo), + OperandMask(0, 0), + firstValue->type.size(c->targetInfo), + OperandMask(0, 0), + c->targetInfo.pointerSize, + dstMask); this->addRead(c, addressValue, SiteMask::lowPart(dstMask)); } @@ -1340,28 +1610,44 @@ class BranchEvent: public Event { int64_t firstConstVal = firstConstant->value->value(); int64_t secondConstVal = secondConstant->value->value(); - if (size > vm::TargetBytesPerWord) { + if (firstValue->type.size(c->targetInfo) > c->targetInfo.pointerSize) { firstConstVal |= findConstantSite (c, firstValue->nextWord)->value->value() << 32; secondConstVal |= findConstantSite (c, secondValue->nextWord)->value->value() << 32; } - if (shouldJump(c, type, size, firstConstVal, secondConstVal)) { - apply(c, lir::Jump, vm::TargetBytesPerWord, addressValue->source, addressValue->source); + if (shouldJump(c, + op, + firstValue->type.size(c->targetInfo), + firstConstVal, + secondConstVal)) { + apply(c, + lir::Jump, + c->targetInfo.pointerSize, + addressValue->source, + addressValue->source); } } else { - freezeSource(c, size, firstValue); - freezeSource(c, size, secondValue); - freezeSource(c, vm::TargetBytesPerWord, addressValue); + freezeSource(c, firstValue->type.size(c->targetInfo), firstValue); + freezeSource(c, firstValue->type.size(c->targetInfo), secondValue); + freezeSource(c, c->targetInfo.pointerSize, addressValue); - apply(c, type, size, firstValue->source, firstValue->nextWord->source, - size, secondValue->source, secondValue->nextWord->source, - vm::TargetBytesPerWord, addressValue->source, addressValue->source); + apply(c, + op, + firstValue->type.size(c->targetInfo), + firstValue->source, + firstValue->nextWord->source, + firstValue->type.size(c->targetInfo), + secondValue->source, + secondValue->nextWord->source, + c->targetInfo.pointerSize, + addressValue->source, + addressValue->source); - thawSource(c, vm::TargetBytesPerWord, addressValue); - thawSource(c, size, secondValue); - thawSource(c, size, firstValue); + thawSource(c, c->targetInfo.pointerSize, addressValue); + thawSource(c, firstValue->type.size(c->targetInfo), secondValue); + thawSource(c, firstValue->type.size(c->targetInfo), firstValue); } } @@ -1372,59 +1658,82 @@ class BranchEvent: public Event { virtual bool isBranch() { return true; } - lir::TernaryOperation type; - unsigned size; + lir::TernaryOperation op; Value* firstValue; Value* secondValue; Value* addressValue; }; -void -appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* firstValue, - Value* secondValue, Value* addressValue) +void appendBranch(Context* c, + lir::TernaryOperation op, + Value* firstValue, + Value* secondValue, + Value* addressValue) { bool thunk; OperandMask firstMask; OperandMask secondMask; - c->arch->planSource(type, - size, firstMask, - size, secondMask, - vm::TargetBytesPerWord, &thunk); + c->arch->planSource(op, + firstValue->type.size(c->targetInfo), + firstMask, + firstValue->type.size(c->targetInfo), + secondMask, + c->targetInfo.pointerSize, + &thunk); if (thunk) { - Stack* oldStack = c->stack; + const size_t MaxValueCount = 4; + FixedSliceStack slice; + size_t stackBase = c->stack ? c->stack->index + 1 : 0; bool threadParameter; - intptr_t handler = c->client->getThunk - (type, size, size, &threadParameter); + intptr_t handler = c->client->getThunk(op, + firstValue->type.size(c->targetInfo), + firstValue->type.size(c->targetInfo), + &threadParameter); assert(c, not threadParameter); - compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), secondValue); - compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), firstValue); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + secondValue, + stackBase, + slice); + slicePush(c, + ceilingDivide(firstValue->type.size(c->targetInfo), + c->targetInfo.pointerSize), + firstValue, + stackBase, + slice); - Stack* argumentStack = c->stack; - c->stack = oldStack; + Value* result = value(c, ir::Type::addr()); + appendCall(c, + value(c, ir::Type::addr(), constantSite(c, handler)), + ir::NativeCallingConvention, + 0, + 0, + result, + slice); - Value* result = value(c, lir::ValueGeneral); - appendCall - (c, value - (c, lir::ValueGeneral, constantSite(c, handler)), 0, 0, result, 4, - argumentStack, ceilingDivide(size, vm::TargetBytesPerWord) * 2, 0); - - appendBranch(c, thunkBranch(c, type), 4, value - (c, lir::ValueGeneral, constantSite(c, static_cast(0))), - result, addressValue); + appendBranch( + c, + thunkBranch(c, op), + value(c, ir::Type::addr(), constantSite(c, static_cast(0))), + result, + addressValue); } else { - append - (c, new(c->zone) - BranchEvent - (c, type, size, firstValue, secondValue, addressValue, - SiteMask::lowPart(firstMask), - SiteMask::highPart(firstMask), - SiteMask::lowPart(secondMask), - SiteMask::highPart(secondMask))); + append(c, + new (c->zone) BranchEvent(c, + op, + firstValue, + secondValue, + addressValue, + SiteMask::lowPart(firstMask), + SiteMask::highPart(firstMask), + SiteMask::lowPart(secondMask), + SiteMask::highPart(secondMask))); } } @@ -1466,14 +1775,16 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, 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) + JumpEvent(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit, + bool cleanLocals) + : Event(c), op(op), address(address), exit(exit), cleanLocals(cleanLocals) { bool thunk; OperandMask mask; - c->arch->plan(type, vm::TargetBytesPerWord, mask, &thunk); + c->arch->plan(op, c->targetInfo.pointerSize, mask, &thunk); assert(c, not thunk); @@ -1486,7 +1797,7 @@ class JumpEvent: public Event { virtual void compile(Context* c) { if (not this->isUnreachable()) { - apply(c, type, vm::TargetBytesPerWord, address->source, address->source); + apply(c, op, c->targetInfo.pointerSize, address->source, address->source); } for (Read* r = reads; r; r = r->eventNext) { @@ -1507,14 +1818,19 @@ class JumpEvent: public Event { return exit or this->isUnreachable(); } - lir::UnaryOperation type; + lir::UnaryOperation op; 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)); +void appendJump(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit, + bool cleanLocals) +{ + append(c, new (c->zone) JumpEvent(c, op, address, exit, cleanLocals)); } class BoundsCheckEvent: public Event { @@ -1542,17 +1858,26 @@ class BoundsCheckEvent: public Event { if (constant->value->value() < 0) { lir::Constant handlerConstant(resolvedPromise(c, handler)); a->apply(lir::Call, - OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); + OperandInfo(c->targetInfo.pointerSize, + lir::ConstantOperand, + &handlerConstant)); } } else { outOfBoundsPromise = compiler::codePromise(c, static_cast(0)); ConstantSite zero(resolvedPromise(c, 0)); ConstantSite oob(outOfBoundsPromise); - apply(c, lir::JumpIfLess, - 4, &zero, &zero, - 4, index->source, index->source, - vm::TargetBytesPerWord, &oob, &oob); + apply(c, + lir::JumpIfLess, + 4, + &zero, + &zero, + 4, + index->source, + index->source, + c->targetInfo.pointerSize, + &oob, + &oob); } if (constant == 0 or constant->value->value() >= 0) { @@ -1563,15 +1888,22 @@ class BoundsCheckEvent: public Event { CodePromise* nextPromise = compiler::codePromise(c, static_cast(0)); - freezeSource(c, vm::TargetBytesPerWord, index); + freezeSource(c, c->targetInfo.pointerSize, index); ConstantSite next(nextPromise); - apply(c, lir::JumpIfGreater, - 4, index->source, - index->source, 4, &length, - &length, vm::TargetBytesPerWord, &next, &next); + apply(c, + lir::JumpIfGreater, + 4, + index->source, + index->source, + 4, + &length, + &length, + c->targetInfo.pointerSize, + &next, + &next); - thawSource(c, vm::TargetBytesPerWord, index); + thawSource(c, c->targetInfo.pointerSize, index); if (constant == 0) { outOfBoundsPromise->offset = a->offset(); @@ -1579,7 +1911,9 @@ class BoundsCheckEvent: public Event { lir::Constant handlerConstant(resolvedPromise(c, handler)); a->apply(lir::Call, - OperandInfo(vm::TargetBytesPerWord, lir::ConstantOperand, &handlerConstant)); + OperandInfo(c->targetInfo.pointerSize, + lir::ConstantOperand, + &handlerConstant)); nextPromise->offset = a->offset(); } diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 02eba8135f..03e21d2bc2 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -113,28 +113,34 @@ 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 appendCall(Context* c, + Value* address, + ir::CallingConvention callingConvention, + unsigned flags, + TraceHandler* traceHandler, + Value* result, + util::Slice arguments); -void -appendReturn(Context* c, unsigned size, Value* value); +void appendReturn(Context* c, Value* value); -void -appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize, - unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst); +void appendMove(Context* c, + lir::BinaryOperation op, + 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 appendCombine(Context* c, + lir::TernaryOperation op, + Value* first, + Value* second, + Value* result); -void -appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, - Value* first, unsigned resultSize, Value* result); +void appendTranslate(Context* c, + lir::BinaryOperation op, + Value* first, + Value* result); void appendOperation(Context* c, lir::Operation op); @@ -143,13 +149,17 @@ 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 appendBranch(Context* c, + lir::TernaryOperation op, + Value* first, + Value* second, + Value* address); -void -appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false, - bool cleanLocals = false); +void appendJump(Context* c, + lir::UnaryOperation op, + Value* address, + bool exit = false, + bool cleanLocals = false); void appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, @@ -164,6 +174,8 @@ appendSaveLocals(Context* c); void appendDummy(Context* c); +void appendBuddy(Context* c, Value* original, Value* buddy); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/frame.cpp b/src/codegen/compiler/frame.cpp index f6a94f3b7a..223d036e9d 100644 --- a/src/codegen/compiler/frame.cpp +++ b/src/codegen/compiler/frame.cpp @@ -45,16 +45,18 @@ int frameIndex(Context* c, int localIndex) { unsigned frameIndexToOffset(Context* c, unsigned frameIndex) { assert(c, frameIndex < totalFrameSize(c)); - return (frameIndex + c->arch->frameFooterSize()) * vm::TargetBytesPerWord; + return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize; } 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()) + assert(c, + static_cast((offset / c->targetInfo.pointerSize) + - c->arch->frameFooterSize()) >= 0); + assert(c, + ((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize()) < totalFrameSize(c)); - return (offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize(); + return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize(); } unsigned frameBase(Context* c) { diff --git a/src/codegen/compiler/ir.cpp b/src/codegen/compiler/ir.cpp index aa2f09eb2f..abd6cc608f 100644 --- a/src/codegen/compiler/ir.cpp +++ b/src/codegen/compiler/ir.cpp @@ -15,14 +15,19 @@ 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(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) { + for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) { i = c->logicalCode[n]; if (i) return i; } diff --git a/src/codegen/compiler/ir.h b/src/codegen/compiler/ir.h index 3bfdffc5d6..8b919c44a4 100644 --- a/src/codegen/compiler/ir.h +++ b/src/codegen/compiler/ir.h @@ -57,17 +57,9 @@ class LogicalInstruction { 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); diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp index e3b5aa7247..1567140cca 100644 --- a/src/codegen/compiler/promise.cpp +++ b/src/codegen/compiler/promise.cpp @@ -90,9 +90,10 @@ class PoolPromise: public Promise { virtual int64_t value() { if (resolved()) { - return reinterpret_cast - (c->machineCode + vm::pad(c->machineCodeSize, vm::TargetBytesPerWord) - + (key * vm::TargetBytesPerWord)); + return reinterpret_cast( + c->machineCode + + vm::pad(c->machineCodeSize, c->targetInfo.pointerSize) + + (key * c->targetInfo.pointerSize)); } abort(c); diff --git a/src/codegen/compiler/regalloc.cpp b/src/codegen/compiler/regalloc.cpp index ba7c6711ab..8699838900 100644 --- a/src/codegen/compiler/regalloc.cpp +++ b/src/codegen/compiler/regalloc.cpp @@ -215,12 +215,12 @@ pickTarget(Context* c, Read* read, bool intersectRead, Value* value = read->value; uint32_t registerMask - = (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask); + = (isFloatValue(value) ? ~0 : c->regFile->generalRegisters.mask); SiteMask mask(~0, registerMask, AnyFrameIndex); read->intersect(&mask); - if (value->type == lir::ValueFloat) { + if (isFloatValue(value)) { uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask; if (floatMask) { mask.registerMask = floatMask; diff --git a/src/codegen/compiler/site.cpp b/src/codegen/compiler/site.cpp index e5a1c02cb2..b1ddcee1d7 100644 --- a/src/codegen/compiler/site.cpp +++ b/src/codegen/compiler/site.cpp @@ -52,7 +52,7 @@ SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies, Site** SiteIterator::findNext(Site** p) { while (true) { if (*p) { - if (pass == 0 or (*p)->registerSize(c) > vm::TargetBytesPerWord) { + if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) { return p; } else { p = &((*p)->next); @@ -103,14 +103,11 @@ void SiteIterator::remove(Context* c) { previous = 0; } - - -unsigned Site::registerSize(Context*) { - return vm::TargetBytesPerWord; +unsigned Site::registerSize(Context* c) +{ + return c->targetInfo.pointerSize; } - - Site* constantSite(Context* c, Promise* value) { return new(c->zone) ConstantSite(value); } @@ -250,7 +247,7 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) { RegisterSite* rs = static_cast(s); unsigned size = rs->registerSize(c); - if (size > vm::TargetBytesPerWord) { + if (size > c->targetInfo.pointerSize) { assert(c, number != lir::NoRegister); return number == rs->number; } else { @@ -352,7 +349,7 @@ SiteMask RegisterSite::mask(Context* c UNUSED) { SiteMask RegisterSite::nextWordMask(Context* c, unsigned) { assert(c, number != lir::NoRegister); - if (registerSize(c) > vm::TargetBytesPerWord) { + if (registerSize(c) > c->targetInfo.pointerSize) { return SiteMask (1 << lir::RegisterOperand, number, NoFrameIndex); } else { @@ -367,7 +364,7 @@ unsigned RegisterSite::registerSize(Context* c) { if ((1 << number) & c->regFile->floatRegisters.mask) { return c->arch->floatRegisterSize(); } else { - return vm::TargetBytesPerWord; + return c->targetInfo.pointerSize; } } @@ -469,12 +466,15 @@ bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) { if (s->type(c) == lir::MemoryOperand) { MemorySite* ms = static_cast(s); return ms->base == this->base - and ((index == 1 and ms->offset == static_cast - (this->offset + vm::TargetBytesPerWord)) - or (index == 0 and this->offset == static_cast - (ms->offset + vm::TargetBytesPerWord))) - and ms->index == this->index - and ms->scale == this->scale; + and ((index == 1 + and ms->offset + == static_cast(this->offset + + c->targetInfo.pointerSize)) + or (index == 0 + and this->offset + == static_cast(ms->offset + + c->targetInfo.pointerSize))) + and ms->index == this->index and ms->scale == this->scale; } else { return false; } @@ -551,10 +551,11 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED, lir::Operand* result) { // todo: endianness? - assert(c, high == this + assert(c, + high == this or (static_cast(high)->base == base and static_cast(high)->offset - == static_cast(offset + vm::TargetBytesPerWord) + == static_cast(offset + c->targetInfo.pointerSize) and static_cast(high)->index == index and static_cast(high)->scale == scale)); @@ -569,7 +570,8 @@ Site* MemorySite::copy(Context* c) { Site* MemorySite::copyHalf(Context* c, bool add) { if (add) { - return memorySite(c, base, offset + vm::TargetBytesPerWord, index, scale); + return memorySite( + c, base, offset + c->targetInfo.pointerSize, index, scale); } else { return copy(c); } @@ -584,10 +586,13 @@ Site* MemorySite::copyHigh(Context* c) { } 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); + return memorySite(c, + base, + offset + ((index == 1) xor c->arch->bigEndian() + ? c->targetInfo.pointerSize + : -c->targetInfo.pointerSize), + this->index, + scale); } SiteMask MemorySite::mask(Context* c) { diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index eccb2b9cb1..411cbe37ee 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -17,10 +17,19 @@ 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) -{ } +Value::Value(Site* site, Site* target, ir::Type type) + : ir::Value(type), + reads(0), + lastRead(0), + sites(site), + source(0), + target(target), + buddy(this), + nextWord(this), + home(NoFrameIndex), + wordIndex(0) +{ +} bool Value::findSite(Site* site) { for (Site* s = this->sites; s; s = s->next) { @@ -106,7 +115,8 @@ bool Value::uniqueSite(Context* c, Site* s) { 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) { + if (this->nextWord != this + and s->registerSize(c) > c->targetInfo.pointerSize) { SiteIterator nit(c, this->nextWord); Site* p = nit.next(); if (nit.hasMore()) { @@ -154,8 +164,8 @@ bool Value::hasBuddy(Context* c, Value* b) { } #endif // not NDEBUG - -Value* value(Context* c, lir::ValueType type, Site* site, Site* target) { +Value* value(Context* c, ir::Type type, Site* site, Site* target) +{ return new(c->zone) Value(site, target, type); } diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index a9723782ea..3eaed04fa7 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -26,7 +26,7 @@ const int NoFrameIndex = -1; const bool DebugSites = false; -class Value: public Compiler::Operand { +class Value : public ir::Value { public: Read* reads; Read* lastRead; @@ -36,10 +36,9 @@ class Value: public Compiler::Operand { Value* buddy; Value* nextWord; int16_t home; - lir::ValueType type; uint8_t wordIndex; - Value(Site* site, Site* target, lir::ValueType type); + Value(Site* site, Site* target, ir::Type type); bool findSite(Site* site); @@ -67,15 +66,17 @@ class Value: public Compiler::Operand { }; -inline bool isGeneralValue(Compiler::Operand* a) { - return static_cast(a)->type == lir::ValueGeneral; +inline bool isFloatValue(ir::Value* a) +{ + return static_cast(a)->type.flavor() == ir::Type::Float; } -inline bool isFloatValue(Compiler::Operand* a) { - return static_cast(a)->type == lir::ValueFloat; +inline bool isGeneralValue(ir::Value* a) +{ + return !isFloatValue(a); } -Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0); +Value* value(Context* c, ir::Type type, Site* site = 0, Site* target = 0); } // namespace compiler } // namespace codegen diff --git a/src/codegen/target/arm/assembler.cpp b/src/codegen/target/arm/assembler.cpp index db62aeef71..b817ef1ae2 100644 --- a/src/codegen/target/arm/assembler.cpp +++ b/src/codegen/target/arm/assembler.cpp @@ -180,6 +180,11 @@ class MyArchitecture: public Architecture { return 3; } + virtual ir::TargetInfo targetInfo() + { + return ir::TargetInfo(TargetBytesPerWord); + } + virtual bool bigEndian() { return false; } diff --git a/src/codegen/target/x86/assembler.cpp b/src/codegen/target/x86/assembler.cpp index 0614f21954..4791f65681 100644 --- a/src/codegen/target/x86/assembler.cpp +++ b/src/codegen/target/x86/assembler.cpp @@ -204,6 +204,11 @@ class MyArchitecture: public Architecture { return rdx; } + virtual ir::TargetInfo targetInfo() + { + return ir::TargetInfo(TargetBytesPerWord); + } + virtual bool bigEndian() { return false; } diff --git a/src/compile.cpp b/src/compile.cpp index cd13d8f59a..052df86620 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,6 +27,8 @@ #include #include +#include "debug-util.h" + using namespace vm; extern "C" uint64_t @@ -56,6 +58,7 @@ const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; const bool DebugFrameMaps = false; +const bool DebugInstructions = false; const bool CheckArrayBounds = true; @@ -756,110 +759,39 @@ class PoolElement: public avian::codegen::Promise { PoolElement* next; }; -class Context; -class SubroutineCall; - class Subroutine { public: - Subroutine(unsigned ip, unsigned logIndex, Subroutine* listNext, - Subroutine* stackNext): - listNext(listNext), - stackNext(stackNext), - calls(0), - handle(0), - ip(ip), - logIndex(logIndex), - stackIndex(0), - callCount(0), - tableIndex(0), - visited(false) + Subroutine(unsigned index, + unsigned returnAddress, + unsigned methodSize, + Subroutine* outer) + : index(index), + outer(outer), + returnAddress(returnAddress), + duplicatedBaseIp(methodSize * index), + visited(false) { } - Subroutine* listNext; - Subroutine* stackNext; - SubroutineCall* calls; - Compiler::Subroutine* handle; - unsigned ip; - unsigned logIndex; - unsigned stackIndex; - unsigned callCount; - unsigned tableIndex; + // Index of this subroutine, in the (unmaterialized) list of subroutines in + // this method. + // Note that in the presence of nested finallys, this could theoretically end + // up being greater than the number of jsr instructions (but this will be + // extremely rare - I don't think we've seen this in practice). + const unsigned index; + + // Subroutine outer to this one (if, for instance, we have nested finallys) + Subroutine* const outer; + + // Starting ip in the original bytecode (always < original bytecode size) + const unsigned returnAddress; + + // Starting ip for this subroutine's copy of the method bytecode + const unsigned duplicatedBaseIp; + bool visited; }; -class SubroutinePath; - -class SubroutineCall { - public: - SubroutineCall(Subroutine* subroutine, avian::codegen::Promise* returnAddress): - subroutine(subroutine), - returnAddress(returnAddress), - paths(0), - next(subroutine->calls) - { - subroutine->calls = this; - ++ subroutine->callCount; - } - - Subroutine* subroutine; - avian::codegen::Promise* returnAddress; - SubroutinePath* paths; - SubroutineCall* next; -}; - -class SubroutinePath { - public: - SubroutinePath(SubroutineCall* call, SubroutinePath* stackNext, - uintptr_t* rootTable): - call(call), - stackNext(stackNext), - listNext(call->paths), - rootTable(rootTable) - { - call->paths = this; - } - - SubroutineCall* call; - SubroutinePath* stackNext; - SubroutinePath* listNext; - uintptr_t* rootTable; -}; - -void -print(SubroutinePath* path) -{ - if (path) { - fprintf(stderr, " ("); - while (true) { - fprintf(stderr, "%p", path->call->returnAddress->resolved() ? - reinterpret_cast(path->call->returnAddress->value()) : 0); - path = path->stackNext; - if (path) { - fprintf(stderr, ", "); - } else { - break; - } - } - fprintf(stderr, ")"); - } -} - -class SubroutineTrace { - public: - SubroutineTrace(SubroutinePath* path, SubroutineTrace* next, - unsigned mapSize): - path(path), - next(next), - watch(false) - { - memset(map, 0, mapSize * BytesPerWord); - } - - SubroutinePath* path; - SubroutineTrace* next; - bool watch; - uintptr_t map[0]; -}; +class Context; class TraceElement: public avian::codegen::TraceHandler { public: @@ -872,10 +804,8 @@ class TraceElement: public avian::codegen::TraceHandler { context(context), address(0), next(next), - subroutineTrace(0), target(target), ip(ip), - subroutineTraceCount(0), argumentIndex(0), flags(flags), watch(false) @@ -893,10 +823,8 @@ class TraceElement: public avian::codegen::TraceHandler { Context* context; avian::codegen::Promise* address; TraceElement* next; - SubroutineTrace* subroutineTrace; object target; unsigned ip; - unsigned subroutineTraceCount; unsigned argumentIndex; unsigned flags; bool watch; @@ -928,8 +856,6 @@ enum Event { ClearEvent, PushExceptionHandlerEvent, TraceEvent, - PushSubroutineEvent, - PopSubroutineEvent }; unsigned @@ -944,26 +870,6 @@ frameMapSizeInWords(MyThread* t, object method) return ceilingDivide(frameMapSizeInBits(t, method), BitsPerWord); } -uint16_t* -makeVisitTable(MyThread* t, Zone* zone, object method) -{ - unsigned size = codeLength(t, methodCode(t, method)) * 2; - uint16_t* table = static_cast(zone->allocate(size)); - memset(table, 0, size); - return table; -} - -uintptr_t* -makeRootTable(MyThread* t, Zone* zone, object method) -{ - unsigned size = frameMapSizeInWords(t, method) - * codeLength(t, methodCode(t, method)) - * BytesPerWord; - uintptr_t* table = static_cast(zone->allocate(size)); - memset(table, 0xFF, size); - return table; -} - enum Thunk { #define THUNK(s) s##Thunk, @@ -1121,7 +1027,7 @@ class Context { assert(t, resultSize == 8); return local::getThunk(t, intToDoubleThunk); } - + default: abort(t); } } @@ -1221,56 +1127,65 @@ class Context { MyThread* t; }; - Context(MyThread* t, BootContext* bootContext, object method): - thread(t), - zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), - assembler(t->arch->makeAssembler(t->m->heap, &zone)), - client(t), - compiler(makeCompiler(t->m->system, assembler, &zone, &client)), - method(method), - bootContext(bootContext), - objectPool(0), - subroutines(0), - traceLog(0), - visitTable(makeVisitTable(t, &zone, method)), - rootTable(makeRootTable(t, &zone, method)), - subroutineTable(0), - executableAllocator(0), - executableStart(0), - executableSize(0), - objectPoolCount(0), - traceLogCount(0), - dirtyRoots(false), - leaf(true), - eventLog(t->m->system, t->m->heap, 1024), - protector(this), - resource(this) + Context(MyThread* t, BootContext* bootContext, object method) + : thread(t), + zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), + client(t), + compiler(makeCompiler(t->m->system, assembler, &zone, &client)), + method(method), + bootContext(bootContext), + objectPool(0), + subroutineCount(0), + traceLog(0), + visitTable( + Slice::allocAndSet(&zone, + codeLength(t, methodCode(t, method)), + 0)), + rootTable( + Slice::allocAndSet(&zone, + codeLength(t, methodCode(t, method)) + * frameMapSizeInWords(t, method), + ~(uintptr_t)0)), + executableAllocator(0), + executableStart(0), + executableSize(0), + objectPoolCount(0), + traceLogCount(0), + dirtyRoots(false), + leaf(true), + eventLog(t->m->system, t->m->heap, 1024), + protector(this), + resource(this), + argumentBuffer( + (ir::Value**)t->m->heap->allocate(256 * sizeof(ir::Value*)), + 256) // below the maximal allowed parameter count for Java { } - Context(MyThread* t): - thread(t), - zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), - assembler(t->arch->makeAssembler(t->m->heap, &zone)), - client(t), - compiler(0), - method(0), - bootContext(0), - objectPool(0), - subroutines(0), - traceLog(0), - visitTable(0), - rootTable(0), - subroutineTable(0), - executableAllocator(0), - executableStart(0), - executableSize(0), - objectPoolCount(0), - traceLogCount(0), - dirtyRoots(false), - leaf(true), - eventLog(t->m->system, t->m->heap, 0), - protector(this), - resource(this) + Context(MyThread* t) + : thread(t), + zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes), + assembler(t->arch->makeAssembler(t->m->heap, &zone)), + client(t), + compiler(0), + method(0), + bootContext(0), + objectPool(0), + subroutineCount(0), + traceLog(0), + visitTable(0, 0), + rootTable(0, 0), + executableAllocator(0), + executableStart(0), + executableSize(0), + objectPoolCount(0), + traceLogCount(0), + dirtyRoots(false), + leaf(true), + eventLog(t->m->system, t->m->heap, 0), + protector(this), + resource(this), + argumentBuffer(0, 0) { } ~Context() { @@ -1291,6 +1206,20 @@ class Context { eventLog.dispose(); zone.dispose(); + + if (argumentBuffer.begin()) { + thread->m->heap->free(argumentBuffer.begin(), 256 * sizeof(ir::Value*)); + } + } + + void extendLogicalCode(unsigned more) + { + compiler->extendLogicalCode(more); + visitTable = visitTable.cloneAndSet(&zone, visitTable.count + more, 0); + rootTable = rootTable.cloneAndSet( + &zone, + rootTable.count + more * frameMapSizeInWords(thread, method), + ~(uintptr_t)0); } MyThread* thread; @@ -1301,11 +1230,10 @@ class Context { object method; BootContext* bootContext; PoolElement* objectPool; - Subroutine* subroutines; + unsigned subroutineCount; TraceElement* traceLog; - uint16_t* visitTable; - uintptr_t* rootTable; - Subroutine** subroutineTable; + Slice visitTable; + Slice rootTable; Allocator* executableAllocator; void* executableStart; unsigned executableSize; @@ -1316,6 +1244,7 @@ class Context { Vector eventLog; MyProtector protector; MyResource resource; + Slice argumentBuffer; }; unsigned @@ -1331,58 +1260,117 @@ translateLocalIndex(Context* context, unsigned footprint, unsigned index) } } -Compiler::Operand* -loadLocal(Context* context, unsigned footprint, unsigned index) +ir::Value* loadLocal(Context* context, + unsigned footprint, + ir::Type type, + unsigned index) { - return context->compiler->loadLocal - (footprint, translateLocalIndex(context, footprint, index)); + ir::Value* result = context->compiler->loadLocal( + type, translateLocalIndex(context, footprint, index)); + + assert(context->thread, type == result->type); + return result; } -void -storeLocal(Context* context, unsigned footprint, Compiler::Operand* value, - unsigned index) +void storeLocal(Context* context, + unsigned footprint, + ir::Type type UNUSED, + ir::Value* value, + unsigned index) { - context->compiler->storeLocal - (footprint, value, translateLocalIndex(context, footprint, index)); + assert(context->thread, type == value->type); + context->compiler->storeLocal(value, + translateLocalIndex(context, footprint, index)); } avian::util::FixedAllocator* codeAllocator(MyThread* t); +ir::Type operandTypeForFieldCode(Thread* t, unsigned code) +{ + + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + return ir::Type::i4(); + case LongField: + return ir::Type::i8(); + + case ObjectField: + return ir::Type::object(); + + case FloatField: + return ir::Type::f4(); + case DoubleField: + return ir::Type::f8(); + + case VoidField: + return ir::Type::void_(); + + default: + abort(t); + } +} + +unsigned methodReferenceParameterFootprint(Thread* t, + object reference, + bool isStatic) +{ + return parameterFootprint( + t, + reinterpret_cast( + &byteArrayBody(t, referenceSpec(t, reference), 0)), + isStatic); +} + +int methodReferenceReturnCode(Thread* t, object reference) +{ + unsigned parameterCount; + unsigned parameterFootprint; + unsigned returnCode; + scanMethodSpec(t, + reinterpret_cast( + &byteArrayBody(t, referenceSpec(t, reference), 0)), + true, + ¶meterCount, + ¶meterFootprint, + &returnCode); + + return returnCode; +} + class Frame { public: - enum StackType { - Integer, - Long, - Object - }; - - typedef Compiler::Operand* Value; - - Frame(Context* context, uint8_t* stackMap): - context(context), - t(context->thread), - c(context->compiler), - subroutine(0), - stackMap(stackMap), - ip(0), - sp(localSize()), - level(0) + Frame(Context* context, ir::Type* stackMap) + : context(context), + t(context->thread), + c(context->compiler), + subroutine(0), + stackMap(stackMap), + ip(0), + sp(localSize()), + level(0) { - memset(stackMap, 0, codeMaxStack(t, methodCode(t, context->method))); + memset(stackMap, + 0, + codeMaxStack(t, methodCode(t, context->method)) * sizeof(ir::Type)); } - Frame(Frame* f, uint8_t* stackMap): - context(f->context), - t(context->thread), - c(context->compiler), - subroutine(f->subroutine), - stackMap(stackMap), - ip(f->ip), - sp(f->sp), - level(f->level + 1) + Frame(Frame* f, ir::Type* stackMap) + : context(f->context), + t(context->thread), + c(context->compiler), + subroutine(f->subroutine), + stackMap(stackMap), + ip(f->ip), + sp(f->sp), + level(f->level + 1) { - memcpy(stackMap, f->stackMap, codeMaxStack - (t, methodCode(t, context->method))); + memcpy(stackMap, + f->stackMap, + codeMaxStack(t, methodCode(t, context->method)) * sizeof(ir::Type)); if (level > 1) { context->eventLog.append(PushContextEvent); @@ -1395,11 +1383,12 @@ class Frame { void dispose() { if (level > 1) { - context->eventLog.append(PopContextEvent); + context->eventLog.append(PopContextEvent); } } - Value append(object o) { + ir::Value* append(object o) + { BootContext* bc = context->bootContext; if (bc) { avian::codegen::Promise* p = new (bc->zone) avian::codegen::ListenPromise(t->m->system, bc->zone); @@ -1408,15 +1397,16 @@ class Frame { object pointer = makePointer(t, p); bc->constants = makeTriple(t, o, pointer, bc->constants); - return c->binaryOp(lir::Add, - TargetBytesPerWord, c->memory - (c->register_(t->arch->thread()), Compiler::AddressType, - TARGET_THREAD_HEAPIMAGE), c->promiseConstant - (p, Compiler::AddressType)); + return c->binaryOp( + lir::Add, + ir::Type::object(), + c->memory( + c->threadRegister(), ir::Type::object(), TARGET_THREAD_HEAPIMAGE), + c->promiseConstant(p, ir::Type::object())); } else { for (PoolElement* e = context->objectPool; e; e = e->next) { if (o == e->target) { - return c->address(e); + return c->address(ir::Type::object(), e); } } @@ -1424,7 +1414,7 @@ class Frame { ++ context->objectPoolCount; - return c->address(context->objectPool); + return c->address(ir::Type::object(), context->objectPool); } } @@ -1440,10 +1430,11 @@ class Frame { return localSize() + stackSize(); } - void set(unsigned index, uint8_t type) { + void set(unsigned index, ir::Type type) + { assert(t, index < frameSize()); - if (type == Object) { + if (type == ir::Type::object()) { context->eventLog.append(MarkEvent); context->eventLog.append2(index); } else { @@ -1457,170 +1448,22 @@ class Frame { } } - uint8_t get(unsigned index) { + ir::Type get(unsigned index) + { assert(t, index < frameSize()); int si = index - localSize(); assert(t, si >= 0); return stackMap[si]; } - void pushedInt() { - assert(t, sp + 1 <= frameSize()); - set(sp++, Integer); - } - - void pushedLong() { - assert(t, sp + 2 <= frameSize()); - set(sp++, Long); - set(sp++, Long); - } - - void pushedObject() { - assert(t, sp + 1 <= frameSize()); - set(sp++, Object); - } - void popped(unsigned count) { assert(t, sp >= count); assert(t, sp - count >= localSize()); while (count) { - set(--sp, Integer); + set(--sp, ir::Type::i4()); -- count; } } - - void poppedInt() { - assert(t, sp >= 1); - assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) == Integer); - -- sp; - } - - void poppedLong() { - assert(t, sp >= 1); - assert(t, sp - 2 >= localSize()); - assert(t, get(sp - 1) == Long); - assert(t, get(sp - 2) == Long); - sp -= 2; - } - - void poppedObject() { - assert(t, sp >= 1); - assert(t, sp - 1 >= localSize()); - assert(t, get(sp - 1) == Object); - set(--sp, Integer); - } - - void storedInt(unsigned index) { - assert(t, index < localSize()); - set(index, Integer); - } - - void storedLong(unsigned index) { - assert(t, index + 1 < localSize()); - set(index, Long); - set(index + 1, Long); - } - - void storedObject(unsigned index) { - assert(t, index < localSize()); - set(index, Object); - } - - void dupped() { - assert(t, sp + 1 <= frameSize()); - assert(t, sp - 1 >= localSize()); - set(sp, get(sp - 1)); - ++ sp; - } - - void duppedX1() { - assert(t, sp + 1 <= frameSize()); - assert(t, sp - 2 >= localSize()); - - uint8_t b2 = get(sp - 2); - uint8_t b1 = get(sp - 1); - - set(sp - 1, b2); - set(sp - 2, b1); - set(sp , b1); - - ++ sp; - } - - void duppedX2() { - assert(t, sp + 1 <= frameSize()); - assert(t, sp - 3 >= localSize()); - - uint8_t b3 = get(sp - 3); - uint8_t b2 = get(sp - 2); - uint8_t b1 = get(sp - 1); - - set(sp - 2, b3); - set(sp - 1, b2); - set(sp - 3, b1); - set(sp , b1); - - ++ sp; - } - - void dupped2() { - assert(t, sp + 2 <= frameSize()); - assert(t, sp - 2 >= localSize()); - - uint8_t b2 = get(sp - 2); - uint8_t b1 = get(sp - 1); - - set(sp, b2); - set(sp + 1, b1); - - sp += 2; - } - - void dupped2X1() { - assert(t, sp + 2 <= frameSize()); - assert(t, sp - 3 >= localSize()); - - uint8_t b3 = get(sp - 3); - uint8_t b2 = get(sp - 2); - uint8_t b1 = get(sp - 1); - - set(sp - 1, b3); - set(sp - 3, b2); - set(sp , b2); - set(sp - 2, b1); - set(sp + 1, b1); - - sp += 2; - } - - void dupped2X2() { - assert(t, sp + 2 <= frameSize()); - assert(t, sp - 4 >= localSize()); - - uint8_t b4 = get(sp - 4); - uint8_t b3 = get(sp - 3); - uint8_t b2 = get(sp - 2); - uint8_t b1 = get(sp - 1); - - set(sp - 2, b4); - set(sp - 1, b3); - set(sp - 4, b2); - set(sp , b2); - set(sp - 3, b1); - set(sp + 1, b1); - - sp += 2; - } - - void swapped() { - assert(t, sp - 2 >= localSize()); - - uint8_t saved = get(sp - 1); - - set(sp - 1, get(sp - 2)); - set(sp - 2, saved); - } avian::codegen::Promise* addressPromise(avian::codegen::Promise* p) { BootContext* bc = context->bootContext; @@ -1632,287 +1475,349 @@ class Frame { } } - Value addressOperand(avian::codegen::Promise* p) { - return c->promiseConstant(p, Compiler::AddressType); + ir::Value* addressOperand(avian::codegen::Promise* p) + { + return c->promiseConstant(p, ir::Type::iptr()); } - Value absoluteAddressOperand(avian::codegen::Promise* p) { + ir::Value* absoluteAddressOperand(avian::codegen::Promise* p) + { return context->bootContext ? c->binaryOp( lir::Add, - TargetBytesPerWord, - c->memory(c->register_(t->arch->thread()), - Compiler::AddressType, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), TARGET_THREAD_CODEIMAGE), c->promiseConstant( new (&context->zone) avian::codegen::OffsetPromise( p, -reinterpret_cast( codeAllocator(t)->memory.begin())), - Compiler::AddressType)) + ir::Type::iptr())) : addressOperand(p); } - Value machineIp(unsigned logicalIp) { - return c->promiseConstant(c->machineIp(logicalIp), Compiler::AddressType); + ir::Value* machineIpValue(unsigned logicalIp) + { + return c->promiseConstant(machineIp(logicalIp), ir::Type::iptr()); } - void visitLogicalIp(unsigned ip) { - c->visitLogicalIp(ip); - - context->eventLog.append(IpEvent); - context->eventLog.append2(ip); - } - - void startLogicalIp(unsigned ip) { - if (subroutine) { - context->subroutineTable[ip] = subroutine; + unsigned duplicatedIp(unsigned bytecodeIp) + { + if (UNLIKELY(subroutine)) { + return bytecodeIp + subroutine->duplicatedBaseIp; + } else { + return bytecodeIp; } + } - c->startLogicalIp(ip); + Promise* machineIp(unsigned bytecodeIp) + { + return c->machineIp(duplicatedIp(bytecodeIp)); + } + + void visitLogicalIp(unsigned bytecodeIp) + { + unsigned dupIp = duplicatedIp(bytecodeIp); + c->visitLogicalIp(dupIp); context->eventLog.append(IpEvent); - context->eventLog.append2(ip); - - this->ip = ip; + context->eventLog.append2(bytecodeIp); } - void pushQuiet(unsigned footprint, Value o) { - c->push(footprint, o); + void startLogicalIp(unsigned bytecodeIp) + { + unsigned dupIp = duplicatedIp(bytecodeIp); + c->startLogicalIp(dupIp); + + context->eventLog.append(IpEvent); + context->eventLog.append2(bytecodeIp); + + this->ip = bytecodeIp; } - void pushLongQuiet(Value o) { - pushQuiet(2, o); - } - - Value popQuiet(unsigned footprint) { - return c->pop(footprint); - } - - Value popLongQuiet() { - return popQuiet(2); - } - - void pushInt(Value o) { - pushQuiet(1, o); - pushedInt(); - } - - void pushAddress(Value o) { - pushQuiet(1, o); - pushedInt(); - } - - void pushObject(Value o) { - pushQuiet(1, o); - pushedObject(); + void push(ir::Type type, ir::Value* o) + { + assert(t, type == o->type); + c->push(o->type, o); + assert(t, sp + 1 <= frameSize()); + set(sp++, type); } void pushObject() { - c->pushed(); + c->pushed(ir::Type::object()); - pushedObject(); + assert(t, sp + 1 <= frameSize()); + set(sp++, ir::Type::object()); } - void pushLong(Value o) { - pushLongQuiet(o); - pushedLong(); + void pushLarge(ir::Type type, ir::Value* o) + { + assert(t, o->type == type); + c->push(type, o); + assert(t, sp + 2 <= frameSize()); + set(sp++, type); + set(sp++, type); } - void pop(unsigned count) { + void popFootprint(unsigned count) + { popped(count); c->popped(count); } - Value popInt() { - poppedInt(); - return popQuiet(1); - } - - Value popLong() { - poppedLong(); - return popLongQuiet(); - } - - Value popObject() { - poppedObject(); - return popQuiet(1); - } - - void loadInt(unsigned index) { - assert(t, index < localSize()); - pushInt(loadLocal(context, 1, index)); - } - - void loadLong(unsigned index) { - assert(t, index < static_cast(localSize() - 1)); - pushLong(loadLocal(context, 2, index)); - } - - void loadObject(unsigned index) { - assert(t, index < localSize()); - pushObject(loadLocal(context, 1, index)); - } - - void storeInt(unsigned index) { - storeLocal(context, 1, popInt(), index); - storedInt(translateLocalIndex(context, 1, index)); - } - - void storeLong(unsigned index) { - storeLocal(context, 2, popLong(), index); - storedLong(translateLocalIndex(context, 2, index)); - } - - void storeObject(unsigned index) { - storeLocal(context, 1, popObject(), index); - storedObject(translateLocalIndex(context, 1, index)); - } - - void storeObjectOrAddress(unsigned index) { - storeLocal(context, 1, popQuiet(1), index); - + ir::Value* pop(ir::Type type) + { assert(t, sp >= 1); assert(t, sp - 1 >= localSize()); - if (get(sp - 1) == Object) { - storedObject(translateLocalIndex(context, 1, index)); - } else { - storedInt(translateLocalIndex(context, 1, index)); - } + assert(t, get(sp - 1) == type); + set(--sp, ir::Type::i4()); + return c->pop(type); + } - popped(1); + ir::Value* popLarge(ir::Type type) + { + assert(t, sp >= 1); + assert(t, sp - 2 >= localSize()); + assert(t, get(sp - 1) == type); + assert(t, get(sp - 2) == type); + sp -= 2; + return c->pop(type); + } + + void load(ir::Type type, unsigned index) + { + assert(t, index < localSize()); + push(type, loadLocal(context, 1, type, index)); + } + + void loadLarge(ir::Type type, unsigned index) { + assert(t, index < static_cast(localSize() - 1)); + pushLarge(type, loadLocal(context, 2, type, index)); + } + + void store(ir::Type type, unsigned index) + { + assert(t, + type == ir::Type::i4() || type == ir::Type::f4() + || type == ir::Type::object()); + storeLocal(context, 1, type, pop(type), index); + unsigned ti = translateLocalIndex(context, 1, index); + assert(t, ti < localSize()); + set(ti, type); + } + + void storeLarge(ir::Type type, unsigned index) { + storeLocal(context, 2, type, popLarge(type), index); + unsigned ti = translateLocalIndex(context, 2, index); + assert(t, ti + 1 < localSize()); + set(ti, type); + set(ti + 1, type); } void dup() { - pushQuiet(1, c->peek(1, 0)); + c->push(ir::Type::i4(), c->peek(1, 0)); - dupped(); + assert(t, sp + 1 <= frameSize()); + assert(t, sp - 1 >= localSize()); + set(sp, get(sp - 1)); + ++ sp; } void dupX1() { - Value s0 = popQuiet(1); - Value s1 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); - pushQuiet(1, s0); - pushQuiet(1, s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); - duppedX1(); + assert(t, sp + 1 <= frameSize()); + assert(t, sp - 2 >= localSize()); + + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 1, b2); + set(sp - 2, b1); + set(sp , b1); + + ++ sp; } void dupX2() { - Value s0 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); - if (get(sp - 2) == Long) { - Value s1 = popLongQuiet(); + if (get(sp - 2) == ir::Type::i8()) { + ir::Value* s1 = c->pop(ir::Type::i8()); - pushQuiet(1, s0); - pushLongQuiet(s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i8(), s1); + c->push(ir::Type::i4(), s0); } else { - Value s1 = popQuiet(1); - Value s2 = popQuiet(1); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); - pushQuiet(1, s0); - pushQuiet(1, s2); - pushQuiet(1, s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); } - duppedX2(); + assert(t, sp + 1 <= frameSize()); + assert(t, sp - 3 >= localSize()); + + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 2, b3); + set(sp - 1, b2); + set(sp - 3, b1); + set(sp , b1); + + ++ sp; } void dup2() { - if (get(sp - 1) == Long) { - pushLongQuiet(c->peek(2, 0)); + if (get(sp - 1) == ir::Type::i8()) { + c->push(ir::Type::i8(), c->peek(2, 0)); } else { - Value s0 = popQuiet(1); - Value s1 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); - pushQuiet(1, s1); - pushQuiet(1, s0); - pushQuiet(1, s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); } - dupped2(); + assert(t, sp + 2 <= frameSize()); + assert(t, sp - 2 >= localSize()); + + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp, b2); + set(sp + 1, b1); + + sp += 2; } void dup2X1() { - if (get(sp - 1) == Long) { - Value s0 = popLongQuiet(); - Value s1 = popQuiet(1); + if (get(sp - 1) == ir::Type::i8()) { + ir::Value* s0 = c->pop(ir::Type::i8()); + ir::Value* s1 = c->pop(ir::Type::i4()); - pushLongQuiet(s0); - pushQuiet(1, s1); - pushLongQuiet(s0); + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i8(), s0); } else { - Value s0 = popQuiet(1); - Value s1 = popQuiet(1); - Value s2 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); - pushQuiet(1, s1); - pushQuiet(1, s0); - pushQuiet(1, s2); - pushQuiet(1, s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); } - dupped2X1(); + assert(t, sp + 2 <= frameSize()); + assert(t, sp - 3 >= localSize()); + + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 1, b3); + set(sp - 3, b2); + set(sp , b2); + set(sp - 2, b1); + set(sp + 1, b1); + + sp += 2; } void dup2X2() { - if (get(sp - 1) == Long) { - Value s0 = popLongQuiet(); + if (get(sp - 1) == ir::Type::i8()) { + ir::Value* s0 = c->pop(ir::Type::i8()); - if (get(sp - 3) == Long) { - Value s1 = popLongQuiet(); + if (get(sp - 3) == ir::Type::i8()) { + ir::Value* s1 = c->pop(ir::Type::i8()); - pushLongQuiet(s0); - pushLongQuiet(s1); - pushLongQuiet(s0); + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i8(), s1); + c->push(ir::Type::i8(), s0); } else { - Value s1 = popQuiet(1); - Value s2 = popQuiet(1); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); - pushLongQuiet(s0); - pushQuiet(1, s2); - pushQuiet(1, s1); - pushLongQuiet(s0); + c->push(ir::Type::i8(), s0); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i8(), s0); } } else { - Value s0 = popQuiet(1); - Value s1 = popQuiet(1); - Value s2 = popQuiet(1); - Value s3 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); + ir::Value* s2 = c->pop(ir::Type::i4()); + ir::Value* s3 = c->pop(ir::Type::i4()); - pushQuiet(1, s1); - pushQuiet(1, s0); - pushQuiet(1, s3); - pushQuiet(1, s2); - pushQuiet(1, s1); - pushQuiet(1, s0); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s3); + c->push(ir::Type::i4(), s2); + c->push(ir::Type::i4(), s1); + c->push(ir::Type::i4(), s0); } - dupped2X2(); + assert(t, sp + 2 <= frameSize()); + assert(t, sp - 4 >= localSize()); + + ir::Type b4 = get(sp - 4); + ir::Type b3 = get(sp - 3); + ir::Type b2 = get(sp - 2); + ir::Type b1 = get(sp - 1); + + set(sp - 2, b4); + set(sp - 1, b3); + set(sp - 4, b2); + set(sp , b2); + set(sp - 3, b1); + set(sp + 1, b1); + + sp += 2; } void swap() { - Value s0 = popQuiet(1); - Value s1 = popQuiet(1); + ir::Value* s0 = c->pop(ir::Type::i4()); + ir::Value* s1 = c->pop(ir::Type::i4()); - pushQuiet(1, s0); - pushQuiet(1, s1); + c->push(ir::Type::i4(), s0); + c->push(ir::Type::i4(), s1); - swapped(); + assert(t, sp - 2 >= localSize()); + + ir::Type saved = get(sp - 1); + + set(sp - 1, get(sp - 2)); + set(sp - 2, saved); } TraceElement* trace(object target, unsigned flags) { unsigned mapSize = frameMapSizeInWords(t, context->method); - TraceElement* e = context->traceLog = new - (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) - TraceElement(context, ip, target, flags, context->traceLog, mapSize); + TraceElement* e = context->traceLog = new ( + context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) + TraceElement(context, + duplicatedIp(ip), + target, + flags, + context->traceLog, + mapSize); ++ context->traceLogCount; @@ -1922,77 +1827,131 @@ class Frame { return e; } - unsigned startSubroutine(unsigned ip, avian::codegen::Promise* returnAddress) { - pushAddress(absoluteAddressOperand(returnAddress)); + void pushReturnValue(unsigned code, ir::Value* result) + { + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case IntField: + return push(ir::Type::i4(), result); + case FloatField: + return push(ir::Type::f4(), result); - Subroutine* subroutine = 0; - for (Subroutine* s = context->subroutines; s; s = s->listNext) { - if (s->ip == ip) { - subroutine = s; - break; - } + case ObjectField: + return push(ir::Type::object(), result); + + case LongField: + return pushLarge(ir::Type::i8(), result); + case DoubleField: + return pushLarge(ir::Type::f8(), result); + + default: + abort(t); + } + } + + Slice peekMethodArguments(unsigned footprint) + { + ir::Value** ptr = context->argumentBuffer.items; + + for (unsigned i = 0; i < footprint; i++) { + *(ptr++) = c->peek(1, footprint - i - 1); } - if (subroutine == 0) { - context->subroutines = subroutine = new - (context->zone.allocate(sizeof(Subroutine))) - Subroutine(ip, context->eventLog.length() + 1 + BytesPerWord + 2, - context->subroutines, this->subroutine); + return Slice(context->argumentBuffer.items, footprint); + } - if (context->subroutineTable == 0) { - unsigned size = codeLength(t, methodCode(t, context->method)) - * sizeof(Subroutine*); + void stackCall(ir::Value* methodValue, + object methodObject, + unsigned flags, + TraceElement* trace) + { + unsigned footprint = methodParameterFootprint(t, methodObject); + unsigned returnCode = methodReturnCode(t, methodObject); + ir::Value* result = c->stackCall(methodValue, + flags, + trace, + operandTypeForFieldCode(t, returnCode), + peekMethodArguments(footprint)); - context->subroutineTable = static_cast - (context->zone.allocate(size)); + popFootprint(footprint); - memset(context->subroutineTable, 0, size); - } + if (returnCode != VoidField) { + pushReturnValue(returnCode, result); + } + } + + void referenceStackCall(bool isStatic, + ir::Value* methodValue, + object methodReference, + unsigned flags, + TraceElement* trace) + { + unsigned footprint + = methodReferenceParameterFootprint(t, methodReference, isStatic); + unsigned returnCode = methodReferenceReturnCode(t, methodReference); + ir::Value* result = c->stackCall(methodValue, + flags, + trace, + operandTypeForFieldCode(t, returnCode), + peekMethodArguments(footprint)); + + popFootprint(footprint); + + if (returnCode != VoidField) { + pushReturnValue(returnCode, result); + } + } + + void startSubroutine(unsigned ip, unsigned returnAddress) + { + // Push a dummy value to the stack, representing the return address (which + // we don't need, since we're expanding everything statically). + // TODO: in the future, push a value that we can track through type checking + push(ir::Type::object(), c->constant(0, ir::Type::object())); + + if (DebugInstructions) { + fprintf(stderr, "startSubroutine %u %u\n", ip, returnAddress); } - subroutine->handle = c->startSubroutine(); + Subroutine* subroutine = new (&context->zone) + Subroutine(context->subroutineCount++, + returnAddress, + codeLength(t, methodCode(t, context->method)), + this->subroutine); + + context->extendLogicalCode(codeLength(t, methodCode(t, context->method))); + this->subroutine = subroutine; - - SubroutineCall* call = new(&context->zone) - SubroutineCall(subroutine, returnAddress); - - context->eventLog.append(PushSubroutineEvent); - context->eventLog.appendAddress(call); - - unsigned nextIndexIndex = context->eventLog.length(); - context->eventLog.append2(0); - - c->saveLocals(); - - return nextIndexIndex; } - void returnFromSubroutine(unsigned returnAddressLocal) { - c->returnFromSubroutine - (subroutine->handle, loadLocal(context, 1, returnAddressLocal)); + unsigned endSubroutine(unsigned returnAddressLocal UNUSED) + { + // TODO: use returnAddressLocal to decide which subroutine we're returning + // from (in case it's ever not the most recent one entered). I'm unsure of + // whether such a subroutine pattern would pass bytecode verification. - subroutine->stackIndex = localOffsetFromStack - (t, translateLocalIndex(context, 1, returnAddressLocal), - context->method); + unsigned returnAddress = subroutine->returnAddress; + + if (DebugInstructions) { + fprintf(stderr, "endSubroutine %u %u\n", ip, returnAddress); + } + + subroutine = subroutine->outer; + + return returnAddress; } - void endSubroutine(unsigned nextIndexIndex) { - c->linkSubroutine(subroutine->handle); - - poppedInt(); - - context->eventLog.append(PopSubroutineEvent); - - context->eventLog.set2(nextIndexIndex, context->eventLog.length()); - - subroutine = subroutine->stackNext; - } - Context* context; MyThread* t; avian::codegen::Compiler* c; + + // Innermost subroutine we're compiling code for Subroutine* subroutine; - uint8_t* stackMap; + + ir::Type* stackMap; unsigned ip; unsigned sp; unsigned level; @@ -3052,81 +3011,30 @@ resultSize(MyThread* t, unsigned code) } } -void -pushReturnValue(MyThread* t, Frame* frame, unsigned code, - Compiler::Operand* result) +ir::Value* popField(MyThread* t, Frame* frame, int code) { switch (code) { case ByteField: case BooleanField: case CharField: case ShortField: - case FloatField: case IntField: - return frame->pushInt(result); - - case ObjectField: - return frame->pushObject(result); + return frame->pop(ir::Type::i4()); + case FloatField: + return frame->pop(ir::Type::f4()); case LongField: + return frame->popLarge(ir::Type::i8()); case DoubleField: - return frame->pushLong(result); - - default: - abort(t); - } -} - -Compiler::Operand* -popField(MyThread* t, Frame* frame, int code) -{ - switch (code) { - case ByteField: - case BooleanField: - case CharField: - case ShortField: - case FloatField: - case IntField: - return frame->popInt(); - - case DoubleField: - case LongField: - return frame->popLong(); + return frame->popLarge(ir::Type::f8()); case ObjectField: - return frame->popObject(); + return frame->pop(ir::Type::object()); default: abort(t); } } -Compiler::OperandType -operandTypeForFieldCode(Thread* t, unsigned code) -{ - switch (code) { - case ByteField: - case BooleanField: - case CharField: - case ShortField: - case IntField: - case LongField: - return Compiler::IntegerType; - - case ObjectField: - return Compiler::ObjectType; - - case FloatField: - case DoubleField: - return Compiler::FloatType; - - case VoidField: - return Compiler::VoidType; - - default: - abort(t); - } -} - bool useLongJump(MyThread* t, uintptr_t target) { @@ -3142,18 +3050,20 @@ useLongJump(MyThread* t, uintptr_t target) } void compileSafePoint(MyThread* t, Compiler* c, Frame* frame) { - c->call - (c->constant(getThunk(t, idleIfNecessaryThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 1, c->register_(t->arch->thread())); + c->call(c->constant(getThunk(t, idleIfNecessaryThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 1, + c->threadRegister()); } -Compiler::Operand* -compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, - bool useThunk, unsigned rSize, avian::codegen::Promise* addressPromise) +void compileDirectInvoke(MyThread* t, + Frame* frame, + object target, + bool tailCall, + bool useThunk, + avian::codegen::Promise* addressPromise) { avian::codegen::Compiler* c = frame->c; @@ -3183,66 +3093,52 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, (frame->context->zone.allocate(sizeof(TraceElementPromise))) TraceElementPromise(t->m->system, trace); - Compiler::Operand* result = c->stackCall - (c->promiseConstant(returnAddressPromise, Compiler::AddressType), - flags, - trace, - rSize, - operandTypeForFieldCode(t, methodReturnCode(t, target)), - methodParameterFootprint(t, target)); + frame->stackCall( + c->promiseConstant(returnAddressPromise, ir::Type::iptr()), + target, + flags, + trace); - c->store - (TargetBytesPerWord, - frame->absoluteAddressOperand(returnAddressPromise), - TargetBytesPerWord, c->memory - (c->register_(t->arch->thread()), Compiler::AddressType, - TARGET_THREAD_TAILADDRESS)); + c->store(frame->absoluteAddressOperand(returnAddressPromise), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_TAILADDRESS)); - c->exit - (c->constant - ((methodFlags(t, target) & ACC_NATIVE) - ? nativeThunk(t) : defaultThunk(t), - Compiler::AddressType)); - - return result; + c->exit(c->constant((methodFlags(t, target) & ACC_NATIVE) + ? nativeThunk(t) + : defaultThunk(t), + ir::Type::iptr())); } else { - return c->stackCall - (c->constant(defaultThunk(t), Compiler::AddressType), - flags, - frame->trace(target, traceFlags), - rSize, - operandTypeForFieldCode(t, methodReturnCode(t, target)), - methodParameterFootprint(t, target)); + return frame->stackCall(c->constant(defaultThunk(t), ir::Type::iptr()), + target, + flags, + frame->trace(target, traceFlags)); } } else { - Compiler::Operand* address = - (addressPromise - ? c->promiseConstant(addressPromise, Compiler::AddressType) - : c->constant(methodAddress(t, target), Compiler::AddressType)); + ir::Value* address + = (addressPromise + ? c->promiseConstant(addressPromise, ir::Type::iptr()) + : c->constant(methodAddress(t, target), ir::Type::iptr())); - return c->stackCall - (address, - flags, - tailCall ? 0 : frame->trace - ((methodFlags(t, target) & ACC_NATIVE) ? target : 0, 0), - rSize, - operandTypeForFieldCode(t, methodReturnCode(t, target)), - methodParameterFootprint(t, target)); + frame->stackCall( + address, + target, + flags, + tailCall ? 0 + : frame->trace( + (methodFlags(t, target) & ACC_NATIVE) ? target : 0, 0)); } } bool compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) { - unsigned rSize = resultSize(t, methodReturnCode(t, target)); - - Compiler::Operand* result = 0; - // don't bother calling an empty method unless calling it might // cause the class to be initialized, which may have side effects if (emptyMethod(t, target) and (not classNeedsInit(t, methodClass(t, target)))) { + frame->popFootprint(methodParameterFootprint(t, target)); tailCall = false; } else { BootContext* bc = frame->context->bootContext; @@ -3258,78 +3154,33 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) object pointer = makePointer(t, p); bc->calls = makeTriple(t, target, pointer, bc->calls); - result = compileDirectInvoke - (t, frame, target, tailCall, false, rSize, p); + compileDirectInvoke(t, frame, target, tailCall, false, p); } else { - result = compileDirectInvoke - (t, frame, target, tailCall, true, rSize, 0); + compileDirectInvoke(t, frame, target, tailCall, true, 0); } } else if (unresolved(t, methodAddress(t, target)) or classNeedsInit(t, methodClass(t, target))) { - result = compileDirectInvoke - (t, frame, target, tailCall, true, rSize, 0); + compileDirectInvoke(t, frame, target, tailCall, true, 0); } else { - result = compileDirectInvoke - (t, frame, target, tailCall, false, rSize, 0); + compileDirectInvoke(t, frame, target, tailCall, false, 0); } } - frame->pop(methodParameterFootprint(t, target)); - - if (rSize) { - pushReturnValue(t, frame, methodReturnCode(t, target), result); - } - return tailCall; } -unsigned -methodReferenceParameterFootprint(Thread* t, object reference, bool isStatic) +void compileReferenceInvoke(Frame* frame, + ir::Value* method, + object reference, + bool isStatic, + bool tailCall) { - return parameterFootprint - (t, reinterpret_cast - (&byteArrayBody(t, referenceSpec(t, reference), 0)), isStatic); -} - -int -methodReferenceReturnCode(Thread* t, object reference) -{ - unsigned parameterCount; - unsigned parameterFootprint; - unsigned returnCode; - scanMethodSpec - (t, reinterpret_cast - (&byteArrayBody(t, referenceSpec(t, reference), 0)), true, - ¶meterCount, ¶meterFootprint, &returnCode); - - return returnCode; -} - -void -compileReferenceInvoke(MyThread* t, Frame* frame, Compiler::Operand* method, - object reference, bool isStatic, bool tailCall) -{ - unsigned parameterFootprint - = methodReferenceParameterFootprint(t, reference, isStatic); - - int returnCode = methodReferenceReturnCode(t, reference); - - unsigned rSize = resultSize(t, returnCode); - - Compiler::Operand* result = frame->c->stackCall - (method, - tailCall ? Compiler::TailJump : 0, - frame->trace(0, 0), - rSize, - operandTypeForFieldCode(t, returnCode), - parameterFootprint); - - frame->pop(parameterFootprint); - - if (rSize) { - pushReturnValue(t, frame, returnCode, result); - } + frame->referenceStackCall(isStatic, + method, + reference, + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0)); } void @@ -3342,40 +3193,27 @@ compileDirectReferenceInvoke(MyThread* t, Frame* frame, Thunk thunk, object pair = makePair(t, frame->context->method, reference); - compileReferenceInvoke - (t, frame, c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::AddressType, - 2, c->register_(t->arch->thread()), frame->append(pair)), - reference, isStatic, tailCall); + compileReferenceInvoke( + frame, + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + 2, + c->threadRegister(), + frame->append(pair)), + reference, + isStatic, + tailCall); } -void -compileAbstractInvoke(MyThread* t, Frame* frame, Compiler::Operand* method, - object target, bool tailCall) +void compileAbstractInvoke(Frame* frame, + ir::Value* method, + object target, + bool tailCall) { - unsigned parameterFootprint = methodParameterFootprint(t, target); - - int returnCode = methodReturnCode(t, target); - - unsigned rSize = resultSize(t, returnCode); - - Compiler::Operand* result = frame->c->stackCall - (method, - tailCall ? Compiler::TailJump : 0, - frame->trace(0, 0), - rSize, - operandTypeForFieldCode(t, returnCode), - parameterFootprint); - - frame->pop(parameterFootprint); - - if (rSize) { - pushReturnValue(t, frame, returnCode, result); - } + frame->stackCall( + method, target, tailCall ? Compiler::TailJump : 0, frame->trace(0, 0)); } void @@ -3384,15 +3222,17 @@ compileDirectAbstractInvoke(MyThread* t, Frame* frame, Thunk thunk, { avian::codegen::Compiler* c = frame->c; - compileAbstractInvoke - (t, frame, c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::AddressType, - 2, c->register_(t->arch->thread()), frame->append(target)), - target, tailCall); + compileAbstractInvoke( + frame, + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + 2, + c->threadRegister(), + frame->append(target)), + target, + tailCall); } void @@ -3402,21 +3242,23 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) object method = frame->context->method; if (methodFlags(t, method) & ACC_SYNCHRONIZED) { - Compiler::Operand* lock; + ir::Value* lock; if (methodFlags(t, method) & ACC_STATIC) { PROTECT(t, method); lock = frame->append(methodClass(t, method)); } else { - lock = loadLocal(frame->context, 1, savedTargetIndex(t, method)); + lock = loadLocal( + frame->context, 1, ir::Type::object(), savedTargetIndex(t, method)); } - - c->call(c->constant(function, Compiler::AddressType), + + c->call(c->constant(function, ir::Type::iptr()), 0, frame->trace(0, 0), - 0, - Compiler::VoidType, - 2, c->register_(t->arch->thread()), lock); + ir::Type::void_(), + 2, + c->threadRegister(), + lock); } } @@ -3430,8 +3272,12 @@ handleEntrance(MyThread* t, Frame* frame) { // save 'this' pointer in case it is overwritten. unsigned index = savedTargetIndex(t, method); - storeLocal(frame->context, 1, loadLocal(frame->context, 1, 0), index); - frame->set(index, Frame::Object); + storeLocal(frame->context, + 1, + ir::Type::object(), + loadLocal(frame->context, 1, ir::Type::object(), 0), + index); + frame->set(index, ir::Type::object()); } handleMonitorEvent @@ -3571,10 +3417,13 @@ lir::TernaryOperation toCompilerJumpOp(MyThread* t, unsigned instruction) { } } -bool -integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, - unsigned size, Compiler::Operand* a, Compiler::Operand* b, - unsigned* newIpp) +bool integerBranch(MyThread* t, + Frame* frame, + object code, + unsigned& ip, + ir::Value* a, + ir::Value* b, + unsigned* newIpp) { if (ip + 3 > codeLength(t, code)) { return false; @@ -3585,8 +3434,8 @@ integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, uint32_t offset = codeReadInt16(t, code, ip); uint32_t newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); - - Compiler::Operand* target = frame->machineIp(newIp); + + ir::Value* target = frame->machineIpValue(newIp); switch (instruction) { case ifeq: @@ -3595,7 +3444,7 @@ integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, case ifge: case iflt: case ifle: - c->condJump(toCompilerJumpOp(t, instruction), size, a, b, target); + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); break; default: @@ -3645,10 +3494,14 @@ lir::TernaryOperation toCompilerFloatJumpOp(MyThread* t, } } -bool -floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, - unsigned size, bool lessIfUnordered, Compiler::Operand* a, - Compiler::Operand* b, unsigned* newIpp) +bool floatBranch(MyThread* t, + Frame* frame, + object code, + unsigned& ip, + bool lessIfUnordered, + ir::Value* a, + ir::Value* b, + unsigned* newIpp) { if (ip + 3 > codeLength(t, code)) { return false; @@ -3659,8 +3512,8 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, uint32_t offset = codeReadInt16(t, code, ip); uint32_t newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); - - Compiler::Operand* target = frame->machineIp(newIp); + + ir::Value* target = frame->machineIpValue(newIp); switch (instruction) { case ifeq: @@ -3670,7 +3523,6 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, case iflt: case ifle: c->condJump(toCompilerFloatJumpOp(t, instruction, lessIfUnordered), - size, a, b, target); @@ -3685,11 +3537,13 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return true; } -Compiler::Operand* -popLongAddress(Frame* frame) +ir::Value* popLongAddress(Frame* frame) { - return TargetBytesPerWord == 8 ? frame->popLong() : frame->c->load - (8, 8, frame->popLong(), TargetBytesPerWord); + return TargetBytesPerWord == 8 + ? frame->popLarge(ir::Type::i8()) + : frame->c->load(ir::SignExtend, + frame->popLarge(ir::Type::i8()), + ir::Type::iptr()); } bool @@ -3706,17 +3560,23 @@ intrinsic(MyThread* t, Frame* frame, object target) if (MATCH(methodName(t, target), "sqrt") and MATCH(methodSpec(t, target), "(D)D")) { - frame->pushLong(c->unaryOp(lir::FloatSquareRoot, 8, frame->popLong())); + frame->pushLarge( + ir::Type::f8(), + c->unaryOp(lir::FloatSquareRoot, frame->popLarge(ir::Type::f8()))); return true; } else if (MATCH(methodName(t, target), "abs")) { if (MATCH(methodSpec(t, target), "(I)I")) { - frame->pushInt(c->unaryOp(lir::Absolute, 4, frame->popInt())); + frame->push(ir::Type::i4(), + c->unaryOp(lir::Absolute, frame->pop(ir::Type::i4()))); return true; } else if (MATCH(methodSpec(t, target), "(J)J")) { - frame->pushLong(c->unaryOp(lir::Absolute, 8, frame->popLong())); + frame->pushLarge( + ir::Type::i8(), + c->unaryOp(lir::Absolute, frame->popLarge(ir::Type::i8()))); return true; } else if (MATCH(methodSpec(t, target), "(F)F")) { - frame->pushInt(c->unaryOp(lir::FloatAbsolute, 4, frame->popInt())); + frame->push(ir::Type::f4(), + c->unaryOp(lir::FloatAbsolute, frame->pop(ir::Type::f4()))); return true; } } @@ -3725,120 +3585,108 @@ intrinsic(MyThread* t, Frame* frame, object target) if (MATCH(methodName(t, target), "getByte") and MATCH(methodSpec(t, target), "(J)B")) { - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - frame->pushInt - (c->load - (1, 1, c->memory(address, Compiler::IntegerType, 0, 0, 1), - TargetBytesPerWord)); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(address, ir::Type::i1()), + ir::Type::i4())); return true; } else if (MATCH(methodName(t, target), "putByte") and MATCH(methodSpec(t, target), "(JB)V")) { - Compiler::Operand* value = frame->popInt(); - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - c->store - (TargetBytesPerWord, value, 1, c->memory - (address, Compiler::IntegerType, 0, 0, 1)); + ir::Value* value = frame->pop(ir::Type::i4()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::i1())); return true; } else if ((MATCH(methodName(t, target), "getShort") and MATCH(methodSpec(t, target), "(J)S")) or (MATCH(methodName(t, target), "getChar") and MATCH(methodSpec(t, target), "(J)C"))) { - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - frame->pushInt - (c->load - (2, 2, c->memory(address, Compiler::IntegerType, 0, 0, 1), - TargetBytesPerWord)); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(address, ir::Type::i2()), + ir::Type::i4())); return true; } else if ((MATCH(methodName(t, target), "putShort") and MATCH(methodSpec(t, target), "(JS)V")) or (MATCH(methodName(t, target), "putChar") and MATCH(methodSpec(t, target), "(JC)V"))) { - Compiler::Operand* value = frame->popInt(); - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - c->store - (TargetBytesPerWord, value, 2, c->memory - (address, Compiler::IntegerType, 0, 0, 1)); + ir::Value* value = frame->pop(ir::Type::i4()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::i2())); return true; } else if ((MATCH(methodName(t, target), "getInt") and MATCH(methodSpec(t, target), "(J)I")) or (MATCH(methodName(t, target), "getFloat") and MATCH(methodSpec(t, target), "(J)F"))) { - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - frame->pushInt - (c->load - (4, 4, c->memory - (address, MATCH(methodName(t, target), "getInt") - ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1), - TargetBytesPerWord)); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + ir::Type type = MATCH(methodName(t, target), "getInt") ? ir::Type::i4() + : ir::Type::f4(); + frame->push(type, + c->load(ir::SignExtend, c->memory(address, type), type)); return true; } else if ((MATCH(methodName(t, target), "putInt") and MATCH(methodSpec(t, target), "(JI)V")) or (MATCH(methodName(t, target), "putFloat") and MATCH(methodSpec(t, target), "(JF)V"))) { - Compiler::Operand* value = frame->popInt(); - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - c->store - (TargetBytesPerWord, value, 4, c->memory - (address, MATCH(methodName(t, target), "putInt") - ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1)); + ir::Type type = MATCH(methodName(t, target), "putInt") ? ir::Type::i4() + : ir::Type::f4(); + ir::Value* value = frame->pop(type); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, type)); return true; } else if ((MATCH(methodName(t, target), "getLong") and MATCH(methodSpec(t, target), "(J)J")) or (MATCH(methodName(t, target), "getDouble") and MATCH(methodSpec(t, target), "(J)D"))) { - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - frame->pushLong - (c->load - (8, 8, c->memory - (address, MATCH(methodName(t, target), "getLong") - ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1), - 8)); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + ir::Type type = MATCH(methodName(t, target), "getLong") ? ir::Type::i8() + : ir::Type::f8(); + frame->pushLarge(type, + c->load(ir::SignExtend, c->memory(address, type), type)); return true; } else if ((MATCH(methodName(t, target), "putLong") and MATCH(methodSpec(t, target), "(JJ)V")) or (MATCH(methodName(t, target), "putDouble") and MATCH(methodSpec(t, target), "(JD)V"))) { - Compiler::Operand* value = frame->popLong(); - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - c->store - (8, value, 8, c->memory - (address, MATCH(methodName(t, target), "putLong") - ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1)); + ir::Type type = MATCH(methodName(t, target), "putLong") ? ir::Type::i8() + : ir::Type::f8(); + ir::Value* value = frame->popLarge(type); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, type)); return true; } else if (MATCH(methodName(t, target), "getAddress") and MATCH(methodSpec(t, target), "(J)J")) { - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - frame->pushLong - (c->load - (TargetBytesPerWord, TargetBytesPerWord, - c->memory(address, Compiler::AddressType, 0, 0, 1), 8)); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + frame->pushLarge(ir::Type::i8(), + c->load(ir::SignExtend, + c->memory(address, ir::Type::iptr()), + ir::Type::i8())); return true; } else if (MATCH(methodName(t, target), "putAddress") and MATCH(methodSpec(t, target), "(JJ)V")) { - Compiler::Operand* value = frame->popLong(); - Compiler::Operand* address = popLongAddress(frame); - frame->popObject(); - c->store - (8, value, TargetBytesPerWord, c->memory - (address, Compiler::AddressType, 0, 0, 1)); + ir::Value* value = frame->popLarge(ir::Type::i8()); + ir::Value* address = popLongAddress(frame); + frame->pop(ir::Type::object()); + c->store(value, c->memory(address, ir::Type::iptr())); return true; } } @@ -3914,18 +3762,18 @@ class SwitchState { SwitchState(Compiler::State* state, unsigned count, unsigned defaultIp, - Compiler::Operand* key, + ir::Value* key, avian::codegen::Promise* start, int bottom, - int top): - state(state), - count(count), - defaultIp(defaultIp), - key(key), - start(start), - bottom(bottom), - top(top), - index(0) + int top) + : state(state), + count(count), + defaultIp(defaultIp), + key(key), + start(start), + bottom(bottom), + top(top), + index(0) { } Frame* frame() { @@ -3941,7 +3789,7 @@ class SwitchState { Compiler::State* state; unsigned count; unsigned defaultIp; - Compiler::Operand* key; + ir::Value* key; avian::codegen::Promise* start; int bottom; int top; @@ -4020,8 +3868,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, unsigned newIp; stack.pushValue(Return); + start: - uint8_t* stackMap = static_cast(stack.push(stackSize)); + ir::Type* stackMap + = static_cast(stack.push(stackSize * sizeof(ir::Type))); frame = new (stack.push(sizeof(Frame))) Frame(frame, stackMap); loop: @@ -4029,7 +3879,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, PROTECT(t, code); while (ip < codeLength(t, code)) { - if (context->visitTable[ip] ++) { + if (context->visitTable[frame->duplicatedIp(ip)]++) { // we've already visited this part of the code frame->visitLogicalIp(ip); goto next; @@ -4043,18 +3893,42 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, exceptionHandlerStart = -1; frame->pushObject(); - - c->call - (c->constant(getThunk(t, gcIfNecessaryThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 1, c->register_(t->arch->thread())); + + c->call(c->constant(getThunk(t, gcIfNecessaryThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 1, + c->threadRegister()); } - + // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); + if (DebugInstructions) { + unsigned startingIp = ip; + fprintf(stderr, " stack: ["); + for (size_t i = frame->localSize(); i < frame->sp; i++) { + ir::Type ty = frame->get(i); + if (ty == ir::Type::i4()) { + fprintf(stderr, "I"); + } else if (ty == ir::Type::i8()) { + fprintf(stderr, "L"); + } else if (ty == ir::Type::f4()) { + fprintf(stderr, "F"); + } else if (ty == ir::Type::f8()) { + fprintf(stderr, "D"); + } else if (ty == ir::Type::object()) { + fprintf(stderr, "O"); + } else { + fprintf(stderr, "?"); + } + } + fprintf(stderr, "]\n"); + fprintf(stderr, "% 5d: ", startingIp); + avian::jvm::debug::printInstruction(&codeBody(t, code, 0), startingIp); + fprintf(stderr, "\n"); + } + unsigned instruction = codeBody(t, code, ip++); switch (instruction) { @@ -4066,8 +3940,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case iaload: case laload: case saload: { - Compiler::Operand* index = frame->popInt(); - Compiler::Operand* array = frame->popObject(); + ir::Value* index = frame->pop(ir::Type::i4()); + ir::Value* array = frame->pop(ir::Type::object()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); @@ -4080,66 +3954,68 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, switch (instruction) { case aaload: - frame->pushObject - (c->load - (TargetBytesPerWord, TargetBytesPerWord, c->memory - (array, Compiler::ObjectType, TargetArrayBody, index, - TargetBytesPerWord), - TargetBytesPerWord)); + frame->push( + ir::Type::object(), + c->load( + ir::SignExtend, + c->memory(array, ir::Type::object(), TargetArrayBody, index), + ir::Type::object())); break; case faload: - frame->pushInt - (c->load - (4, 4, c->memory - (array, Compiler::FloatType, TargetArrayBody, index, 4), - TargetBytesPerWord)); + frame->push( + ir::Type::f4(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::f4(), TargetArrayBody, index), + ir::Type::f4())); break; case iaload: - frame->pushInt - (c->load - (4, 4, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 4), - TargetBytesPerWord)); + frame->push( + ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::i4(), TargetArrayBody, index), + ir::Type::i4())); break; case baload: - frame->pushInt - (c->load - (1, 1, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 1), - TargetBytesPerWord)); + frame->push( + ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::i1(), TargetArrayBody, index), + ir::Type::i4())); break; case caload: - frame->pushInt - (c->loadz - (2, 2, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 2), - TargetBytesPerWord)); + frame->push( + ir::Type::i4(), + c->load(ir::ZeroExtend, + c->memory(array, ir::Type::i2(), TargetArrayBody, index), + ir::Type::i4())); break; case daload: - frame->pushLong - (c->load - (8, 8, c->memory - (array, Compiler::FloatType, TargetArrayBody, index, 8), 8)); + frame->pushLarge( + ir::Type::f8(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::f8(), TargetArrayBody, index), + ir::Type::f8())); break; case laload: - frame->pushLong - (c->load - (8, 8, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 8), 8)); + frame->pushLarge( + ir::Type::i8(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::i8(), TargetArrayBody, index), + ir::Type::i8())); break; case saload: - frame->pushInt - (c->load - (2, 2, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 2), - TargetBytesPerWord)); + frame->push( + ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(array, ir::Type::i2(), TargetArrayBody, index), + ir::Type::i4())); break; } } break; @@ -4152,17 +4028,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case iastore: case lastore: case sastore: { - Compiler::Operand* value; - if (instruction == dastore or instruction == lastore) { - value = frame->popLong(); + ir::Value* value; + if (instruction == lastore) { + value = frame->popLarge(ir::Type::i8()); + } else if (instruction == dastore) { + value = frame->popLarge(ir::Type::f8()); } else if (instruction == aastore) { - value = frame->popObject(); + value = frame->pop(ir::Type::object()); + } else if (instruction == fastore) { + value = frame->pop(ir::Type::f4()); } else { - value = frame->popInt(); + value = frame->pop(ir::Type::i4()); } - Compiler::Operand* index = frame->popInt(); - Compiler::Operand* array = frame->popObject(); + ir::Value* index = frame->pop(ir::Type::i4()); + ir::Value* array = frame->pop(ir::Type::object()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); @@ -4175,82 +4055,79 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, switch (instruction) { case aastore: { - c->call - (c->constant(getThunk(t, setMaybeNullThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 4, c->register_(t->arch->thread()), array, - c->binaryOp(lir::Add, - 4, c->constant(TargetArrayBody, Compiler::IntegerType), - c->binaryOp(lir::ShiftLeft, - 4, c->constant(log(TargetBytesPerWord), Compiler::IntegerType), - index)), - value); + c->call(c->constant(getThunk(t, setMaybeNullThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 4, + c->threadRegister(), + array, + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(TargetArrayBody, ir::Type::i4()), + c->binaryOp(lir::ShiftLeft, + ir::Type::i4(), + c->constant(log(TargetBytesPerWord), + ir::Type::i4()), + index)), + value); } break; case fastore: - c->store - (TargetBytesPerWord, value, 4, c->memory - (array, Compiler::FloatType, TargetArrayBody, index, 4)); + c->store(value, + c->memory(array, ir::Type::f4(), TargetArrayBody, index)); break; case iastore: - c->store - (TargetBytesPerWord, value, 4, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 4)); + c->store(value, + c->memory(array, ir::Type::i4(), TargetArrayBody, index)); break; case bastore: - c->store - (TargetBytesPerWord, value, 1, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 1)); + c->store(value, + c->memory(array, ir::Type::i1(), TargetArrayBody, index)); break; case castore: case sastore: - c->store - (TargetBytesPerWord, value, 2, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 2)); + c->store(value, + c->memory(array, ir::Type::i2(), TargetArrayBody, index)); break; case dastore: - c->store - (8, value, 8, c->memory - (array, Compiler::FloatType, TargetArrayBody, index, 8)); + c->store(value, + c->memory(array, ir::Type::f8(), TargetArrayBody, index)); break; case lastore: - c->store - (8, value, 8, c->memory - (array, Compiler::IntegerType, TargetArrayBody, index, 8)); + c->store(value, + c->memory(array, ir::Type::i8(), TargetArrayBody, index)); break; } } break; case aconst_null: - frame->pushObject(c->constant(0, Compiler::ObjectType)); + frame->push(ir::Type::object(), c->constant(0, ir::Type::object())); break; case aload: - frame->loadObject(codeBody(t, code, ip++)); + frame->load(ir::Type::object(), codeBody(t, code, ip++)); break; case aload_0: - frame->loadObject(0); + frame->load(ir::Type::object(), 0); break; case aload_1: - frame->loadObject(1); + frame->load(ir::Type::object(), 1); break; case aload_2: - frame->loadObject(2); + frame->load(ir::Type::object(), 2); break; case aload_3: - frame->loadObject(3); + frame->load(ir::Type::object(), 3); break; case anewarray: { @@ -4263,7 +4140,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, object class_ = resolveClassInPool(t, context->method, index - 1, false); - Compiler::Operand* length = frame->popInt(); + ir::Value* length = frame->pop(ir::Type::i4()); object argument; Thunk thunk; @@ -4275,70 +4152,68 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, thunk = makeBlankObjectArrayFromReferenceThunk; } - frame->pushObject - (c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 3, c->register_(t->arch->thread()), frame->append(argument), - length)); + frame->push(ir::Type::object(), + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 3, + c->threadRegister(), + frame->append(argument), + length)); } break; case areturn: { handleExit(t, frame); - c->return_(TargetBytesPerWord, frame->popObject()); + c->return_(frame->pop(ir::Type::object())); } goto next; case arraylength: { - frame->pushInt - (c->load - (TargetBytesPerWord, TargetBytesPerWord, - c->memory - (frame->popObject(), Compiler::IntegerType, - TargetArrayLength, 0, 1), - TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(frame->pop(ir::Type::object()), + ir::Type::iptr(), + TargetArrayLength), + ir::Type::i4())); } break; case astore: - frame->storeObjectOrAddress(codeBody(t, code, ip++)); + frame->store(ir::Type::object(), codeBody(t, code, ip++)); break; case astore_0: - frame->storeObjectOrAddress(0); + frame->store(ir::Type::object(), 0); break; case astore_1: - frame->storeObjectOrAddress(1); + frame->store(ir::Type::object(), 1); break; case astore_2: - frame->storeObjectOrAddress(2); + frame->store(ir::Type::object(), 2); break; case astore_3: - frame->storeObjectOrAddress(3); + frame->store(ir::Type::object(), 3); break; case athrow: { - Compiler::Operand* target = frame->popObject(); - c->call - (c->constant(getThunk(t, throw_Thunk), Compiler::AddressType), - Compiler::NoReturn, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 2, c->register_(t->arch->thread()), target); + ir::Value* target = frame->pop(ir::Type::object()); + c->call(c->constant(getThunk(t, throw_Thunk), ir::Type::iptr()), + Compiler::NoReturn, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + target); c->nullaryOp(lir::Trap); } goto next; case bipush: - frame->pushInt - (c->constant - (static_cast(codeBody(t, code, ip++)), - Compiler::IntegerType)); + frame->push(ir::Type::i4(), + c->constant(static_cast(codeBody(t, code, ip++)), + ir::Type::i4())); break; case checkcast: { @@ -4361,28 +4236,31 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, thunk = checkCastFromReferenceThunk; } - Compiler::Operand* instance = c->peek(1, 0); + ir::Value* instance = c->peek(1, 0); - c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 3, c->register_(t->arch->thread()), frame->append(argument), - instance); + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 3, + c->threadRegister(), + frame->append(argument), + instance); } break; case d2f: { - frame->pushInt(c->f2f(8, 4, frame->popLong())); + frame->push(ir::Type::f4(), + c->f2f(ir::Type::f4(), frame->popLarge(ir::Type::f8()))); } break; case d2i: { - frame->pushInt(c->f2i(8, 4, frame->popLong())); + frame->push(ir::Type::i4(), + c->f2i(ir::Type::i4(), frame->popLarge(ir::Type::f8()))); } break; case d2l: { - frame->pushLong(c->f2i(8, 8, frame->popLong())); + frame->pushLarge(ir::Type::i8(), + c->f2i(ir::Type::i8(), frame->popLarge(ir::Type::f8()))); } break; case dadd: @@ -4390,56 +4268,71 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case dmul: case ddiv: case vm::drem: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); - frame->pushLong(c->binaryOp(toCompilerBinaryOp(t, instruction), 8, a, b)); + frame->pushLarge( + ir::Type::f8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::f8(), a, b)); } break; case dcmpg: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); - if (floatBranch(t, frame, code, ip, 8, false, a, b, &newIp)) { + if (floatBranch(t, frame, code, ip, false, a, b, &newIp)) { goto branch; } else { - frame->pushInt - (c->call - (c->constant - (getThunk(t, compareDoublesGThunk), Compiler::AddressType), - 0, 0, 4, Compiler::IntegerType, 4, - static_cast(0), a, - static_cast(0), b)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, compareDoublesGThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + 4, + static_cast(0), + a, + static_cast(0), + b)); } } break; case dcmpl: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::f8()); + ir::Value* b = frame->popLarge(ir::Type::f8()); - if (floatBranch(t, frame, code, ip, 8, true, a, b, &newIp)) { + if (floatBranch(t, frame, code, ip, true, a, b, &newIp)) { goto branch; } else { - frame->pushInt - (c->call - (c->constant - (getThunk(t, compareDoublesLThunk), Compiler::AddressType), - 0, 0, 4, Compiler::IntegerType, 4, - static_cast(0), a, - static_cast(0), b)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, compareDoublesLThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + 4, + static_cast(0), + a, + static_cast(0), + b)); } } break; case dconst_0: - frame->pushLong(c->constant(doubleToBits(0.0), Compiler::FloatType)); + frame->pushLarge(ir::Type::f8(), + c->constant(doubleToBits(0.0), ir::Type::f8())); break; - + case dconst_1: - frame->pushLong(c->constant(doubleToBits(1.0), Compiler::FloatType)); + frame->pushLarge(ir::Type::f8(), + c->constant(doubleToBits(1.0), ir::Type::f8())); break; case dneg: { - frame->pushLong(c->unaryOp(lir::FloatNegate, 8, frame->popLong())); + frame->pushLarge( + ir::Type::f8(), + c->unaryOp(lir::FloatNegate, frame->popLarge(ir::Type::f8()))); } break; case dup: @@ -4467,15 +4360,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, break; case f2d: { - frame->pushLong(c->f2f(4, 8, frame->popInt())); + frame->pushLarge(ir::Type::f8(), + c->f2f(ir::Type::f8(), frame->pop(ir::Type::f4()))); } break; case f2i: { - frame->pushInt(c->f2i(4, 4, frame->popInt())); + frame->push(ir::Type::i4(), + c->f2i(ir::Type::i4(), frame->pop(ir::Type::f4()))); } break; case f2l: { - frame->pushLong(c->f2i(4, 8, frame->popInt())); + frame->pushLarge(ir::Type::i8(), + c->f2i(ir::Type::i8(), frame->pop(ir::Type::f4()))); } break; case fadd: @@ -4483,56 +4379,71 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case fmul: case fdiv: case frem: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); - frame->pushInt(c->binaryOp(toCompilerBinaryOp(t, instruction), 4, a, b)); + frame->push( + ir::Type::f4(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::f4(), a, b)); } break; case fcmpg: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); - if (floatBranch(t, frame, code, ip, 4, false, a, b, &newIp)) { + if (floatBranch(t, frame, code, ip, false, a, b, &newIp)) { goto branch; } else { - frame->pushInt - (c->call - (c->constant - (getThunk(t, compareFloatsGThunk), Compiler::AddressType), - 0, 0, 4, Compiler::IntegerType, 2, a, b)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, compareFloatsGThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + 2, + a, + b)); } } break; case fcmpl: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = frame->pop(ir::Type::f4()); + ir::Value* b = frame->pop(ir::Type::f4()); - if (floatBranch(t, frame, code, ip, 4, true, a, b, &newIp)) { + if (floatBranch(t, frame, code, ip, true, a, b, &newIp)) { goto branch; } else { - frame->pushInt - (c->call - (c->constant - (getThunk(t, compareFloatsLThunk), Compiler::AddressType), - 0, 0, 4, Compiler::IntegerType, 2, a, b)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, compareFloatsLThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + 2, + a, + b)); } } break; case fconst_0: - frame->pushInt(c->constant(floatToBits(0.0), Compiler::FloatType)); + frame->push(ir::Type::f4(), + c->constant(floatToBits(0.0), ir::Type::f4())); break; case fconst_1: - frame->pushInt(c->constant(floatToBits(1.0), Compiler::FloatType)); + frame->push(ir::Type::f4(), + c->constant(floatToBits(1.0), ir::Type::f4())); break; case fconst_2: - frame->pushInt(c->constant(floatToBits(2.0), Compiler::FloatType)); + frame->push(ir::Type::f4(), + c->constant(floatToBits(2.0), ir::Type::f4())); break; case fneg: { - frame->pushInt(c->unaryOp(lir::FloatNegate, 4, frame->popInt())); + frame->push(ir::Type::f4(), + c->unaryOp(lir::FloatNegate, frame->pop(ir::Type::f4()))); } break; case getfield: @@ -4554,16 +4465,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, { PROTECT(t, field); - c->call - (c->constant - (getThunk(t, acquireMonitorForObjectThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), - frame->append(field)); + c->call(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(field)); } - Compiler::Operand* table; + ir::Value* table; if (instruction == getstatic) { checkField(t, field, true); @@ -4571,22 +4483,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, PROTECT(t, field); if (classNeedsInit(t, fieldClass(t, field))) { - c->call - (c->constant - (getThunk(t, tryInitClassThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 2, c->register_(t->arch->thread()), - frame->append(fieldClass(t, field))); + c->call( + c->constant(getThunk(t, tryInitClassThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(fieldClass(t, field))); } table = frame->append(classStaticTable(t, fieldClass(t, field))); } else { checkField(t, field, false); - table = frame->popObject(); + table = frame->pop(ir::Type::object()); if (inTryBlock(t, code, ip - 3)) { c->saveLocals(); @@ -4597,68 +4508,75 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, switch (fieldCode(t, field)) { case ByteField: case BooleanField: - frame->pushInt - (c->load - (1, 1, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::i1(), + targetFieldOffset(context, field)), + ir::Type::i4())); break; case CharField: - frame->pushInt - (c->loadz - (2, 2, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->load(ir::ZeroExtend, + c->memory(table, + ir::Type::i2(), + targetFieldOffset(context, field)), + ir::Type::i4())); break; case ShortField: - frame->pushInt - (c->load - (2, 2, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::i2(), + targetFieldOffset(context, field)), + ir::Type::i4())); break; case FloatField: - frame->pushInt - (c->load - (4, 4, c->memory - (table, Compiler::FloatType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::f4(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::f4(), + targetFieldOffset(context, field)), + ir::Type::f4())); break; case IntField: - frame->pushInt - (c->load - (4, 4, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::i4(), + targetFieldOffset(context, field)), + ir::Type::i4())); break; case DoubleField: - frame->pushLong - (c->load - (8, 8, c->memory - (table, Compiler::FloatType, targetFieldOffset - (context, field), 0, 1), 8)); + frame->pushLarge(ir::Type::f8(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::f8(), + targetFieldOffset(context, field)), + ir::Type::f8())); break; case LongField: - frame->pushLong - (c->load - (8, 8, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1), 8)); + frame->pushLarge(ir::Type::i8(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::i8(), + targetFieldOffset(context, field)), + ir::Type::i8())); break; case ObjectField: - frame->pushObject - (c->load - (TargetBytesPerWord, TargetBytesPerWord, - c->memory - (table, Compiler::ObjectType, targetFieldOffset - (context, field), 0, 1), TargetBytesPerWord)); + frame->push(ir::Type::object(), + c->load(ir::SignExtend, + c->memory(table, + ir::Type::object(), + targetFieldOffset(context, field)), + ir::Type::object())); break; default: @@ -4670,13 +4588,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, and (fieldCode(t, field) == DoubleField or fieldCode(t, field) == LongField)) { - c->call - (c->constant - (getThunk(t, releaseMonitorForObjectThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), - frame->append(field)); + c->call(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(field)); } else { c->nullaryOp(lir::LoadBarrier); } @@ -4687,30 +4606,35 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, object pair = makePair(t, context->method, reference); - unsigned rSize = resultSize(t, fieldCode); - Compiler::OperandType rType = operandTypeForFieldCode(t, fieldCode); + ir::Type rType = operandTypeForFieldCode(t, fieldCode); - Compiler::Operand* result; + ir::Value* result; if (instruction == getstatic) { - result = c->call - (c->constant - (getThunk(t, getStaticFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 2, - c->register_(t->arch->thread()), frame->append(pair)); + result = c->call( + c->constant(getThunk(t, getStaticFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 2, + c->threadRegister(), + frame->append(pair)); } else { - Compiler::Operand* instance = frame->popObject(); + ir::Value* instance = frame->pop(ir::Type::object()); - result = c->call - (c->constant - (getThunk(t, getFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 3, - c->register_(t->arch->thread()), frame->append(pair), - instance); + result = c->call( + c->constant(getThunk(t, getFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 3, + c->threadRegister(), + frame->append(pair), + instance); } - pushReturnValue(t, frame, fieldCode, result); + frame->pushReturnValue(fieldCode, result); } } break; @@ -4723,7 +4647,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, compileSafePoint(t, c, frame); } - c->jmp(frame->machineIp(newIp)); + c->jmp(frame->machineIpValue(newIp)); ip = newIp; } break; @@ -4736,35 +4660,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, compileSafePoint(t, c, frame); } - c->jmp(frame->machineIp(newIp)); + c->jmp(frame->machineIpValue(newIp)); ip = newIp; } break; case i2b: { - frame->pushInt - (c->load(TargetBytesPerWord, 1, frame->popInt(), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::SignExtend, + ir::Type::i4(), + ir::Type::i1(), + frame->pop(ir::Type::i4()))); } break; case i2c: { - frame->pushInt - (c->loadz(TargetBytesPerWord, 2, frame->popInt(), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::ZeroExtend, + ir::Type::i4(), + ir::Type::i2(), + frame->pop(ir::Type::i4()))); } break; case i2d: { - frame->pushLong(c->i2f(4, 8, frame->popInt())); + frame->pushLarge(ir::Type::f8(), + c->i2f(ir::Type::f8(), frame->pop(ir::Type::i4()))); } break; case i2f: { - frame->pushInt(c->i2f(4, 4, frame->popInt())); + frame->push(ir::Type::f4(), + c->i2f(ir::Type::f4(), frame->pop(ir::Type::i4()))); } break; case i2l: - frame->pushLong(c->load(TargetBytesPerWord, 4, frame->popInt(), 8)); + frame->pushLarge(ir::Type::i8(), + c->truncateThenExtend(ir::SignExtend, + ir::Type::i8(), + ir::Type::i4(), + frame->pop(ir::Type::i4()))); break; case i2s: { - frame->pushInt - (c->load(TargetBytesPerWord, 2, frame->popInt(), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->truncateThenExtend(ir::SignExtend, + ir::Type::i4(), + ir::Type::i2(), + frame->pop(ir::Type::i4()))); } break; case iadd: @@ -4776,49 +4715,53 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case isub: case ixor: case imul: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); - frame->pushInt(c->binaryOp(toCompilerBinaryOp(t, instruction), 4, a, b)); + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + frame->push( + ir::Type::i4(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i4(), a, b)); } break; case iconst_m1: - frame->pushInt(c->constant(-1, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(-1, ir::Type::i4())); break; case iconst_0: - frame->pushInt(c->constant(0, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(0, ir::Type::i4())); break; case iconst_1: - frame->pushInt(c->constant(1, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(1, ir::Type::i4())); break; case iconst_2: - frame->pushInt(c->constant(2, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(2, ir::Type::i4())); break; case iconst_3: - frame->pushInt(c->constant(3, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(3, ir::Type::i4())); break; case iconst_4: - frame->pushInt(c->constant(4, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(4, ir::Type::i4())); break; case iconst_5: - frame->pushInt(c->constant(5, Compiler::IntegerType)); + frame->push(ir::Type::i4(), c->constant(5, ir::Type::i4())); break; case idiv: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); frame->trace(0, 0); } - frame->pushInt(c->binaryOp(lir::Divide, 4, a, b)); + frame->push(ir::Type::i4(), + c->binaryOp(lir::Divide, ir::Type::i4(), a, b)); } break; case if_acmpeq: @@ -4830,12 +4773,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if(newIp <= ip) { compileSafePoint(t, c, frame); } - - Compiler::Operand* a = frame->popObject(); - Compiler::Operand* b = frame->popObject(); - Compiler::Operand* target = frame->machineIp(newIp); - c->condJump(toCompilerJumpOp(t, instruction), TargetBytesPerWord, a, b, target); + ir::Value* a = frame->pop(ir::Type::object()); + ir::Value* b = frame->pop(ir::Type::object()); + ir::Value* target = frame->machineIpValue(newIp); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); } goto branch; case if_icmpeq: @@ -4851,12 +4794,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if(newIp <= ip) { compileSafePoint(t, c, frame); } - - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); - Compiler::Operand* target = frame->machineIp(newIp); - c->condJump(toCompilerJumpOp(t, instruction), 4, a, b, target); + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); + ir::Value* target = frame->machineIpValue(newIp); + + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); } goto branch; case ifeq: @@ -4869,16 +4812,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, newIp = (ip - 3) + offset; assert(t, newIp < codeLength(t, code)); - Compiler::Operand* target = frame->machineIp(newIp); + ir::Value* target = frame->machineIpValue(newIp); if(newIp <= ip) { compileSafePoint(t, c, frame); } - Compiler::Operand* a = c->constant(0, Compiler::IntegerType); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = c->constant(0, ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); - c->condJump(toCompilerJumpOp(t, instruction), 4, a, b, target); + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); } goto branch; case ifnull: @@ -4891,52 +4834,65 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, compileSafePoint(t, c, frame); } - Compiler::Operand* a = c->constant(0, Compiler::ObjectType); - Compiler::Operand* b = frame->popObject(); - Compiler::Operand* target = frame->machineIp(newIp); + ir::Value* a = c->constant(0, ir::Type::object()); + ir::Value* b = frame->pop(ir::Type::object()); + ir::Value* target = frame->machineIpValue(newIp); - c->condJump(toCompilerJumpOp(t, instruction), TargetBytesPerWord, a, b, target); + c->condJump(toCompilerJumpOp(t, instruction), a, b, target); } goto branch; case iinc: { uint8_t index = codeBody(t, code, ip++); int8_t count = codeBody(t, code, ip++); - storeLocal - (context, 1, - c->binaryOp(lir::Add, - 4, c->constant(count, Compiler::IntegerType), - loadLocal(context, 1, index)), - index); + storeLocal(context, + 1, + ir::Type::i4(), + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(count, ir::Type::i4()), + loadLocal(context, 1, ir::Type::i4(), index)), + index); } break; case iload: + frame->load(ir::Type::i4(), codeBody(t, code, ip++)); + break; case fload: - frame->loadInt(codeBody(t, code, ip++)); + frame->load(ir::Type::f4(), codeBody(t, code, ip++)); break; case iload_0: + frame->load(ir::Type::i4(), 0); + break; case fload_0: - frame->loadInt(0); + frame->load(ir::Type::f4(), 0); break; case iload_1: + frame->load(ir::Type::i4(), 1); + break; case fload_1: - frame->loadInt(1); + frame->load(ir::Type::f4(), 1); break; case iload_2: + frame->load(ir::Type::i4(), 2); + break; case fload_2: - frame->loadInt(2); + frame->load(ir::Type::f4(), 2); break; case iload_3: + frame->load(ir::Type::i4(), 3); + break; case fload_3: - frame->loadInt(3); + frame->load(ir::Type::f4(), 3); break; case ineg: { - frame->pushInt(c->unaryOp(lir::Negate, 4, frame->popInt())); + frame->push(ir::Type::i4(), + c->unaryOp(lir::Negate, frame->pop(ir::Type::i4()))); } break; case instanceof: { @@ -4949,7 +4905,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, object class_ = resolveClassInPool(t, context->method, index - 1, false); - Compiler::Operand* instance = frame->popObject(); + ir::Value* instance = frame->pop(ir::Type::object()); object argument; Thunk thunk; @@ -4961,12 +4917,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, thunk = instanceOfFromReferenceThunk; } - frame->pushInt - (c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, frame->trace(0, 0), 4, Compiler::IntegerType, - 3, c->register_(t->arch->thread()), frame->append(argument), - instance)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::i4(), + 3, + c->threadRegister(), + frame->append(argument), + instance)); } break; case invokeinterface: { @@ -5007,25 +4966,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, unsigned rSize = resultSize(t, returnCode); - Compiler::Operand* result = c->stackCall - (c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, + ir::Value* result = c->stackCall( + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + 3, + c->threadRegister(), + frame->append(argument), + c->peek(1, parameterFootprint - 1)), + tailCall ? Compiler::TailJump : 0, frame->trace(0, 0), - TargetBytesPerWord, - Compiler::AddressType, - 3, c->register_(t->arch->thread()), frame->append(argument), - c->peek(1, parameterFootprint - 1)), - tailCall ? Compiler::TailJump : 0, - frame->trace(0, 0), - rSize, - operandTypeForFieldCode(t, returnCode), - parameterFootprint); + operandTypeForFieldCode(t, returnCode), + frame->peekMethodArguments(parameterFootprint)); - frame->pop(parameterFootprint); + frame->popFootprint(parameterFootprint); if (rSize) { - pushReturnValue(t, frame, returnCode, result); + frame->pushReturnValue(returnCode, result); } } break; @@ -5114,34 +5072,25 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, unsigned offset = TargetClassVtable + (methodOffset(t, target) * TargetBytesPerWord); - Compiler::Operand* instance = c->peek(1, parameterFootprint - 1); + ir::Value* instance = c->peek(1, parameterFootprint - 1); - unsigned rSize = resultSize(t, methodReturnCode(t, target)); - - Compiler::Operand* result = c->stackCall - (c->memory - (c->binaryOp(lir::And, - TargetBytesPerWord, c->constant - (TargetPointerMask, Compiler::IntegerType), - c->memory(instance, Compiler::ObjectType, 0, 0, 1)), - Compiler::ObjectType, offset, 0, 1), - tailCall ? Compiler::TailJump : 0, - frame->trace(0, 0), - rSize, - operandTypeForFieldCode(t, methodReturnCode(t, target)), - parameterFootprint); - - frame->pop(parameterFootprint); - - if (rSize) { - pushReturnValue(t, frame, methodReturnCode(t, target), result); - } + frame->stackCall( + c->memory(c->binaryOp( + lir::And, + ir::Type::iptr(), + c->constant(TargetPointerMask, ir::Type::iptr()), + c->memory(instance, ir::Type::object())), + ir::Type::object(), + offset), + target, + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0)); } else { // OpenJDK generates invokevirtual calls to private methods // (e.g. readObject and writeObject for serialization), so // we must handle such cases here. - compileDirectInvoke(t, frame, target, tailCall); + compileDirectInvoke(t, frame, target, tailCall); } } } else { @@ -5149,63 +5098,83 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, object pair = makePair(t, context->method, reference); - compileReferenceInvoke - (t, frame, c->call - (c->constant(getThunk(t, findVirtualMethodFromReferenceThunk), - Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::AddressType, - 3, c->register_(t->arch->thread()), frame->append(pair), - c->peek(1, methodReferenceParameterFootprint - (t, reference, false) - 1)), - reference, false, isReferenceTailCall - (t, code, ip, context->method, reference)); + compileReferenceInvoke( + frame, + c->call( + c->constant(getThunk(t, findVirtualMethodFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::iptr(), + 3, + c->threadRegister(), + frame->append(pair), + c->peek(1, + methodReferenceParameterFootprint(t, reference, false) + - 1)), + reference, + false, + isReferenceTailCall(t, code, ip, context->method, reference)); } } break; case irem: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popInt(); + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->pop(ir::Type::i4()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); frame->trace(0, 0); } - frame->pushInt(c->binaryOp(lir::Remainder, 4, a, b)); + frame->push(ir::Type::i4(), + c->binaryOp(lir::Remainder, ir::Type::i4(), a, b)); } break; - case ireturn: + case ireturn: { + handleExit(t, frame); + c->return_(frame->pop(ir::Type::i4())); + } + goto next; + case freturn: { handleExit(t, frame); - c->return_(4, frame->popInt()); + c->return_(frame->pop(ir::Type::f4())); } goto next; case istore: + frame->store(ir::Type::i4(), codeBody(t, code, ip++)); + break; case fstore: - frame->storeInt(codeBody(t, code, ip++)); + frame->store(ir::Type::f4(), codeBody(t, code, ip++)); break; case istore_0: + frame->store(ir::Type::i4(), 0); + break; case fstore_0: - frame->storeInt(0); + frame->store(ir::Type::f4(), 0); break; case istore_1: + frame->store(ir::Type::i4(), 1); + break; case fstore_1: - frame->storeInt(1); + frame->store(ir::Type::f4(), 1); break; case istore_2: + frame->store(ir::Type::i4(), 2); + break; case fstore_2: - frame->storeInt(2); + frame->store(ir::Type::f4(), 2); break; case istore_3: + frame->store(ir::Type::i4(), 3); + break; case fstore_3: - frame->storeInt(3); + frame->store(ir::Type::f4(), 3); break; case jsr: @@ -5224,26 +5193,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, assert(t, newIp < codeLength(t, code)); - unsigned start = frame->startSubroutine(newIp, c->machineIp(ip)); + frame->startSubroutine(newIp, ip); - c->jmp(frame->machineIp(newIp)); + c->jmp(frame->machineIpValue(newIp)); - stack.pushValue(start); - stack.pushValue(ip); - stack.pushValue(Unsubroutine); ip = newIp; - } goto start; + } break; case l2d: { - frame->pushLong(c->i2f(8, 8, frame->popLong())); + frame->pushLarge(ir::Type::f8(), + c->i2f(ir::Type::f8(), frame->popLarge(ir::Type::i8()))); } break; case l2f: { - frame->pushInt(c->i2f(8, 4, frame->popLong())); + frame->push(ir::Type::f4(), + c->i2f(ir::Type::f4(), frame->popLarge(ir::Type::i8()))); } break; case l2i: - frame->pushInt(c->load(8, 8, frame->popLong(), TargetBytesPerWord)); + frame->push(ir::Type::i4(), + c->truncate(ir::Type::i4(), frame->popLarge(ir::Type::i8()))); break; case ladd: @@ -5252,34 +5221,41 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case lsub: case lxor: case lmul: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->binaryOp(toCompilerBinaryOp(t, instruction), 8, a, b)); + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + frame->pushLarge( + ir::Type::i8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i8(), a, b)); } break; case lcmp: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); - if (integerBranch(t, frame, code, ip, 8, a, b, &newIp)) { + if (integerBranch(t, frame, code, ip, a, b, &newIp)) { goto branch; } else { - frame->pushInt - (c->call - (c->constant - (getThunk(t, compareLongsThunk), Compiler::AddressType), - 0, 0, 4, Compiler::IntegerType, 4, - static_cast(0), a, - static_cast(0), b)); + frame->push(ir::Type::i4(), + c->call(c->constant(getThunk(t, compareLongsThunk), + ir::Type::iptr()), + 0, + 0, + ir::Type::i4(), + 4, + static_cast(0), + a, + static_cast(0), + b)); } } break; case lconst_0: - frame->pushLong(c->constant(0, Compiler::IntegerType)); + frame->pushLarge(ir::Type::i8(), c->constant(0, ir::Type::i8())); break; case lconst_1: - frame->pushLong(c->constant(1, Compiler::IntegerType)); + frame->pushLarge(ir::Type::i8(), c->constant(1, ir::Type::i8())); break; case ldc: @@ -5297,7 +5273,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if (singletonIsObject(t, pool, index - 1)) { object v = singletonObject(t, pool, index - 1); - loadMemoryBarrier(); + loadMemoryBarrier(); if (objectClass(t, v) == type(t, Machine::ReferenceType)) { object reference = v; @@ -5306,41 +5282,41 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, v = resolveClassInPool(t, context->method, index - 1, false); if (UNLIKELY(v == 0)) { - frame->pushObject - (c->call - (c->constant - (getThunk(t, getJClassFromReferenceThunk), - Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 2, c->register_(t->arch->thread()), - frame->append(makePair(t, context->method, reference)))); + frame->push( + ir::Type::object(), + c->call( + c->constant(getThunk(t, getJClassFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 2, + c->threadRegister(), + frame->append(makePair(t, context->method, reference)))); } } if (v) { if (objectClass(t, v) == type(t, Machine::ClassType)) { - frame->pushObject - (c->call - (c->constant - (getThunk(t, getJClass64Thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 2, c->register_(t->arch->thread()), frame->append(v))); + frame->push(ir::Type::object(), + c->call(c->constant(getThunk(t, getJClass64Thunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 2, + c->threadRegister(), + frame->append(v))); } else { - frame->pushObject(frame->append(v)); + frame->push(ir::Type::object(), frame->append(v)); } } } else { - frame->pushInt - (c->constant - (singletonValue(t, pool, index - 1), - singletonBit(t, pool, poolSize(t, pool), index - 1) - ? Compiler::FloatType : Compiler::IntegerType)); + ir::Type type = singletonBit(t, pool, poolSize(t, pool), index - 1) + ? ir::Type::f4() + : ir::Type::i4(); + frame->push(type, + c->constant(singletonValue(t, pool, index - 1), type)); } } break; @@ -5351,51 +5327,64 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, uint64_t v; memcpy(&v, &singletonValue(t, pool, index - 1), 8); - frame->pushLong - (c->constant - (v, singletonBit(t, pool, poolSize(t, pool), index - 1) - ? Compiler::FloatType : Compiler::IntegerType)); + ir::Type type = singletonBit(t, pool, poolSize(t, pool), index - 1) + ? ir::Type::f8() + : ir::Type::i8(); + frame->pushLarge(type, c->constant(v, type)); } break; case ldiv_: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); frame->trace(0, 0); } - frame->pushLong(c->binaryOp(lir::Divide, 8, a, b)); + frame->pushLarge(ir::Type::i8(), + c->binaryOp(lir::Divide, ir::Type::i8(), a, b)); } break; case lload: + frame->loadLarge(ir::Type::i8(), codeBody(t, code, ip++)); + break; case dload: - frame->loadLong(codeBody(t, code, ip++)); + frame->loadLarge(ir::Type::f8(), codeBody(t, code, ip++)); break; case lload_0: + frame->loadLarge(ir::Type::i8(), 0); + break; case dload_0: - frame->loadLong(0); + frame->loadLarge(ir::Type::f8(), 0); break; case lload_1: + frame->loadLarge(ir::Type::i8(), 1); + break; case dload_1: - frame->loadLong(1); + frame->loadLarge(ir::Type::f8(), 1); break; case lload_2: + frame->loadLarge(ir::Type::i8(), 2); + break; case dload_2: - frame->loadLong(2); + frame->loadLarge(ir::Type::f8(), 2); break; case lload_3: + frame->loadLarge(ir::Type::i8(), 3); + break; case dload_3: - frame->loadLong(3); + frame->loadLarge(ir::Type::f8(), 3); break; case lneg: - frame->pushLong(c->unaryOp(lir::Negate, 8, frame->popLong())); + frame->pushLarge( + ir::Type::i8(), + c->unaryOp(lir::Negate, frame->popLarge(ir::Type::i8()))); break; case lookupswitch: { @@ -5403,16 +5392,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, ip = (ip + 3) & ~3; // pad to four byte boundary - Compiler::Operand* key = frame->popInt(); - + ir::Value* key = frame->pop(ir::Type::i4()); + uint32_t defaultIp = base + codeReadInt32(t, code, ip); assert(t, defaultIp < codeLength(t, code)); int32_t pairCount = codeReadInt32(t, code, ip); if (pairCount) { - Compiler::Operand* default_ = frame->addressOperand - (frame->addressPromise(c->machineIp(defaultIp))); + ir::Value* default_ = frame->addressOperand( + frame->addressPromise(frame->machineIp(defaultIp))); avian::codegen::Promise* start = 0; uint32_t* ipTable = static_cast @@ -5429,23 +5418,29 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if (i == 0) { start = p; } - c->poolAppendPromise - (frame->addressPromise(c->machineIp(newIp))); + c->poolAppendPromise(frame->addressPromise(frame->machineIp(newIp))); } assert(t, start); - Compiler::Operand* address = c->call - (c->constant(getThunk(t, lookUpAddressThunk), Compiler::AddressType), - 0, 0, TargetBytesPerWord, Compiler::AddressType, - 4, key, frame->absoluteAddressOperand(start), - c->constant(pairCount, Compiler::IntegerType), default_); + ir::Value* address = c->call( + c->constant(getThunk(t, lookUpAddressThunk), ir::Type::iptr()), + 0, + 0, + ir::Type::iptr(), + 4, + key, + frame->absoluteAddressOperand(start), + c->constant(pairCount, ir::Type::i4()), + default_); - c->jmp - (context->bootContext ? c->binaryOp(lir::Add, - TargetBytesPerWord, c->memory - (c->register_(t->arch->thread()), Compiler::AddressType, - TARGET_THREAD_CODEIMAGE), address) - : address); + c->jmp(context->bootContext + ? c->binaryOp(lir::Add, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_CODEIMAGE), + address) + : address); new (stack.push(sizeof(SwitchState))) SwitchState (c->saveState(), pairCount, defaultIp, 0, 0, 0, 0); @@ -5453,78 +5448,103 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, goto switchloop; } else { // a switch statement with no cases, apparently - c->jmp(frame->machineIp(defaultIp)); + c->jmp(frame->machineIpValue(defaultIp)); ip = defaultIp; } } break; case lrem: { - Compiler::Operand* a = frame->popLong(); - Compiler::Operand* b = frame->popLong(); + ir::Value* a = frame->popLarge(ir::Type::i8()); + ir::Value* b = frame->popLarge(ir::Type::i8()); if (inTryBlock(t, code, ip - 1)) { c->saveLocals(); frame->trace(0, 0); } - frame->pushLong(c->binaryOp(lir::Remainder, 8, a, b)); + frame->pushLarge(ir::Type::i8(), + c->binaryOp(lir::Remainder, ir::Type::i8(), a, b)); } break; - case lreturn: + case lreturn: { + handleExit(t, frame); + c->return_(frame->popLarge(ir::Type::i8())); + } + goto next; + case dreturn: { handleExit(t, frame); - c->return_(8, frame->popLong()); + c->return_(frame->popLarge(ir::Type::f8())); } goto next; case lshl: case lshr: case lushr: { - Compiler::Operand* a = frame->popInt(); - Compiler::Operand* b = frame->popLong(); - frame->pushLong(c->binaryOp(toCompilerBinaryOp(t, instruction), 8, a, b)); + ir::Value* a = frame->pop(ir::Type::i4()); + ir::Value* b = frame->popLarge(ir::Type::i8()); + frame->pushLarge( + ir::Type::i8(), + c->binaryOp( + toCompilerBinaryOp(t, instruction), ir::Type::i8(), a, b)); } break; case lstore: + frame->storeLarge(ir::Type::i8(), codeBody(t, code, ip++)); + break; case dstore: - frame->storeLong(codeBody(t, code, ip++)); + frame->storeLarge(ir::Type::f8(), codeBody(t, code, ip++)); break; case lstore_0: + frame->storeLarge(ir::Type::i8(), 0); + break; case dstore_0: - frame->storeLong(0); + frame->storeLarge(ir::Type::f8(), 0); break; case lstore_1: + frame->storeLarge(ir::Type::i8(), 1); + break; case dstore_1: - frame->storeLong(1); + frame->storeLarge(ir::Type::f8(), 1); break; case lstore_2: + frame->storeLarge(ir::Type::i8(), 2); + break; case dstore_2: - frame->storeLong(2); + frame->storeLarge(ir::Type::f8(), 2); break; case lstore_3: + frame->storeLarge(ir::Type::i8(), 3); + break; case dstore_3: - frame->storeLong(3); + frame->storeLarge(ir::Type::f8(), 3); break; case monitorenter: { - Compiler::Operand* target = frame->popObject(); - c->call - (c->constant - (getThunk(t, acquireMonitorForObjectThunk), Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), target); + ir::Value* target = frame->pop(ir::Type::object()); + c->call(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + target); } break; case monitorexit: { - Compiler::Operand* target = frame->popObject(); - c->call - (c->constant - (getThunk(t, releaseMonitorForObjectThunk), Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), target); + ir::Value* target = frame->pop(ir::Type::object()); + c->call(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + target); } break; case multianewarray: { @@ -5553,19 +5573,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, (t, localSize(t, context->method) + c->topOfStack(), context->method) + t->arch->frameReturnAddressSize(); - Compiler::Operand* result = c->call - (c->constant - (getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 4, c->register_(t->arch->thread()), frame->append(argument), - c->constant(dimensions, Compiler::IntegerType), - c->constant(offset, Compiler::IntegerType)); + ir::Value* result + = c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 4, + c->threadRegister(), + frame->append(argument), + c->constant(dimensions, ir::Type::i4()), + c->constant(offset, ir::Type::i4())); - frame->pop(dimensions); - frame->pushObject(result); + frame->popFootprint(dimensions); + frame->push(ir::Type::object(), result); } break; case new_: { @@ -5592,40 +5612,41 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, thunk = makeNewFromReferenceThunk; } - frame->pushObject - (c->call - (c->constant(getThunk(t, thunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 2, c->register_(t->arch->thread()), frame->append(argument))); + frame->push(ir::Type::object(), + c->call(c->constant(getThunk(t, thunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 2, + c->threadRegister(), + frame->append(argument))); } break; case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* length = frame->popInt(); + ir::Value* length = frame->pop(ir::Type::i4()); - frame->pushObject - (c->call - (c->constant(getThunk(t, makeBlankArrayThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - TargetBytesPerWord, - Compiler::ObjectType, - 3, c->register_(t->arch->thread()), - c->constant(type, Compiler::IntegerType), length)); + frame->push(ir::Type::object(), + c->call(c->constant(getThunk(t, makeBlankArrayThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::object(), + 3, + c->threadRegister(), + c->constant(type, ir::Type::i4()), + length)); } break; case nop: break; case pop_: - frame->pop(1); + frame->popFootprint(1); break; case pop2: - frame->pop(2); + frame->popFootprint(2); break; case putfield: @@ -5650,15 +5671,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if (classNeedsInit(t, fieldClass(t, field))) { PROTECT(t, field); - c->call - (c->constant - (getThunk(t, tryInitClassThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 2, c->register_(t->arch->thread()), - frame->append(fieldClass(t, field))); + c->call( + c->constant(getThunk(t, tryInitClassThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(fieldClass(t, field))); } staticTable = classStaticTable(t, fieldClass(t, field)); @@ -5677,95 +5697,99 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, { PROTECT(t, field); - c->call - (c->constant - (getThunk(t, acquireMonitorForObjectThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), frame->append(field)); + c->call(c->constant(getThunk(t, acquireMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(field)); } else { c->nullaryOp(lir::StoreStoreBarrier); } } - Compiler::Operand* value = popField(t, frame, fieldCode); + ir::Value* value = popField(t, frame, fieldCode); - Compiler::Operand* table; + ir::Value* table; if (instruction == putstatic) { PROTECT(t, field); table = frame->append(staticTable); } else { - table = frame->popObject(); + table = frame->pop(ir::Type::object()); } switch (fieldCode) { case ByteField: case BooleanField: - c->store - (TargetBytesPerWord, value, 1, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::i1(), targetFieldOffset(context, field))); break; case CharField: case ShortField: - c->store - (TargetBytesPerWord, value, 2, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::i2(), targetFieldOffset(context, field))); break; - + case FloatField: - c->store - (TargetBytesPerWord, value, 4, c->memory - (table, Compiler::FloatType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::f4(), targetFieldOffset(context, field))); break; case IntField: - c->store - (TargetBytesPerWord, value, 4, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::i4(), targetFieldOffset(context, field))); break; case DoubleField: - c->store - (8, value, 8, c->memory - (table, Compiler::FloatType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::f8(), targetFieldOffset(context, field))); break; case LongField: - c->store - (8, value, 8, c->memory - (table, Compiler::IntegerType, targetFieldOffset - (context, field), 0, 1)); + c->store( + value, + c->memory( + table, ir::Type::i8(), targetFieldOffset(context, field))); break; case ObjectField: if (instruction == putfield) { - c->call - (c->constant - (getThunk(t, setMaybeNullThunk), Compiler::AddressType), - 0, - frame->trace(0, 0), - 0, - Compiler::VoidType, - 4, c->register_(t->arch->thread()), table, - c->constant(targetFieldOffset(context, field), - Compiler::IntegerType), - value); + c->call( + c->constant(getThunk(t, setMaybeNullThunk), ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 4, + c->threadRegister(), + table, + c->constant(targetFieldOffset(context, field), ir::Type::i4()), + value); } else { - c->call - (c->constant(getThunk(t, setThunk), Compiler::AddressType), - 0, 0, 0, Compiler::VoidType, - 4, c->register_(t->arch->thread()), table, - c->constant(targetFieldOffset(context, field), - Compiler::IntegerType), - value); + c->call( + c->constant(getThunk(t, setThunk), ir::Type::iptr()), + 0, + 0, + ir::Type::void_(), + 4, + c->threadRegister(), + table, + c->constant(targetFieldOffset(context, field), ir::Type::i4()), + value); } break; @@ -5776,12 +5800,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, if (TargetBytesPerWord == 4 and (fieldCode == DoubleField or fieldCode == LongField)) { - c->call - (c->constant - (getThunk(t, releaseMonitorForObjectThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), 0, Compiler::VoidType, 2, - c->register_(t->arch->thread()), frame->append(field)); + c->call(c->constant(getThunk(t, releaseMonitorForObjectThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + ir::Type::void_(), + 2, + c->threadRegister(), + frame->append(field)); } else { c->nullaryOp(lir::StoreLoadBarrier); } @@ -5790,9 +5816,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, int fieldCode = vm::fieldCode (t, byteArrayBody(t, referenceSpec(t, reference), 0)); - Compiler::Operand* value = popField(t, frame, fieldCode); - unsigned rSize = resultSize(t, fieldCode); - Compiler::OperandType rType = operandTypeForFieldCode(t, fieldCode); + ir::Value* value = popField(t, frame, fieldCode); + ir::Type rType = operandTypeForFieldCode(t, fieldCode); object pair = makePair(t, context->method, reference); @@ -5804,68 +5829,91 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case FloatField: case IntField: { if (instruction == putstatic) { - c->call - (c->constant - (getThunk(t, setStaticFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 3, - c->register_(t->arch->thread()), frame->append(pair), - value); + c->call( + c->constant(getThunk(t, setStaticFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 3, + c->threadRegister(), + frame->append(pair), + value); } else { - Compiler::Operand* instance = frame->popObject(); + ir::Value* instance = frame->pop(ir::Type::object()); - c->call - (c->constant - (getThunk(t, setFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 4, - c->register_(t->arch->thread()), frame->append(pair), - instance, value); + c->call(c->constant(getThunk(t, setFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 4, + c->threadRegister(), + frame->append(pair), + instance, + value); } } break; case DoubleField: case LongField: { if (instruction == putstatic) { - c->call - (c->constant - (getThunk(t, setStaticLongFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 4, - c->register_(t->arch->thread()), frame->append(pair), - static_cast(0), value); + c->call(c->constant( + getThunk(t, setStaticLongFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 4, + c->threadRegister(), + frame->append(pair), + static_cast(0), + value); } else { - Compiler::Operand* instance = frame->popObject(); + ir::Value* instance = frame->pop(ir::Type::object()); - c->call - (c->constant - (getThunk(t, setLongFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 5, - c->register_(t->arch->thread()), frame->append(pair), - instance, static_cast(0), value); + c->call( + c->constant(getThunk(t, setLongFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 5, + c->threadRegister(), + frame->append(pair), + instance, + static_cast(0), + value); } } break; case ObjectField: { if (instruction == putstatic) { - c->call - (c->constant - (getThunk(t, setStaticObjectFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 3, - c->register_(t->arch->thread()), frame->append(pair), - value); + c->call( + c->constant( + getThunk(t, setStaticObjectFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 3, + c->threadRegister(), + frame->append(pair), + value); } else { - Compiler::Operand* instance = frame->popObject(); + ir::Value* instance = frame->pop(ir::Type::object()); - c->call - (c->constant - (getThunk(t, setObjectFieldValueFromReferenceThunk), - Compiler::AddressType), - 0, frame->trace(0, 0), rSize, rType, 4, - c->register_(t->arch->thread()), frame->append(pair), - instance, value); + c->call( + c->constant(getThunk(t, setObjectFieldValueFromReferenceThunk), + ir::Type::iptr()), + 0, + frame->trace(0, 0), + rType, + 4, + c->threadRegister(), + frame->append(pair), + instance, + value); } } break; @@ -5876,8 +5924,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case ret: { unsigned index = codeBody(t, code, ip); - frame->returnFromSubroutine(index); - } goto next; + + unsigned returnAddress = frame->endSubroutine(index); + c->jmp(frame->machineIpValue(returnAddress)); + ip = returnAddress; + } break; case return_: if (needsReturnBarrier(t, context->method)) { @@ -5885,14 +5936,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, } handleExit(t, frame); - c->return_(0, 0); + c->return_(); goto next; case sipush: - frame->pushInt - (c->constant - (static_cast(codeReadInt16(t, code, ip)), - Compiler::IntegerType)); + frame->push(ir::Type::i4(), + c->constant(static_cast(codeReadInt16(t, code, ip)), + ir::Type::i4())); break; case swap: @@ -5921,20 +5971,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, ipTable[i] = newIp; - avian::codegen::Promise* p = c->poolAppendPromise - (frame->addressPromise(c->machineIp(newIp))); + avian::codegen::Promise* p = c->poolAppendPromise( + frame->addressPromise(frame->machineIp(newIp))); if (i == 0) { start = p; } } assert(t, start); - Compiler::Operand* key = frame->popInt(); - - c->condJump(lir::JumpIfLess, 4, c->constant(bottom, Compiler::IntegerType), key, - frame->machineIp(defaultIp)); + ir::Value* key = frame->pop(ir::Type::i4()); - c->save(1, key); + c->condJump(lir::JumpIfLess, + c->constant(bottom, ir::Type::i4()), + key, + frame->machineIpValue(defaultIp)); + + c->save(ir::Type::i4(), key); new (stack.push(sizeof(SwitchState))) SwitchState (c->saveState(), count, defaultIp, key, start, bottom, top); @@ -5946,46 +5998,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, case wide: { switch (codeBody(t, code, ip++)) { case aload: { - frame->loadObject(codeReadInt16(t, code, ip)); + frame->load(ir::Type::object(), codeReadInt16(t, code, ip)); } break; case astore: { - frame->storeObject(codeReadInt16(t, code, ip)); + frame->store(ir::Type::object(), codeReadInt16(t, code, ip)); } break; case iinc: { uint16_t index = codeReadInt16(t, code, ip); int16_t count = codeReadInt16(t, code, ip); - storeLocal - (context, 1, - c->binaryOp(lir::Add, - 4, c->constant(count, Compiler::IntegerType), - loadLocal(context, 1, index)), - index); + storeLocal(context, + 1, + ir::Type::i4(), + c->binaryOp(lir::Add, + ir::Type::i4(), + c->constant(count, ir::Type::i4()), + loadLocal(context, 1, ir::Type::i4(), index)), + index); } break; case iload: { - frame->loadInt(codeReadInt16(t, code, ip)); + frame->load(ir::Type::i4(), codeReadInt16(t, code, ip)); } break; case istore: { - frame->storeInt(codeReadInt16(t, code, ip)); + frame->store(ir::Type::i4(), codeReadInt16(t, code, ip)); } break; case lload: { - frame->loadLong(codeReadInt16(t, code, ip)); + frame->loadLarge(ir::Type::i8(), codeReadInt16(t, code, ip)); } break; case lstore: { - frame->storeLong(codeReadInt16(t, code, ip)); + frame->storeLarge(ir::Type::i8(), codeReadInt16(t, code, ip)); } break; case ret: { unsigned index = codeReadInt16(t, code, ip); - c->jmp(loadLocal(context, 1, index)); - frame->returnFromSubroutine(index); - } goto next; + + unsigned returnAddress = frame->endSubroutine(index); + c->jmp(frame->machineIpValue(returnAddress)); + ip = returnAddress; + } break; default: abort(t); } @@ -5999,18 +6055,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, frame->dispose(); frame = 0; stack.pop(sizeof(Frame)); - stack.pop(stackSize); + stack.pop(stackSize * sizeof(ir::Type)); switch (stack.popValue()) { case Return: return; case Unbranch: + if (DebugInstructions) { + fprintf(stderr, "Unbranch\n"); + } ip = stack.popValue(); c->restoreState(reinterpret_cast(stack.popValue())); frame = static_cast(stack.peek(sizeof(Frame))); goto loop; case Untable0: { + if (DebugInstructions) { + fprintf(stderr, "Untable0\n"); + } SwitchState* s = static_cast (stack.peek(sizeof(SwitchState))); @@ -6018,15 +6080,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, c->restoreState(s->state); - c->condJump(lir::JumpIfGreater, 4, c->constant(s->top, Compiler::IntegerType), s->key, - frame->machineIp(s->defaultIp)); - - c->save(1, s->key); + c->condJump(lir::JumpIfGreater, + c->constant(s->top, ir::Type::i4()), + s->key, + frame->machineIpValue(s->defaultIp)); + + c->save(ir::Type::i4(), s->key); ip = s->defaultIp; stack.pushValue(Untable1); } goto start; case Untable1: { + if (DebugInstructions) { + fprintf(stderr, "Untable1\n"); + } SwitchState* s = static_cast (stack.peek(sizeof(SwitchState))); @@ -6034,32 +6101,40 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, c->restoreState(s->state); - Compiler::Operand* normalizedKey - = (s->bottom - ? c->binaryOp(lir::Subtract, 4, c->constant(s->bottom, Compiler::IntegerType), s->key) - : s->key); + ir::Value* normalizedKey + = (s->bottom + ? c->binaryOp(lir::Subtract, + ir::Type::i4(), + c->constant(s->bottom, ir::Type::i4()), + s->key) + : s->key); - Compiler::Operand* entry = c->memory - (frame->absoluteAddressOperand(s->start), Compiler::AddressType, 0, - normalizedKey, TargetBytesPerWord); + ir::Value* entry = c->memory(frame->absoluteAddressOperand(s->start), + ir::Type::iptr(), + 0, + normalizedKey); - c->jmp - (c->load - (TargetBytesPerWord, TargetBytesPerWord, context->bootContext - ? c->binaryOp(lir::Add, - TargetBytesPerWord, c->memory - (c->register_(t->arch->thread()), Compiler::AddressType, - TARGET_THREAD_CODEIMAGE), entry) - : entry, - TargetBytesPerWord)); + c->jmp(c->load(ir::SignExtend, + context->bootContext + ? c->binaryOp(lir::Add, + ir::Type::iptr(), + c->memory(c->threadRegister(), + ir::Type::iptr(), + TARGET_THREAD_CODEIMAGE), + entry) + : entry, + ir::Type::iptr())); s->state = c->saveState(); } goto switchloop; case Unswitch: { + if (DebugInstructions) { + fprintf(stderr, "Unswitch\n"); + } SwitchState* s = static_cast (stack.peek(sizeof(SwitchState))); - + frame = s->frame(); c->restoreState @@ -6067,6 +6142,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned initialIp, } goto switchloop; case Unsubroutine: { + if (DebugInstructions) { + fprintf(stderr, "Unsubroutine\n"); + } ip = stack.popValue(); unsigned start = stack.popValue(); frame = reinterpret_cast(stack.peek(sizeof(Frame))); @@ -6131,9 +6209,8 @@ int resolveIpBackwards(Context* context, int start, int end) { Thread* t = context->thread; - if (start >= static_cast - (codeLength(t, methodCode(t, context->method)))) - { + if (start >= static_cast(codeLength(t, methodCode(t, context->method)) + * (context->subroutineCount + 1))) { start = codeLength(t, methodCode(t, context->method)); } else { while (start >= end and context->visitTable[start] == 0) { @@ -6197,9 +6274,10 @@ truncateLineNumberTable(Thread* t, object table, unsigned length) return newTable; } -object -translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start, - intptr_t end) +object translateExceptionHandlerTable(MyThread* t, + Context* context, + intptr_t start, + intptr_t end) { avian::codegen::Compiler* c = context->compiler; @@ -6211,55 +6289,68 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start, unsigned length = exceptionHandlerTableLength(t, oldTable); - object newIndex = makeIntArray(t, length * 3); + object newIndex + = makeIntArray(t, length * (context->subroutineCount + 1) * 3); PROTECT(t, newIndex); - object newTable = makeArray(t, length + 1); + object newTable = makeArray(t, length * (context->subroutineCount + 1) + 1); PROTECT(t, newTable); unsigned ni = 0; - for (unsigned oi = 0; oi < length; ++ oi) { - uint64_t oldHandler = exceptionHandlerTableBody - (t, oldTable, oi); + for (unsigned subI = 0; subI <= context->subroutineCount; ++subI) { + unsigned duplicatedBaseIp + = subI * codeLength(t, methodCode(t, context->method)); - int handlerStart = resolveIpForwards - (context, exceptionHandlerStart(oldHandler), - exceptionHandlerEnd(oldHandler)); + for (unsigned oi = 0; oi < length; ++oi) { + uint64_t oldHandler = exceptionHandlerTableBody(t, oldTable, oi); - if (LIKELY(handlerStart >= 0)) { - assert(t, handlerStart < static_cast - (codeLength(t, methodCode(t, context->method)))); + int handlerStart = resolveIpForwards( + context, + duplicatedBaseIp + exceptionHandlerStart(oldHandler), + duplicatedBaseIp + exceptionHandlerEnd(oldHandler)); - int handlerEnd = resolveIpBackwards - (context, exceptionHandlerEnd(oldHandler), - exceptionHandlerStart(oldHandler)); + if (LIKELY(handlerStart >= 0)) { + assert( + t, + handlerStart + < static_cast(codeLength(t, methodCode(t, context->method)) + * (context->subroutineCount + 1))); - assert(t, handlerEnd >= 0); - assert(t, handlerEnd <= static_cast - (codeLength(t, methodCode(t, context->method)))); + int handlerEnd = resolveIpBackwards( + context, + duplicatedBaseIp + exceptionHandlerEnd(oldHandler), + duplicatedBaseIp + exceptionHandlerStart(oldHandler)); - intArrayBody(t, newIndex, ni * 3) - = c->machineIp(handlerStart)->value() - start; + assert(t, handlerEnd >= 0); + assert(t, + handlerEnd <= static_cast( + codeLength(t, methodCode(t, context->method)) + * (context->subroutineCount + 1))); - intArrayBody(t, newIndex, (ni * 3) + 1) - = (handlerEnd == static_cast - (codeLength(t, methodCode(t, context->method))) - ? end : c->machineIp(handlerEnd)->value()) - start; + intArrayBody(t, newIndex, ni* 3) = c->machineIp(handlerStart)->value() + - start; - intArrayBody(t, newIndex, (ni * 3) + 2) - = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; + intArrayBody(t, newIndex, (ni* 3) + 1) + = (handlerEnd == static_cast(codeLength( + t, methodCode(t, context->method))) + ? end + : c->machineIp(handlerEnd)->value()) - start; - object type; - if (exceptionHandlerCatchType(oldHandler)) { - type = resolveClassInPool - (t, context->method, exceptionHandlerCatchType(oldHandler) - 1); - } else { - type = 0; + intArrayBody(t, newIndex, (ni* 3) + 2) + = c->machineIp(exceptionHandlerIp(oldHandler))->value() - start; + + object type; + if (exceptionHandlerCatchType(oldHandler)) { + type = resolveClassInPool( + t, context->method, exceptionHandlerCatchType(oldHandler) - 1); + } else { + type = 0; + } + + set(t, newTable, ArrayBody + ((ni + 1) * BytesPerWord), type); + + ++ni; } - - set(t, newTable, ArrayBody + ((ni + 1) * BytesPerWord), type); - - ++ ni; } } @@ -6302,7 +6393,7 @@ translateLineNumberTable(MyThread* t, Context* context, intptr_t start) } if (UNLIKELY(ni < length)) { - newTable = truncateLineNumberTable(t, newTable, ni); + newTable = truncateLineNumberTable(t, newTable, ni); } return newTable; @@ -6325,37 +6416,24 @@ printSet(uintptr_t* m, unsigned limit) } } -void -calculateTryCatchRoots(Context* context, SubroutinePath* subroutinePath, - uintptr_t* roots, unsigned mapSize, unsigned start, - unsigned end) +void calculateTryCatchRoots( + Context* context, + uintptr_t* roots, + unsigned mapSize, + unsigned start, + unsigned end) { memset(roots, 0xFF, mapSize * BytesPerWord); if (DebugFrameMaps) { - fprintf(stderr, "calculate try/catch roots from %d to %d", start, end); - if (subroutinePath) { - fprintf(stderr, " "); - print(subroutinePath); - } - fprintf(stderr, "\n"); + fprintf(stderr, "calculate try/catch roots from %d to %d\n", start, end); } for (TraceElement* te = context->traceLog; te; te = te->next) { if (te->ip >= start and te->ip < end) { uintptr_t* traceRoots = 0; - if (subroutinePath == 0) { - traceRoots = te->map; - te->watch = true; - } else { - for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) { - if (t->path == subroutinePath) { - traceRoots = t->map; - t->watch = true; - break; - } - } - } + traceRoots = te->map; + te->watch = true; if (traceRoots) { if (DebugFrameMaps) { @@ -6382,10 +6460,11 @@ calculateTryCatchRoots(Context* context, SubroutinePath* subroutinePath, } } -unsigned -calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, - unsigned eventIndex, SubroutinePath* subroutinePath = 0, - uintptr_t* resultRoots = 0) +unsigned calculateFrameMaps(MyThread* t, + Context* context, + uintptr_t* originalRoots, + unsigned eventIndex, + uintptr_t* resultRoots) { // for each instruction with more than one predecessor, and for each // stack position, determine if there exists a path to that @@ -6417,9 +6496,11 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, Event e = static_cast(context->eventLog.get(eventIndex++)); switch (e) { case PushContextEvent: { - eventIndex = calculateFrameMaps - (t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, subroutinePath, - resultRoots); + eventIndex = calculateFrameMaps(t, + context, + RUNTIME_ARRAY_BODY(roots), + eventIndex, /*subroutinePath,*/ + resultRoots); } break; case PopContextEvent: @@ -6435,9 +6516,8 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, fprintf(stderr, "\n"); } - uintptr_t* tableRoots - = (subroutinePath ? subroutinePath->rootTable : context->rootTable) - + (ip * mapSize); + assert(context->thread, ip * mapSize <= context->rootTable.count); + uintptr_t* tableRoots = context->rootTable.begin() + (ip * mapSize); if (context->visitTable[ip] > 1) { for (unsigned wi = 0; wi < mapSize; ++wi) { @@ -6488,26 +6568,11 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, unsigned end = context->eventLog.get2(eventIndex); eventIndex += 2; - if (context->subroutineTable and context->subroutineTable[start]) { - Subroutine* s = context->subroutineTable[start]; - unsigned originalEventIndex = eventIndex; + calculateTryCatchRoots( + context, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); - for (SubroutineCall* c = s->calls; c; c = c->next) { - for (SubroutinePath* p = c->paths; p; p = p->listNext) { - calculateTryCatchRoots - (context, p, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); - - eventIndex = calculateFrameMaps - (t, context, RUNTIME_ARRAY_BODY(roots), originalEventIndex, p); - } - } - } else { - calculateTryCatchRoots - (context, 0, RUNTIME_ARRAY_BODY(roots), mapSize, start, end); - - eventIndex = calculateFrameMaps - (t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0); - } + eventIndex = calculateFrameMaps( + t, context, RUNTIME_ARRAY_BODY(roots), eventIndex, 0); } break; case TraceEvent: { @@ -6515,39 +6580,13 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, if (DebugFrameMaps) { fprintf(stderr, " trace roots at ip %3d: ", ip); printSet(RUNTIME_ARRAY_BODY(roots), mapSize); - if (subroutinePath) { - fprintf(stderr, " "); - print(subroutinePath); - } fprintf(stderr, "\n"); } uintptr_t* map; bool watch; - if (subroutinePath == 0) { - map = te->map; - watch = te->watch; - } else { - SubroutineTrace* trace = 0; - for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) { - if (t->path == subroutinePath) { - trace = t; - break; - } - } - - if (trace == 0) { - te->subroutineTrace = trace = new - (context->zone.allocate - (sizeof(SubroutineTrace) + (mapSize * BytesPerWord))) - SubroutineTrace(subroutinePath, te->subroutineTrace, mapSize); - - ++ te->subroutineTraceCount; - } - - map = trace->map; - watch = trace->watch; - } + map = te->map; + watch = te->watch; for (unsigned wi = 0; wi < mapSize; ++wi) { uintptr_t v = RUNTIME_ARRAY_BODY(roots)[wi]; @@ -6566,45 +6605,6 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, eventIndex += BytesPerWord; } break; - case PushSubroutineEvent: { - SubroutineCall* call; - context->eventLog.get(eventIndex, &call, BytesPerWord); - eventIndex += BytesPerWord; - - unsigned nextIndex = context->eventLog.get2(eventIndex); - - eventIndex = nextIndex; - - SubroutinePath* path = 0; - for (SubroutinePath* p = call->paths; p; p = p->listNext) { - if (p->stackNext == subroutinePath) { - path = p; - break; - } - } - - if (path == 0) { - path = new(&context->zone) - SubroutinePath(call, subroutinePath, - makeRootTable(t, &(context->zone), context->method)); - } - - THREAD_RUNTIME_ARRAY(t, uintptr_t, subroutineRoots, mapSize); - - calculateFrameMaps - (t, context, RUNTIME_ARRAY_BODY(roots), call->subroutine->logIndex, - path, RUNTIME_ARRAY_BODY(subroutineRoots)); - - for (unsigned wi = 0; wi < mapSize; ++wi) { - RUNTIME_ARRAY_BODY(roots)[wi] - &= RUNTIME_ARRAY_BODY(subroutineRoots)[wi]; - } - } break; - - case PopSubroutineEvent: - eventIndex = static_cast(-1); - goto exit; - default: abort(t); } } @@ -6614,10 +6614,6 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, if (DebugFrameMaps) { fprintf(stderr, "result roots at ip %3d: ", ip); printSet(RUNTIME_ARRAY_BODY(roots), mapSize); - if (subroutinePath) { - fprintf(stderr, " "); - print(subroutinePath); - } fprintf(stderr, "\n"); } @@ -6675,15 +6671,15 @@ clearBit(int32_t* dst, unsigned index) dst[index / 32] &= ~(static_cast(1) << (index % 32)); } -void -copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits, - unsigned offset, TraceElement* p, - SubroutinePath* subroutinePath) +void copyFrameMap(int32_t* dst, + uintptr_t* src, + unsigned mapSizeInBits, + unsigned offset, + TraceElement* p) { if (DebugFrameMaps) { fprintf(stderr, " orig roots at ip %3d: ", p->ip); printSet(src, ceilingDivide(mapSizeInBits, BitsPerWord)); - print(subroutinePath); fprintf(stderr, "\n"); fprintf(stderr, " final roots at ip %3d: ", p->ip); @@ -6704,7 +6700,6 @@ copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits, } if (DebugFrameMaps) { - print(subroutinePath); fprintf(stderr, "\n"); } } @@ -6745,157 +6740,6 @@ class FrameMapTablePath { int32_t elements[0]; }; -int -compareInt32s(const void* va, const void* vb) -{ - return *static_cast(va) - *static_cast(vb); -} - -int -compare(SubroutinePath* a, SubroutinePath* b) -{ - if (a->stackNext) { - int d = compare(a->stackNext, b->stackNext); - if (d) return d; - } - int64_t av = a->call->returnAddress->value(); - int64_t bv = b->call->returnAddress->value(); - if (av > bv) { - return 1; - } else if (av < bv) { - return -1; - } else { - return 0; - } -} - -int -compareSubroutineTracePointers(const void* va, const void* vb) -{ - return compare((*static_cast(va))->path, - (*static_cast(vb))->path); -} - -object -makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start, - TraceElement** elements, unsigned elementCount, - unsigned pathFootprint, unsigned mapCount) -{ - unsigned mapSize = frameMapSizeInBits(t, context->method); - unsigned indexOffset = sizeof(FrameMapTableHeader); - unsigned mapsOffset = indexOffset - + (elementCount * sizeof(FrameMapTableIndexElement)); - unsigned pathsOffset = mapsOffset + (ceilingDivide(mapCount * mapSize, 32) * 4); - - object table = makeByteArray(t, pathsOffset + pathFootprint); - - int8_t* body = &byteArrayBody(t, table, 0); - new (body) FrameMapTableHeader(elementCount); - - unsigned nextTableIndex = pathsOffset; - unsigned nextMapIndex = 0; - for (unsigned i = 0; i < elementCount; ++i) { - TraceElement* p = elements[i]; - unsigned mapBase = nextMapIndex; - - unsigned pathIndex; - if (p->subroutineTrace) { - FrameMapTablePath* previous = 0; - Subroutine* subroutine = p->subroutineTrace->path->call->subroutine; - for (Subroutine* s = subroutine; s; s = s->stackNext) { - if (s->tableIndex == 0) { - unsigned pathObjectSize = sizeof(FrameMapTablePath) - + (sizeof(int32_t) * s->callCount); - - assert(t, nextTableIndex + pathObjectSize - <= byteArrayLength(t, table)); - - s->tableIndex = nextTableIndex; - - nextTableIndex += pathObjectSize; - - FrameMapTablePath* current = new (body + s->tableIndex) - FrameMapTablePath - (s->stackIndex, s->callCount, - s->stackNext ? s->stackNext->tableIndex : 0); - - unsigned i = 0; - for (SubroutineCall* c = subroutine->calls; c; c = c->next) { - assert(t, i < s->callCount); - - current->elements[i++] - = static_cast(c->returnAddress->value()) - - reinterpret_cast(start); - } - assert(t, i == s->callCount); - - qsort(current->elements, s->callCount, sizeof(int32_t), - compareInt32s); - - if (previous) { - previous->next = s->tableIndex; - } - - previous = current; - } else { - break; - } - } - - pathIndex = subroutine->tableIndex; - - THREAD_RUNTIME_ARRAY - (t, SubroutineTrace*, traces, p->subroutineTraceCount); - - unsigned i = 0; - for (SubroutineTrace* trace = p->subroutineTrace; - trace; trace = trace->next) - { - assert(t, i < p->subroutineTraceCount); - RUNTIME_ARRAY_BODY(traces)[i++] = trace; - } - assert(t, i == p->subroutineTraceCount); - - qsort(RUNTIME_ARRAY_BODY(traces), p->subroutineTraceCount, - sizeof(SubroutineTrace*), compareSubroutineTracePointers); - - for (unsigned i = 0; i < p->subroutineTraceCount; ++i) { - assert(t, mapsOffset + ceilingDivide(nextMapIndex + mapSize, 32) * 4 - <= pathsOffset); - - copyFrameMap(reinterpret_cast(body + mapsOffset), - RUNTIME_ARRAY_BODY(traces)[i]->map, mapSize, - nextMapIndex, p, RUNTIME_ARRAY_BODY(traces)[i]->path); - - nextMapIndex += mapSize; - } - } else { - pathIndex = 0; - - assert(t, mapsOffset + ceilingDivide(nextMapIndex + mapSize, 32) * 4 - <= pathsOffset); - - copyFrameMap(reinterpret_cast(body + mapsOffset), p->map, - mapSize, nextMapIndex, p, 0); - - nextMapIndex += mapSize; - } - - unsigned elementIndex = indexOffset - + (i * sizeof(FrameMapTableIndexElement)); - - assert(t, elementIndex + sizeof(FrameMapTableIndexElement) <= mapsOffset); - - new (body + elementIndex) FrameMapTableIndexElement - (static_cast(p->address->value()) - - reinterpret_cast(start), mapBase, pathIndex); - } - - assert(t, nextMapIndex == mapCount * mapSize); - - return table; -} - object makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, TraceElement** elements, unsigned elementCount) @@ -6917,8 +6761,11 @@ makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start, <= intArrayLength(t, table)); if (mapSize) { - copyFrameMap(&intArrayBody(t, table, elementCount), p->map, - mapSize, i * mapSize, p, 0); + copyFrameMap(&intArrayBody(t, table, elementCount), + p->map, + mapSize, + i * mapSize, + p); } } @@ -7037,29 +6884,12 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) if (context->traceLogCount) { THREAD_RUNTIME_ARRAY(t, TraceElement*, elements, context->traceLogCount); unsigned index = 0; - unsigned pathFootprint = 0; - unsigned mapCount = 0; + // unsigned pathFootprint = 0; + // unsigned mapCount = 0; for (TraceElement* p = context->traceLog; p; p = p->next) { assert(t, index < context->traceLogCount); if (p->address) { - SubroutineTrace* trace = p->subroutineTrace; - unsigned myMapCount = 1; - if (trace) { - for (Subroutine* s = trace->path->call->subroutine; - s; s = s->stackNext) - { - unsigned callCount = s->callCount; - myMapCount *= callCount; - if (not s->visited) { - s->visited = true; - pathFootprint += sizeof(FrameMapTablePath) - + (sizeof(int32_t) * callCount); - } - } - } - - mapCount += myMapCount; RUNTIME_ARRAY_BODY(elements)[index++] = p; @@ -7074,15 +6904,8 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) qsort(RUNTIME_ARRAY_BODY(elements), index, sizeof(TraceElement*), compareTraceElementPointers); - object map; - if (pathFootprint) { - map = makeGeneralFrameMapTable - (t, context, start, RUNTIME_ARRAY_BODY(elements), index, pathFootprint, - mapCount); - } else { - map = makeSimpleFrameMapTable - (t, context, start, RUNTIME_ARRAY_BODY(elements), index); - } + object map = makeSimpleFrameMapTable( + t, context, start, RUNTIME_ARRAY_BODY(elements), index); set(t, methodCode(t, context->method), CodePool, map); } @@ -7129,14 +6952,14 @@ compile(MyThread* t, Context* context) c->init(codeLength(t, methodCode(t, context->method)), footprint, locals, alignedFrameSize(t, context->method)); - THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, - codeMaxStack(t, methodCode(t, context->method))); - Frame frame(context, RUNTIME_ARRAY_BODY(stackMap)); + ir::Type* stackMap = (ir::Type*)malloc( + sizeof(ir::Type) * codeMaxStack(t, methodCode(t, context->method))); + Frame frame(context, stackMap); unsigned index = methodParameterFootprint(t, context->method); if ((methodFlags(t, context->method) & ACC_STATIC) == 0) { - frame.set(--index, Frame::Object); - c->initLocal(1, index, Compiler::ObjectType); + frame.set(--index, ir::Type::object()); + c->initLocal(index, ir::Type::object()); } for (MethodSpecIterator it @@ -7147,30 +6970,30 @@ compile(MyThread* t, Context* context) switch (*it.next()) { case 'L': case '[': - frame.set(--index, Frame::Object); - c->initLocal(1, index, Compiler::ObjectType); + frame.set(--index, ir::Type::object()); + c->initLocal(index, ir::Type::object()); break; - + case 'J': - frame.set(--index, Frame::Long); - frame.set(--index, Frame::Long); - c->initLocal(2, index, Compiler::IntegerType); + frame.set(--index, ir::Type::i8()); + frame.set(--index, ir::Type::i8()); + c->initLocal(index, ir::Type::i8()); break; case 'D': - frame.set(--index, Frame::Long); - frame.set(--index, Frame::Long); - c->initLocal(2, index, Compiler::FloatType); + frame.set(--index, ir::Type::f8()); + frame.set(--index, ir::Type::f8()); + c->initLocal(index, ir::Type::f8()); break; - + case 'F': - frame.set(--index, Frame::Integer); - c->initLocal(1, index, Compiler::FloatType); + frame.set(--index, ir::Type::i4()); + c->initLocal(index, ir::Type::f4()); break; - + default: - frame.set(--index, Frame::Integer); - c->initLocal(1, index, Compiler::IntegerType); + frame.set(--index, ir::Type::i4()); + c->initLocal(index, ir::Type::i4()); break; } } @@ -7182,7 +7005,7 @@ compile(MyThread* t, Context* context) compile(t, &frame, 0); context->dirtyRoots = false; - unsigned eventIndex = calculateFrameMaps(t, context, 0, 0); + unsigned eventIndex = calculateFrameMaps(t, context, 0, 0, 0); object eht = codeExceptionHandlerTable(t, methodCode(t, context->method)); if (eht) { @@ -7197,48 +7020,51 @@ compile(MyThread* t, Context* context) while (progress) { progress = false; - for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { - uint64_t eh = exceptionHandlerTableBody(t, eht, i); - int start = resolveIpForwards - (context, exceptionHandlerStart(eh), exceptionHandlerEnd(eh)); + for (unsigned subI = 0; subI <= context->subroutineCount; ++subI) { + unsigned duplicatedBaseIp + = subI * codeLength(t, methodCode(t, context->method)); - if ((not RUNTIME_ARRAY_BODY(visited)[i]) - and start >= 0 - and context->visitTable[start]) - { - RUNTIME_ARRAY_BODY(visited)[i] = true; - progress = true; + for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { + uint64_t eh = exceptionHandlerTableBody(t, eht, i); + int start + = resolveIpForwards(context, + duplicatedBaseIp + exceptionHandlerStart(eh), + duplicatedBaseIp + exceptionHandlerEnd(eh)); - c->restoreState(state); + if ((not RUNTIME_ARRAY_BODY(visited)[i])and start + >= 0 and context->visitTable[start]) { + RUNTIME_ARRAY_BODY(visited)[i] = true; + progress = true; - THREAD_RUNTIME_ARRAY - (t, uint8_t, stackMap, - codeMaxStack(t, methodCode(t, context->method))); - Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap)); + c->restoreState(state); - unsigned end = exceptionHandlerEnd(eh); - if (exceptionHandlerIp(eh) >= static_cast(start) - and exceptionHandlerIp(eh) < end) - { - end = exceptionHandlerIp(eh); + ir::Type* stackMap = (ir::Type*)malloc( + sizeof(ir::Type) + * codeMaxStack(t, methodCode(t, context->method))); + Frame frame2(&frame, stackMap); + + unsigned end = duplicatedBaseIp + exceptionHandlerEnd(eh); + if (exceptionHandlerIp(eh) >= static_cast(start) + and exceptionHandlerIp(eh) < end) { + end = duplicatedBaseIp + exceptionHandlerIp(eh); + } + + context->eventLog.append(PushExceptionHandlerEvent); + context->eventLog.append2(start); + context->eventLog.append2(end); + + for (unsigned i = 1; + i < codeMaxStack(t, methodCode(t, context->method)); + ++i) { + frame2.set(localSize(t, context->method) + i, ir::Type::i4()); + } + + compile(t, &frame2, exceptionHandlerIp(eh), start); + + context->eventLog.append(PopContextEvent); + + eventIndex = calculateFrameMaps(t, context, 0, eventIndex, 0); } - - context->eventLog.append(PushExceptionHandlerEvent); - context->eventLog.append2(start); - context->eventLog.append2(end); - - for (unsigned i = 1; - i < codeMaxStack(t, methodCode(t, context->method)); - ++i) - { - frame2.set(localSize(t, context->method) + i, Frame::Integer); - } - - compile(t, &frame2, exceptionHandlerIp(eh), start); - - context->eventLog.append(PopContextEvent); - - eventIndex = calculateFrameMaps(t, context, 0, eventIndex); } } } @@ -7246,8 +7072,9 @@ compile(MyThread* t, Context* context) while (context->dirtyRoots) { context->dirtyRoots = false; - calculateFrameMaps(t, context, 0, 0); + calculateFrameMaps(t, context, 0, 0, 0); } + free(stackMap); } void diff --git a/src/debug-util.cpp b/src/debug-util.cpp new file mode 100644 index 0000000000..c0275aae97 --- /dev/null +++ b/src/debug-util.cpp @@ -0,0 +1,612 @@ +/* Copyright (c) 2008-2013, 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 + +#include "debug-util.h" + +namespace avian { +namespace jvm { +namespace debug { + +uint16_t read16(uint8_t* code, unsigned& ip) +{ + uint16_t a = code[ip++]; + uint16_t b = code[ip++]; + return (a << 8) | b; +} + +uint32_t read32(uint8_t* code, unsigned& ip) +{ + uint32_t b = code[ip++]; + uint32_t a = code[ip++]; + uint32_t c = code[ip++]; + uint32_t d = code[ip++]; + return (a << 24) | (b << 16) | (c << 8) | d; +} + +using namespace vm; + +int printInstruction(uint8_t* code, unsigned& ip, const char* prefix) +{ + unsigned startIp = ip; + + uint8_t instr = code[ip++]; + switch (instr) { + case aaload: + return fprintf(stderr, "aaload"); + case aastore: + return fprintf(stderr, "aastore"); + + case aconst_null: + return fprintf(stderr, "aconst_null"); + + case aload: + return fprintf(stderr, "aload %2d", code[ip++]); + case aload_0: + return fprintf(stderr, "aload_0"); + case aload_1: + return fprintf(stderr, "aload_1"); + case aload_2: + return fprintf(stderr, "aload_2"); + case aload_3: + return fprintf(stderr, "aload_3"); + + case anewarray: + return fprintf(stderr, "anewarray %4d", read16(code, ip)); + case areturn: + return fprintf(stderr, "areturn"); + case arraylength: + return fprintf(stderr, "arraylength"); + + case astore: + return fprintf(stderr, "astore %2d", code[ip++]); + case astore_0: + return fprintf(stderr, "astore_0"); + case astore_1: + return fprintf(stderr, "astore_1"); + case astore_2: + return fprintf(stderr, "astore_2"); + case astore_3: + return fprintf(stderr, "astore_3"); + + case athrow: + return fprintf(stderr, "athrow"); + case baload: + return fprintf(stderr, "baload"); + case bastore: + return fprintf(stderr, "bastore"); + + case bipush: + return fprintf(stderr, "bipush %2d", code[ip++]); + case caload: + return fprintf(stderr, "caload"); + case castore: + return fprintf(stderr, "castore"); + case checkcast: + return fprintf(stderr, "checkcast %4d", read16(code, ip)); + case d2f: + return fprintf(stderr, "d2f"); + case d2i: + return fprintf(stderr, "d2i"); + case d2l: + return fprintf(stderr, "d2l"); + case dadd: + return fprintf(stderr, "dadd"); + case daload: + return fprintf(stderr, "daload"); + case dastore: + return fprintf(stderr, "dastore"); + case dcmpg: + return fprintf(stderr, "dcmpg"); + case dcmpl: + return fprintf(stderr, "dcmpl"); + case dconst_0: + return fprintf(stderr, "dconst_0"); + case dconst_1: + return fprintf(stderr, "dconst_1"); + case ddiv: + return fprintf(stderr, "ddiv"); + case dmul: + return fprintf(stderr, "dmul"); + case dneg: + return fprintf(stderr, "dneg"); + case vm::drem: + return fprintf(stderr, "drem"); + case dsub: + return fprintf(stderr, "dsub"); + case dup: + return fprintf(stderr, "dup"); + case dup_x1: + return fprintf(stderr, "dup_x1"); + case dup_x2: + return fprintf(stderr, "dup_x2"); + case dup2: + return fprintf(stderr, "dup2"); + case dup2_x1: + return fprintf(stderr, "dup2_x1"); + case dup2_x2: + return fprintf(stderr, "dup2_x2"); + case f2d: + return fprintf(stderr, "f2d"); + case f2i: + return fprintf(stderr, "f2i"); + case f2l: + return fprintf(stderr, "f2l"); + case fadd: + return fprintf(stderr, "fadd"); + case faload: + return fprintf(stderr, "faload"); + case fastore: + return fprintf(stderr, "fastore"); + case fcmpg: + return fprintf(stderr, "fcmpg"); + case fcmpl: + return fprintf(stderr, "fcmpl"); + case fconst_0: + return fprintf(stderr, "fconst_0"); + case fconst_1: + return fprintf(stderr, "fconst_1"); + case fconst_2: + return fprintf(stderr, "fconst_2"); + case fdiv: + return fprintf(stderr, "fdiv"); + case fmul: + return fprintf(stderr, "fmul"); + case fneg: + return fprintf(stderr, "fneg"); + case frem: + return fprintf(stderr, "frem"); + case fsub: + return fprintf(stderr, "fsub"); + + case getfield: + return fprintf(stderr, "getfield %4d", read16(code, ip)); + case getstatic: + return fprintf(stderr, "getstatic %4d", read16(code, ip)); + case goto_: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "goto %4d", offset + ip - 3); + } + case goto_w: { + int32_t offset = read32(code, ip); + return fprintf(stderr, "goto_w %08x", offset + ip - 5); + } + + case i2b: + return fprintf(stderr, "i2b"); + case i2c: + return fprintf(stderr, "i2c"); + case i2d: + return fprintf(stderr, "i2d"); + case i2f: + return fprintf(stderr, "i2f"); + case i2l: + return fprintf(stderr, "i2l"); + case i2s: + return fprintf(stderr, "i2s"); + case iadd: + return fprintf(stderr, "iadd"); + case iaload: + return fprintf(stderr, "iaload"); + case iand: + return fprintf(stderr, "iand"); + case iastore: + return fprintf(stderr, "iastore"); + case iconst_m1: + return fprintf(stderr, "iconst_m1"); + case iconst_0: + return fprintf(stderr, "iconst_0"); + case iconst_1: + return fprintf(stderr, "iconst_1"); + case iconst_2: + return fprintf(stderr, "iconst_2"); + case iconst_3: + return fprintf(stderr, "iconst_3"); + case iconst_4: + return fprintf(stderr, "iconst_4"); + case iconst_5: + return fprintf(stderr, "iconst_5"); + case idiv: + return fprintf(stderr, "idiv"); + + case if_acmpeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_acmpeq %4d", offset + ip - 3); + } + case if_acmpne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_acmpne %4d", offset + ip - 3); + } + case if_icmpeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpeq %4d", offset + ip - 3); + } + case if_icmpne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpne %4d", offset + ip - 3); + } + + case if_icmpgt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpgt %4d", offset + ip - 3); + } + case if_icmpge: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmpge %4d", offset + ip - 3); + } + case if_icmplt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmplt %4d", offset + ip - 3); + } + case if_icmple: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "if_icmple %4d", offset + ip - 3); + } + + case ifeq: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifeq %4d", offset + ip - 3); + } + case ifne: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifne %4d", offset + ip - 3); + } + case ifgt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifgt %4d", offset + ip - 3); + } + case ifge: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifge %4d", offset + ip - 3); + } + case iflt: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "iflt %4d", offset + ip - 3); + } + case ifle: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifle %4d", offset + ip - 3); + } + + case ifnonnull: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifnonnull %4d", offset + ip - 3); + } + case ifnull: { + int16_t offset = read16(code, ip); + return fprintf(stderr, "ifnull %4d", offset + ip - 3); + } + + case iinc: { + uint8_t a = code[ip++]; + uint8_t b = code[ip++]; + return fprintf(stderr, "iinc %2d %2d", a, b); + } + + case iload: + return fprintf(stderr, "iload %2d", code[ip++]); + case fload: + return fprintf(stderr, "fload %2d", code[ip++]); + + case iload_0: + return fprintf(stderr, "iload_0"); + case fload_0: + return fprintf(stderr, "fload_0"); + case iload_1: + return fprintf(stderr, "iload_1"); + case fload_1: + return fprintf(stderr, "fload_1"); + + case iload_2: + return fprintf(stderr, "iload_2"); + case fload_2: + return fprintf(stderr, "fload_2"); + case iload_3: + return fprintf(stderr, "iload_3"); + case fload_3: + return fprintf(stderr, "fload_3"); + + case imul: + return fprintf(stderr, "imul"); + case ineg: + return fprintf(stderr, "ineg"); + + case instanceof: + return fprintf(stderr, "instanceof %4d", read16(code, ip)); + case invokeinterface: + return fprintf(stderr, "invokeinterface %4d", read16(code, ip)); + case invokespecial: + return fprintf(stderr, "invokespecial %4d", read16(code, ip)); + case invokestatic: + return fprintf(stderr, "invokestatic %4d", read16(code, ip)); + case invokevirtual: + return fprintf(stderr, "invokevirtual %4d", read16(code, ip)); + + case ior: + return fprintf(stderr, "ior"); + case irem: + return fprintf(stderr, "irem"); + case ireturn: + return fprintf(stderr, "ireturn"); + case freturn: + return fprintf(stderr, "freturn"); + case ishl: + return fprintf(stderr, "ishl"); + case ishr: + return fprintf(stderr, "ishr"); + + case istore: + return fprintf(stderr, "istore %2d", code[ip++]); + case fstore: + return fprintf(stderr, "fstore %2d", code[ip++]); + + case istore_0: + return fprintf(stderr, "istore_0"); + case fstore_0: + return fprintf(stderr, "fstore_0"); + case istore_1: + return fprintf(stderr, "istore_1"); + case fstore_1: + return fprintf(stderr, "fstore_1"); + case istore_2: + return fprintf(stderr, "istore_2"); + case fstore_2: + return fprintf(stderr, "fstore_2"); + case istore_3: + return fprintf(stderr, "istore_3"); + case fstore_3: + return fprintf(stderr, "fstore_3"); + + case isub: + return fprintf(stderr, "isub"); + case iushr: + return fprintf(stderr, "iushr"); + case ixor: + return fprintf(stderr, "ixor"); + + case jsr: + return fprintf(stderr, "jsr %4d", read16(code, ip) + startIp); + case jsr_w: + return fprintf(stderr, "jsr_w %08x", read32(code, ip) + startIp); + + case l2d: + return fprintf(stderr, "l2d"); + case l2f: + return fprintf(stderr, "l2f"); + case l2i: + return fprintf(stderr, "l2i"); + case ladd: + return fprintf(stderr, "ladd"); + case laload: + return fprintf(stderr, "laload"); + + case land: + return fprintf(stderr, "land"); + case lastore: + return fprintf(stderr, "lastore"); + + case lcmp: + return fprintf(stderr, "lcmp"); + case lconst_0: + return fprintf(stderr, "lconst_0"); + case lconst_1: + return fprintf(stderr, "lconst_1"); + + case ldc: + return fprintf(stderr, "ldc %4d", read16(code, ip)); + case ldc_w: + return fprintf(stderr, "ldc_w %08x", read32(code, ip)); + case ldc2_w: + return fprintf(stderr, "ldc2_w %4d", read16(code, ip)); + + case ldiv_: + return fprintf(stderr, "ldiv_"); + + case lload: + return fprintf(stderr, "lload %2d", code[ip++]); + case dload: + return fprintf(stderr, "dload %2d", code[ip++]); + + case lload_0: + return fprintf(stderr, "lload_0"); + case dload_0: + return fprintf(stderr, "dload_0"); + case lload_1: + return fprintf(stderr, "lload_1"); + case dload_1: + return fprintf(stderr, "dload_1"); + case lload_2: + return fprintf(stderr, "lload_2"); + case dload_2: + return fprintf(stderr, "dload_2"); + case lload_3: + return fprintf(stderr, "lload_3"); + case dload_3: + return fprintf(stderr, "dload_3"); + + case lmul: + return fprintf(stderr, "lmul"); + case lneg: + return fprintf(stderr, "lneg"); + + case lookupswitch: { + while (ip & 0x3) { + ip++; + } + int32_t default_ = read32(code, ip) + startIp; + int32_t pairCount = read32(code, ip); + fprintf( + stderr, "lookupswitch default: %d pairCount: %d", default_, pairCount); + + for (int i = 0; i < pairCount; i++) { + int32_t k = read32(code, ip); + int32_t d = read32(code, ip) + startIp; + fprintf(stderr, "\n%s key: %2d dest: %d", prefix, k, d); + } + fprintf(stderr, "\n"); + fflush(stderr); + return 0; + } + + case lor: + return fprintf(stderr, "lor"); + case lrem: + return fprintf(stderr, "lrem"); + case lreturn: + return fprintf(stderr, "lreturn"); + case dreturn: + return fprintf(stderr, "dreturn"); + case lshl: + return fprintf(stderr, "lshl"); + case lshr: + return fprintf(stderr, "lshr"); + + case lstore: + return fprintf(stderr, "lstore %2d", code[ip++]); + case dstore: + return fprintf(stderr, "dstore %2d", code[ip++]); + + case lstore_0: + return fprintf(stderr, "lstore_0"); + case dstore_0: + return fprintf(stderr, "dstore_0"); + case lstore_1: + return fprintf(stderr, "lstore_1"); + case dstore_1: + return fprintf(stderr, "dstore_1"); + case lstore_2: + return fprintf(stderr, "lstore_2"); + case dstore_2: + return fprintf(stderr, "dstore_2"); + case lstore_3: + return fprintf(stderr, "lstore_3"); + case dstore_3: + return fprintf(stderr, "dstore_3"); + + case lsub: + return fprintf(stderr, "lsub"); + case lushr: + return fprintf(stderr, "lushr"); + case lxor: + return fprintf(stderr, "lxor"); + + case monitorenter: + return fprintf(stderr, "monitorenter"); + case monitorexit: + return fprintf(stderr, "monitorexit"); + + case multianewarray: { + unsigned type = read16(code, ip); + return fprintf(stderr, "multianewarray %4d %2d", type, code[ip++]); + } + + case new_: + return fprintf(stderr, "new %4d", read16(code, ip)); + + case newarray: + return fprintf(stderr, "newarray %2d", code[ip++]); + + case nop: + return fprintf(stderr, "nop"); + case pop_: + return fprintf(stderr, "pop"); + case pop2: + return fprintf(stderr, "pop2"); + + case putfield: + return fprintf(stderr, "putfield %4d", read16(code, ip)); + case putstatic: + return fprintf(stderr, "putstatic %4d", read16(code, ip)); + + case ret: + return fprintf(stderr, "ret %2d", code[ip++]); + + case return_: + return fprintf(stderr, "return_"); + case saload: + return fprintf(stderr, "saload"); + case sastore: + return fprintf(stderr, "sastore"); + + case sipush: + return fprintf(stderr, "sipush %4d", read16(code, ip)); + + case swap: + return fprintf(stderr, "swap"); + + case tableswitch: { + while (ip & 0x3) { + ip++; + } + int32_t default_ = read32(code, ip) + startIp; + int32_t bottom = read32(code, ip); + int32_t top = read32(code, ip); + fprintf(stderr, + "tableswitch default: %d bottom: %d top: %d", + default_, + bottom, + top); + + for (int i = 0; i < top - bottom + 1; i++) { + int32_t d = read32(code, ip) + startIp; + fprintf(stderr, "%s key: %d dest: %d", prefix, i + bottom, d); + } + return 0; + } + + case wide: { + switch (code[ip++]) { + case aload: + return fprintf(stderr, "wide aload %4d", read16(code, ip)); + + case astore: + return fprintf(stderr, "wide astore %4d", read16(code, ip)); + case iinc: + fprintf(stderr, "wide iinc %4d %4d", read16(code, ip), read16(code, ip)); + case iload: + return fprintf(stderr, "wide iload %4d", read16(code, ip)); + case istore: + return fprintf(stderr, "wide istore %4d", read16(code, ip)); + case lload: + return fprintf(stderr, "wide lload %4d", read16(code, ip)); + case lstore: + return fprintf(stderr, "wide lstore %4d", read16(code, ip)); + case ret: + return fprintf(stderr, "wide ret %4d", read16(code, ip)); + + default: { + fprintf( + stderr, "unknown wide instruction %2d %4d", instr, read16(code, ip)); + } + } + } + + default: { + return fprintf(stderr, "unknown instruction %2d", instr); + } + } + return ip; +} + +void disassembleCode(const char* prefix, uint8_t* code, unsigned length) +{ + unsigned ip = 0; + + while (ip < length) { + fprintf(stderr, "%s%x:\t", prefix, ip); + printInstruction(code, ip, prefix); + fprintf(stderr, "\n"); + } +} + +} // namespace debug +} // namespace jvm +} // namespace avian diff --git a/src/debug-util.h b/src/debug-util.h new file mode 100644 index 0000000000..bb981baa10 --- /dev/null +++ b/src/debug-util.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2008-2013, 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 + +namespace avian { +namespace jvm { +namespace debug { + +// print out a single instruction (no newline) +// returns number of characters printed +int printInstruction(uint8_t* code, unsigned& ip, const char* prefix = ""); +void disassembleCode(const char* prefix, uint8_t* code, unsigned length); + +} // namespace debug +} // namespace jvm +} // namespace avian diff --git a/test/Subroutine.java b/test/Subroutine.java index d566f78095..5fb5bfa223 100644 --- a/test/Subroutine.java +++ b/test/Subroutine.java @@ -253,6 +253,16 @@ public class Subroutine { return true; } + private static int test6(boolean predicate) { + try { + if (predicate) { + return -2; + } + } finally { + return new Throwable().getStackTrace()[0].getLineNumber(); + } + } + public static void main(String[] args) throws Exception { test(false, false); test(false, true); @@ -311,6 +321,15 @@ public class Subroutine { (null, new Object[0]); stackMap(new Object()); + + { + int f = test6(false); + int t = test6(true); + System.out.println("line: " + f); + expect(f > 0); + expect(f == t); + } + } private static class DummyException extends RuntimeException { } diff --git a/test/ci.sh b/test/ci.sh index a2fd8492a5..f64c13939b 100755 --- a/test/ci.sh +++ b/test/ci.sh @@ -24,6 +24,7 @@ run make ${flags} process=interpret ${test_target} # bootimage and openjdk builds without openjdk-src don't work: if [ -z "${openjdk}" ]; then run make ${flags} bootimage=true ${test_target} + run make ${flags} mode=debug bootimage=true ${test_target} # might as well do an openjdk test while we're here: run make openjdk=$JAVA_HOME ${flags} ${test_target} fi