diff --git a/src/assembler.h b/src/assembler.h index 44c127db05..e597554ee8 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -159,11 +159,11 @@ class Assembler { virtual int argumentRegister(unsigned index) = 0; virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, - uint64_t* registerMask, uintptr_t* procedure) = 0; + uint64_t* registerMask, bool* thunk) = 0; virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, - uint64_t* bRegisterMask, uintptr_t* procedure) = 0; + uint64_t* bRegisterMask, bool* thunk) = 0; virtual void apply(Operation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index f11b69d367..0a61e7a3c8 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = false; +const bool Verbose = true; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -438,6 +438,19 @@ makeRootTable(MyThread* t, Zone* zone, object method) return table; } +enum Thunk { +#define THUNK(s) s##Thunk, + +#include "thunks.cpp" + +#undef THUNK +}; + +const unsigned ThunkCount = gcIfNecessaryThunk + 1; + +intptr_t +getThunk(MyThread* t, Thunk thunk); + class Context { public: class MyProtector: public Thread::Protector { @@ -459,11 +472,43 @@ class Context { Context* c; }; - Context(MyThread* t, object method, void* indirection): + class MyClient: public Compiler::Client { + public: + MyClient(MyThread* t): t(t) { } + + virtual intptr_t getThunk(UnaryOperation, unsigned) { + abort(t); + } + + virtual intptr_t getThunk(BinaryOperation op, unsigned size) { + switch (op) { + case Divide: + if (size == 8) { + return ::getThunk(t, divideLongThunk); + } + break; + + case Remainder: + if (size == 8) { + return ::getThunk(t, moduloLongThunk); + } + break; + + default: break; + } + + abort(t); + } + + MyThread* t; + }; + + Context(MyThread* t, object method): thread(t), zone(t->m->system, t->m->heap, 16 * 1024), assembler(makeAssembler(t->m->system, t->m->heap, &zone)), - compiler(makeCompiler(t->m->system, assembler, &zone, indirection)), + client(t), + compiler(makeCompiler(t->m->system, assembler, &zone, &client)), method(method), objectPool(0), traceLog(0), @@ -478,6 +523,7 @@ class Context { thread(t), zone(t->m->system, t->m->heap, LikelyPageSizeInBytes), assembler(makeAssembler(t->m->system, t->m->heap, &zone)), + client(t), compiler(0), method(0), objectPool(0), @@ -497,6 +543,7 @@ class Context { MyThread* thread; Zone zone; Assembler* assembler; + MyClient client; Compiler* compiler; object method; PoolElement* objectPool; @@ -1323,13 +1370,13 @@ negateFloat(uint32_t a) return floatToBits(- bitsToFloat(a)); } -int64_t +int64_t FORCE_ALIGN divideLong(int64_t b, int64_t a) { return a / b; } -int64_t +int64_t FORCE_ALIGN moduloLong(int64_t b, int64_t a) { return a % b; @@ -1495,13 +1542,36 @@ makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions, } } -void NO_RETURN FORCE_ALIGN -throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) +unsigned +traceSize(Thread* t) { - object message = makeString - (t, "array of length %d indexed at %d", - cast(array, BytesPerWord), index); - t->exception = makeArrayIndexOutOfBoundsException(t, message); + class Counter: public Processor::StackVisitor { + public: + Counter(): count(0) { } + + virtual bool visit(Processor::StackWalker*) { + ++ count; + return true; + } + + unsigned count; + } counter; + + t->m->processor->walkStack(t, &counter); + + return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray) + + (counter.count * FixedSizeOfTraceElement); +} + +void NO_RETURN FORCE_ALIGN +throwArrayIndexOutOfBounds(MyThread* t) +{ + ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t)); + + t->tracing = true; + t->exception = makeArrayIndexOutOfBoundsException(t, 0); + t->tracing = false; + unwind(t); } @@ -1598,10 +1668,13 @@ emptyMethod(MyThread* t, object method) } object -defaultCompiled(MyThread* t); +defaultThunk(MyThread* t); object -nativeCompiled(MyThread* t); +nativeThunk(MyThread* t); + +object +aioobThunk(MyThread* t); void compileDirectInvoke(MyThread* t, Frame* frame, object target) @@ -1617,16 +1690,16 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) result = c->call (c->constant (reinterpret_cast - (&singletonBody(t, nativeCompiled(t), 0))), + (&singletonBody(t, nativeThunk(t), 0))), 0, frame->trace(target, false), rSize, 0); - } else if (methodCompiled(t, target) == defaultCompiled(t)) { + } else if (methodCompiled(t, target) == defaultThunk(t)) { result = c->call (c->constant (reinterpret_cast - (&singletonBody(t, defaultCompiled(t), 0))), + (&singletonBody(t, defaultThunk(t), 0))), Compiler::Aligned, frame->trace(target, false), rSize, @@ -1666,7 +1739,7 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) } c->call(c->constant(function), - Compiler::Indirect, + 0, frame->trace(0, false), 0, 2, c->thread(), lock); @@ -1692,14 +1765,14 @@ handleEntrance(MyThread* t, Frame* frame) } handleMonitorEvent - (t, frame, reinterpret_cast(acquireMonitorForObject)); + (t, frame, getThunk(t, acquireMonitorForObjectThunk)); } void handleExit(MyThread* t, Frame* frame) { handleMonitorEvent - (t, frame, reinterpret_cast(releaseMonitorForObject)); + (t, frame, getThunk(t, releaseMonitorForObjectThunk)); } void @@ -1733,8 +1806,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject(); c->call - (c->constant(reinterpret_cast(gcIfNecessary)), - Compiler::Indirect, + (c->constant(getThunk(t, gcIfNecessaryThunk)), + 0, frame->trace(0, false), 0, 1, c->thread()); @@ -1753,47 +1826,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iaload: case laload: case saload: { - if (CheckArrayBounds) { - Compiler::Operand* index = c->peek(4, 0); - Compiler::Operand* array = c->peek(BytesPerWord, 1); - - Compiler::Operand* load = c->label(); - Compiler::Operand* throw_ = 0; - - if (c->isConstant(index)) { - expect(t, c->constantValue(index) >= 0); - } else { - throw_ = c->label(); - c->cmp(4, c->constant(0), index); - c->jl(throw_); - - index = c->peek(4, 0); - array = c->peek(BytesPerWord, 1); - } - - c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jg(load); - - if (not c->isConstant(index)) { - c->mark(throw_); - } - - index = c->peek(4, 0); - array = c->peek(BytesPerWord, 1); - - c->call - (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - Compiler::NoReturn | Compiler::Indirect, - frame->trace(0, false), - 0, - 3, c->thread(), array, index); - - c->mark(load); - } - Compiler::Operand* index = frame->popInt(); Compiler::Operand* array = frame->popObject(); + if (CheckArrayBounds) { + c->checkBounds(array, ArrayLength, index, reinterpret_cast + (&singletonValue(t, aioobThunk(t), 0))); + } + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { @@ -1866,47 +1906,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case iastore: case lastore: case sastore: { - if (CheckArrayBounds) { - unsigned valueSize - = (instruction == dastore or instruction == lastore ? 2 : 1); - - Compiler::Operand* index = c->peek(4, valueSize); - Compiler::Operand* array = c->peek(BytesPerWord, valueSize + 1); - - Compiler::Operand* store = c->label(); - Compiler::Operand* throw_ = 0; - - if (c->isConstant(index)) { - expect(t, c->constantValue(index) >= 0); - } else { - throw_ = c->label(); - c->cmp(4, c->constant(0), index); - c->jl(throw_); - - index = c->peek(4, valueSize); - array = c->peek(BytesPerWord, valueSize + 1); - } - - c->cmp(BytesPerWord, index, c->memory(array, ArrayLength, 0, 1)); - c->jg(store); - - if (not c->isConstant(index)) { - c->mark(throw_); - } - - index = c->peek(4, valueSize); - array = c->peek(BytesPerWord, valueSize + 1); - - c->call - (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), - Compiler::NoReturn | Compiler::Indirect, - frame->trace(0, false), - 0, - 3, c->thread(), array, index); - - c->mark(store); - } - Compiler::Operand* value; if (instruction == dastore or instruction == lastore) { value = frame->popLong(); @@ -1919,13 +1918,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* index = frame->popInt(); Compiler::Operand* array = frame->popObject(); + if (CheckArrayBounds) { + c->checkBounds(array, ArrayLength, index, reinterpret_cast + (&singletonValue(t, aioobThunk(t), 0))); + } + if (c->isConstant(index)) { unsigned i = c->constantValue(index); switch (instruction) { case aastore: { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), array, @@ -1956,8 +1960,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, switch (instruction) { case aastore: { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), array, @@ -2022,8 +2026,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call - (c->constant(reinterpret_cast(makeBlankObjectArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeBlankObjectArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(class_), length)); @@ -2062,8 +2066,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case athrow: { c->call - (c->constant(reinterpret_cast(throw_)), - Compiler::NoReturn | Compiler::Indirect, + (c->constant(getThunk(t, throw_Thunk)), + Compiler::NoReturn, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); @@ -2083,8 +2087,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* instance = c->peek(BytesPerWord, 0); c->call - (c->constant(reinterpret_cast(checkCast)), - Compiler::Indirect, + (c->constant(getThunk(t, checkCastThunk)), + 0, frame->trace(0, false), 0, 3, c->thread(), frame->append(class_), instance); @@ -2093,24 +2097,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case d2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(doubleToFloat)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, doubleToFloatThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; case d2i: { frame->pushInt (c->call - (c->constant(reinterpret_cast(doubleToInt)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, doubleToIntThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; case d2l: { frame->pushLong (c->call - (c->constant(reinterpret_cast(doubleToLong)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, doubleToLongThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; @@ -2120,8 +2124,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(addDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, addDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2132,8 +2136,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareDoublesG)), - Compiler::Indirect, 0, 4, 4, + (c->constant(getThunk(t, compareDoublesGThunk)), + 0, 0, 4, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2144,8 +2148,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareDoublesL)), - Compiler::Indirect, 0, 4, 4, + (c->constant(getThunk(t, compareDoublesLThunk)), + 0, 0, 4, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2164,8 +2168,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(divideDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, divideDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2176,8 +2180,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(multiplyDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, multiplyDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2185,8 +2189,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case dneg: { frame->pushLong (c->call - (c->constant(reinterpret_cast(negateDouble)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, negateDoubleThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; @@ -2196,8 +2200,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(moduloDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, moduloDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2208,8 +2212,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushLong (c->call - (c->constant(reinterpret_cast(subtractDouble)), - Compiler::Indirect, 0, 8, 4, + (c->constant(getThunk(t, subtractDoubleThunk)), + 0, 0, 8, 4, static_cast(0), a, static_cast(0), b)); } break; @@ -2241,22 +2245,22 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case f2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(floatToDouble)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, floatToDoubleThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case f2i: { frame->pushInt (c->call - (c->constant(reinterpret_cast(floatToInt)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, floatToIntThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case f2l: { frame->pushLong (c->call - (c->constant(reinterpret_cast(floatToLong)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, floatToLongThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case fadd: { @@ -2265,8 +2269,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(addFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, addFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fcmpg: { @@ -2275,8 +2279,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareFloatsG)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, compareFloatsGThunk)), + 0, 0, 4, 2, a, b)); } break; case fcmpl: { @@ -2285,8 +2289,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(compareFloatsL)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, compareFloatsLThunk)), + 0, 0, 4, 2, a, b)); } break; case fconst_0: @@ -2307,8 +2311,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(divideFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, divideFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fmul: { @@ -2317,15 +2321,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(multiplyFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, multiplyFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fneg: { frame->pushInt (c->call - (c->constant(reinterpret_cast(negateFloat)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, negateFloatThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case vm::frem: { @@ -2334,8 +2338,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(moduloFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, moduloFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case fsub: { @@ -2344,8 +2348,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(subtractFloat)), - Compiler::Indirect, 0, 4, 2, a, b)); + (c->constant(getThunk(t, subtractFloatThunk)), + 0, 0, 4, 2, a, b)); } break; case getfield: @@ -2362,8 +2366,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) { c->call - (c->constant(reinterpret_cast(tryInitClass)), - Compiler::Indirect, + (c->constant(getThunk(t, tryInitClassThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -2441,15 +2445,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case i2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(intToDouble)), - Compiler::Indirect, 0, 8, 1, frame->popInt())); + (c->constant(getThunk(t, intToDoubleThunk)), + 0, 0, 8, 1, frame->popInt())); } break; case i2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(intToFloat)), - Compiler::Indirect, 0, 4, 1, frame->popInt())); + (c->constant(getThunk(t, intToFloatThunk)), + 0, 0, 4, 1, frame->popInt())); } break; case i2l: @@ -2675,8 +2679,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushInt (c->call - (c->constant(reinterpret_cast(instanceOf)), - Compiler::Indirect, 0, 4, + (c->constant(getThunk(t, instanceOfThunk)), + 0, 0, 4, 3, c->thread(), frame->append(class_), frame->popObject())); } break; @@ -2696,8 +2700,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* result = c->call (c->call (c->constant - (reinterpret_cast(findInterfaceMethodFromInstance)), - Compiler::Indirect, + (getThunk(t, findInterfaceMethodFromInstanceThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), frame->append(target), @@ -2868,16 +2872,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case l2d: { frame->pushLong (c->call - (c->constant(reinterpret_cast(longToDouble)), - Compiler::Indirect, 0, 8, 2, + (c->constant(getThunk(t, longToDoubleThunk)), + 0, 0, 8, 2, static_cast(0), frame->popLong())); } break; case l2f: { frame->pushInt (c->call - (c->constant(reinterpret_cast(longToFloat)), - Compiler::Indirect, 0, 4, 2, + (c->constant(getThunk(t, longToFloatThunk)), + 0, 0, 4, 2, static_cast(0), frame->popLong())); } break; @@ -3055,8 +3059,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp (c->call - (c->constant(reinterpret_cast(lookUpAddress)), - Compiler::Indirect, 0, BytesPerWord, + (c->constant(getThunk(t, lookUpAddressThunk)), + 0, 0, BytesPerWord, 4, key, start, c->constant(pairCount), default_)); for (int32_t i = 0; i < pairCount; ++i) { @@ -3142,15 +3146,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case monitorenter: { c->call - (c->constant(reinterpret_cast(acquireMonitorForObject)), - Compiler::Indirect, + (c->constant(getThunk(t, acquireMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; case monitorexit: { c->call - (c->constant(reinterpret_cast(releaseMonitorForObject)), - Compiler::Indirect, + (c->constant(getThunk(t, releaseMonitorForObjectThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->popObject()); } break; @@ -3163,8 +3167,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, PROTECT(t, class_); Compiler::Operand* result = c->call - (c->constant(reinterpret_cast(makeMultidimensionalArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeMultidimensionalArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 4, c->thread(), frame->append(class_), c->constant(dimensions), @@ -3183,16 +3187,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (classVmFlags(t, class_) & WeakReferenceFlag) { frame->pushObject (c->call - (c->constant(reinterpret_cast(makeNewWeakReference)), - Compiler::Indirect, + (c->constant(getThunk(t, makeNewWeakReferenceThunk)), + 0, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); } else { frame->pushObject (c->call - (c->constant(reinterpret_cast(makeNew)), - Compiler::Indirect, + (c->constant(getThunk(t, makeNewThunk)), + 0, frame->trace(0, false), BytesPerWord, 2, c->thread(), frame->append(class_))); @@ -3243,8 +3247,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->pushObject (c->call - (c->constant(reinterpret_cast(makeBlankArray)), - Compiler::Indirect, + (c->constant(getThunk(t, makeBlankArrayThunk)), + 0, frame->trace(0, false), BytesPerWord, 3, c->thread(), c->constant(reinterpret_cast(constructor)), @@ -3275,8 +3279,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, and (classVmFlags(t, fieldClass(t, field)) & InitFlag) == 0) { c->call - (c->constant(reinterpret_cast(tryInitClass)), - Compiler::Indirect, + (c->constant(getThunk(t, tryInitClassThunk)), + 0, frame->trace(0, false), 0, 2, c->thread(), frame->append(fieldClass(t, field))); @@ -3340,15 +3344,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case ObjectField: if (instruction == putfield) { c->call - (c->constant(reinterpret_cast(setMaybeNull)), - Compiler::Indirect, + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, frame->trace(0, false), 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } else { c->call - (c->constant(reinterpret_cast(set)), - Compiler::Indirect, 0, 0, + (c->constant(getThunk(t, setThunk)), + 0, 0, 0, 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } break; @@ -3683,7 +3687,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, return eventIndex; } -Allocator* +Zone* codeZone(MyThread* t); int @@ -3722,6 +3726,14 @@ frameObjectMapSize(MyThread* t, object method, object map) return ceiling(intArrayLength(t, map) * size, 32 + size); } +unsigned +codeSingletonSizeInBytes(MyThread*, unsigned codeSizeInBytes) +{ + unsigned count = ceiling(codeSizeInBytes, BytesPerWord); + unsigned size = count + singletonMaskSize(count); + return pad(SingletonBody + (size * BytesPerWord)); +} + object allocateCode(MyThread* t, unsigned codeSizeInBytes) { @@ -3860,7 +3872,7 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "compareTo") == 0) { asm("int3"); } @@ -4380,41 +4392,6 @@ popThread(MyThread*, Assembler* a) } } -object -compileDefault(MyThread* t, Assembler* a) -{ - saveStackAndBase(t, a); - pushThread(t, a); - - ResolvedPromise procPromise(reinterpret_cast(compileMethod)); - Assembler::Constant proc(&procPromise); - a->apply(Call, BytesPerWord, ConstantOperand, &proc); - - popThread(t, a); - - Assembler::Register result(a->returnLow()); - a->apply(Jump, BytesPerWord, RegisterOperand, &result); - - return finish(t, a, "default"); -} - -object -compileNative(MyThread* t, Assembler* a) -{ - saveStackAndBase(t, a); - pushThread(t, a); - - ResolvedPromise promise(reinterpret_cast(invokeNative)); - Assembler::Constant proc(&promise); - a->apply(Call, BytesPerWord, ConstantOperand, &proc); - - popThread(t, a); - - a->apply(Return); - - return finish(t, a, "native"); -} - class ArgumentList { public: ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_, @@ -4593,27 +4570,6 @@ invoke(Thread* thread, object method, ArgumentList* arguments) return r; } -unsigned -traceSize(Thread* t) -{ - class Counter: public Processor::StackVisitor { - public: - Counter(): count(0) { } - - virtual bool visit(Processor::StackWalker*) { - ++ count; - return true; - } - - unsigned count; - } counter; - - t->m->processor->walkStack(t, &counter); - - return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray) - + (counter.count * FixedSizeOfTraceElement); -} - class SegFaultHandler: public System::SignalHandler { public: SegFaultHandler(): m(0) { } @@ -4686,14 +4642,13 @@ class MyProcessor: public Processor { MyProcessor(System* s, Allocator* allocator): s(s), allocator(allocator), - defaultCompiled(0), - nativeCompiled(0), + defaultThunk(0), + nativeThunk(0), + aioobThunk(0), callTable(0), callTableSize(0), methodTree(0), methodTreeSentinal(0), - indirectCaller(0), - indirectCallerSize(0), codeAllocator(s), codeZone(s, &codeAllocator, 64 * 1024) { } @@ -4707,22 +4662,6 @@ class MyProcessor: public Processor { return t; } - object getDefaultCompiled(MyThread* t) { - if (defaultCompiled == 0) { - Context context(t); - defaultCompiled = compileDefault(t, context.assembler); - } - return defaultCompiled; - } - - object getNativeCompiled(MyThread* t) { - if (nativeCompiled == 0) { - Context context(t); - nativeCompiled = compileNative(t, context.assembler); - } - return nativeCompiled; - } - virtual object makeMethod(vm::Thread* t, uint8_t vmFlags, @@ -4739,7 +4678,7 @@ class MyProcessor: public Processor { return vm::makeMethod (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, offset, name, spec, class_, code, - getDefaultCompiled(static_cast(t))); + ::defaultThunk(static_cast(t))); } virtual object @@ -4770,7 +4709,7 @@ class MyProcessor: public Processor { initVtable(Thread* t, object c) { void* compiled = &singletonBody - (t, getDefaultCompiled(static_cast(t)), 0); + (t, ::defaultThunk(static_cast(t)), 0); for (unsigned i = 0; i < classLength(t, c); ++i) { classVtable(t, c, i) = compiled; @@ -4801,8 +4740,6 @@ class MyProcessor: public Processor { MyThread* t = static_cast(vmt); if (t == t->m->rootThread) { - v->visit(&defaultCompiled); - v->visit(&nativeCompiled); v->visit(&callTable); v->visit(&methodTree); v->visit(&methodTreeSentinal); @@ -4970,13 +4907,13 @@ class MyProcessor: public Processor { virtual object getStackTrace(Thread* vmt, Thread* vmTarget) { MyThread* t = static_cast(vmt); MyThread* target = static_cast(vmTarget); - - processor(t)->getDefaultCompiled(t); - processor(t)->getNativeCompiled(t); + MyProcessor* p = processor(t); class Visitor: public System::ThreadVisitor { public: - Visitor(MyThread* t, MyThread* target): t(t), target(target) { } + Visitor(MyThread* t, MyProcessor* p, MyThread* target): + t(t), p(p), target(target) + { } virtual void visit(void* ip, void* base, void* stack) { void* oldIp = target->ip; @@ -4988,25 +4925,12 @@ class MyProcessor: public Processor { target->base = base; target->stack = stack; } else { - MyProcessor* p = processor(t); + uint8_t* thunkStart = reinterpret_cast + (&singletonValue(t, p->thunkTable, 0)); + uint8_t* thunkEnd = thunkStart + (p->thunkSize * ThunkCount); - uint8_t* default_ = reinterpret_cast - (&singletonValue(t, p->defaultCompiled, 0)); - unsigned defaultSize = singletonLength(t, p->defaultCompiled); - - uint8_t* native = reinterpret_cast - (&singletonValue(t, p->nativeCompiled, 0)); - unsigned nativeSize = singletonLength(t, p->nativeCompiled); - - if ((static_cast(ip) >= p->indirectCaller - and static_cast(ip) - < p->indirectCaller + p->indirectCallerSize) - - or (static_cast(ip) >= default_ - and static_cast(ip) < default_ + defaultSize) - - or (static_cast(ip) >= native - and static_cast(ip) < native + nativeSize)) + if (static_cast(ip) >= thunkStart + and static_cast(ip) < thunkEnd) { target->ip = *static_cast(stack); target->base = base; @@ -5026,9 +4950,10 @@ class MyProcessor: public Processor { } MyThread* t; + MyProcessor* p; MyThread* target; object trace; - } visitor(t, target); + } visitor(t, p, target); t->m->system->visit(t->systemThread, target->systemThread, &visitor); @@ -5043,19 +4968,159 @@ class MyProcessor: public Processor { System* s; Allocator* allocator; - object defaultCompiled; - object nativeCompiled; + object defaultThunk; + object nativeThunk; + object aioobThunk; + object thunkTable; + unsigned thunkSize; object callTable; unsigned callTableSize; object methodTree; object methodTreeSentinal; - uint8_t* indirectCaller; - unsigned indirectCallerSize; SegFaultHandler segFaultHandler; CodeAllocator codeAllocator; Zone codeZone; }; +intptr_t +getThunk(MyThread* t, Thunk thunk) +{ + MyProcessor* p = processor(t); + + return reinterpret_cast + (&singletonValue(t, p->thunkTable, (thunk * p->thunkSize) / BytesPerWord)); +} + +void +compileThunks(MyThread* t, MyProcessor* p) +{ + class ThunkContext { + public: + class MyPromise: public Promise { + public: + MyPromise(): resolved_(false) { } + + virtual int64_t value() { + return value_; + } + + virtual bool resolved() { + return resolved_; + } + + int64_t value_; + bool resolved_; + }; + + ThunkContext(MyThread* t): context(t) { } + + Context context; + MyPromise promise; + }; + + ThunkContext defaultContext(t); + + { Assembler* a = defaultContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + defaultContext.promise.resolved_ = true; + defaultContext.promise.value_ = reinterpret_cast(compileMethod); + + Assembler::Constant proc(&(defaultContext.promise)); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); + + popThread(t, a); + + Assembler::Register result(a->returnLow()); + a->apply(Jump, BytesPerWord, RegisterOperand, &result); + } + + ThunkContext nativeContext(t); + + { Assembler* a = nativeContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + nativeContext.promise.resolved_ = true; + nativeContext.promise.value_ = reinterpret_cast(invokeNative); + + Assembler::Constant proc(&(nativeContext.promise)); + a->apply(Call, BytesPerWord, ConstantOperand, &proc); + + popThread(t, a); + + a->apply(Return); + } + + ThunkContext aioobContext(t); + + { Assembler* a = aioobContext.context.assembler; + + saveStackAndBase(t, a); + pushThread(t, a); + + aioobContext.promise.resolved_ = true; + aioobContext.promise.value_ = reinterpret_cast + (throwArrayIndexOutOfBounds); + + Assembler::Constant proc(&(aioobContext.promise)); + a->apply(Jump, BytesPerWord, ConstantOperand, &proc); + } + + ThunkContext tableContext(t); + + { Assembler* a = tableContext.context.assembler; + + saveStackAndBase(t, a); + + Assembler::Constant proc(&(tableContext.promise)); + a->apply(Jump, BytesPerWord, ConstantOperand, &proc); + } + + p->thunkSize = pad(tableContext.context.assembler->length()); + + expect(t, codeZone(t)->ensure + (codeSingletonSizeInBytes + (t, defaultContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, nativeContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, aioobContext.context.assembler->length()) + + codeSingletonSizeInBytes + (t, p->thunkSize * ThunkCount))); + + Zone::Segment* oldSegment = codeZone(t)->segment; + + p->defaultThunk = finish(t, defaultContext.context.assembler, "default"); + p->nativeThunk = finish(t, nativeContext.context.assembler, "native"); + p->aioobThunk = finish(t, aioobContext.context.assembler, "aioob"); + + p->thunkTable = allocateCode(t, p->thunkSize * ThunkCount); + uint8_t* start = reinterpret_cast + (&singletonValue(t, p->thunkTable, 0)); + + if (Verbose) { + logCompile(start, p->thunkSize * ThunkCount, 0, "thunkTable", 0); + fprintf(stderr, "thunk size: %d\n", p->thunkSize); + } + + tableContext.promise.resolved_ = true; + +#define THUNK(s) \ + tableContext.promise.value_ = reinterpret_cast(s); \ + tableContext.context.assembler->writeTo(start); \ + start += p->thunkSize; + +#include "thunks.cpp" + +#undef THUNK + + assert(t, oldSegment == codeZone(t)->segment); +} + MyProcessor* processor(MyThread* t) { @@ -5070,23 +5135,7 @@ processor(MyThread* t) set(t, p->methodTree, TreeNodeLeft, p->methodTreeSentinal); set(t, p->methodTree, TreeNodeRight, p->methodTreeSentinal); - Context context(t); - Assembler* a = context.assembler; - - saveStackAndBase(t, a); - - Assembler::Register proc(a->returnLow()); - a->apply(Jump, BytesPerWord, RegisterOperand, &proc); - - p->indirectCallerSize = a->length(); - p->indirectCaller = static_cast - (p->codeZone.allocate(p->indirectCallerSize)); - a->writeTo(p->indirectCaller); - - if (Verbose) { - logCompile - (p->indirectCaller, p->indirectCallerSize, 0, "indirect caller", 0); - } + compileThunks(t, p); p->segFaultHandler.m = t->m; expect(t, t->m->system->success @@ -5097,15 +5146,21 @@ processor(MyThread* t) } object -defaultCompiled(MyThread* t) +defaultThunk(MyThread* t) { - return processor(t)->getDefaultCompiled(t); + return processor(t)->defaultThunk; } object -nativeCompiled(MyThread* t) +nativeThunk(MyThread* t) { - return processor(t)->getNativeCompiled(t); + return processor(t)->nativeThunk; +} + +object +aioobThunk(MyThread* t) +{ + return processor(t)->aioobThunk; } void @@ -5113,21 +5168,21 @@ compile(MyThread* t, object method) { MyProcessor* p = processor(t); - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { PROTECT(t, method); ACQUIRE(t, t->m->classLock); - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { initClass(t, methodClass(t, method)); if (UNLIKELY(t->exception)) return; - if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { + if (methodCompiled(t, method) == p->defaultThunk) { object compiled; if (methodFlags(t, method) & ACC_NATIVE) { - compiled = p->getNativeCompiled(t); + compiled = p->nativeThunk; } else { - Context context(t, method, p->indirectCaller); + Context context(t, method); compiled = compile(t, &context); if (UNLIKELY(t->exception)) return; } @@ -5252,7 +5307,7 @@ methodTreeSentinal(MyThread* t) return processor(t)->methodTreeSentinal; } -Allocator* +Zone* codeZone(MyThread* t) { return &(processor(t)->codeZone); } diff --git a/src/compiler.cpp b/src/compiler.cpp index b69bd94c64..c941ba377c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -184,11 +184,12 @@ class Value: public Compiler::Operand { class Context { public: - Context(System* system, Assembler* assembler, Zone* zone, void* indirection): + Context(System* system, Assembler* assembler, Zone* zone, + Compiler::Client* client): system(system), assembler(assembler), zone(zone), - indirection(indirection), + client(client), logicalIp(-1), state(new (zone->allocate(sizeof(State))) State(0, 0)), logicalCode(0), @@ -220,7 +221,7 @@ class Context { System* system; Assembler* assembler; Zone* zone; - void* indirection; + Compiler::Client* client; int logicalIp; State* state; LogicalInstruction* logicalCode; @@ -884,6 +885,13 @@ anyRegisterSite(Context* c) return virtualSite(c, 0, 1 << RegisterOperand, ~static_cast(0)); } +VirtualSite* +registerOrConstantSite(Context* c) +{ + return virtualSite(c, 0, (1 << RegisterOperand) | (1 << ConstantOperand), + ~static_cast(0)); +} + Site* targetOrRegister(Context* c, Value* v) { @@ -1366,14 +1374,8 @@ class CallEvent: public Event { s = s->next; } - if (flags & Compiler::Indirect) { - int r = c->assembler->returnLow(); - addRead(c, address, BytesPerWord, fixedRegisterSite(c, r)); - mask &= ~(1 << r); - } else { - addRead(c, address, BytesPerWord, virtualSite - (c, 0, ~0, (static_cast(mask) << 32) | mask)); - } + addRead(c, address, BytesPerWord, virtualSite + (c, 0, ~0, (static_cast(mask) << 32) | mask)); for (Stack* s = stack; s; s = s->next) { s->pushEvent->active = true; @@ -1392,12 +1394,7 @@ class CallEvent: public Event { pushNow(c, stack); UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); - if (flags & Compiler::Indirect) { - apply(c, type, BytesPerWord, - constantSite(c, reinterpret_cast(c->indirection))); - } else { - apply(c, type, BytesPerWord, address->source); - } + apply(c, type, BytesPerWord, address->source); if (traceHandler) { traceHandler->handleTrace @@ -1575,14 +1572,14 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, VirtualSite* srcTarget = virtualSite(c, dst); VirtualSite* dstTarget = virtualSite(c); - uintptr_t procedure; + bool thunk; c->assembler->plan(type, size, &(srcTarget->typeMask), &(srcTarget->registerMask), &(dstTarget->typeMask), &(dstTarget->registerMask), - &procedure); + &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo new (c->zone->allocate(sizeof(MoveEvent))) MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); @@ -1619,14 +1616,14 @@ appendCompare(Context* c, unsigned size, Value* first, Value* second) { VirtualSite* firstTarget = virtualSite(c); VirtualSite* secondTarget = virtualSite(c); - uintptr_t procedure; + bool thunk; c->assembler->plan(Compare, size, &(firstTarget->typeMask), &(firstTarget->registerMask), &(secondTarget->typeMask), &(secondTarget->registerMask), - &procedure); + &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo if (DebugAppend) { fprintf(stderr, "appendCompare\n"); @@ -1723,14 +1720,14 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, { VirtualSite* firstTarget = virtualSite(c); VirtualSite* secondTarget = virtualSite(c, result); - uintptr_t procedure; + bool thunk; c->assembler->plan(type, size, &(firstTarget->typeMask), &(firstTarget->registerMask), &(secondTarget->typeMask), &(secondTarget->registerMask), - &procedure); + &thunk); - if (procedure) { + if (thunk) { secondTarget->value = 0; Stack* oldStack = c->state->stack; @@ -1741,8 +1738,8 @@ appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, Stack* argumentStack = c->state->stack; c->state->stack = oldStack; - appendCall(c, value(c, constantSite(c, procedure)), Compiler::Indirect, - 0, result, size, argumentStack, 2); + appendCall(c, value(c, constantSite(c, c->client->getThunk(type, size))), + 0, 0, result, size, argumentStack, 2); } else { if (DebugAppend) { fprintf(stderr, "appendCombine\n"); @@ -1798,12 +1795,12 @@ appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, } VirtualSite* target = virtualSite(c, result); - uintptr_t procedure; + bool thunk; c->assembler->plan - (type, size, &(target->typeMask), &(target->registerMask), &procedure); + (type, size, &(target->typeMask), &(target->registerMask), &thunk); - assert(c, procedure == 0); // todo + assert(c, not thunk); // todo target->typeMask &= ~(1 << MemoryOperand); @@ -2178,6 +2175,105 @@ appendLocal(Context* c, unsigned size, Local* local) new (c->zone->allocate(sizeof(LocalEvent))) LocalEvent(c, size, local); } +CodePromise* +codePromise(Context* c, Event* e) +{ + return e->promises = new (c->zone->allocate(sizeof(CodePromise))) + CodePromise(c, e->promises); +} + +CodePromise* +codePromise(Context* c, int offset) +{ + return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); +} + +class BoundsCheckEvent: public Event { + public: + BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler): + Event(c), object(object), lengthOffset(lengthOffset), index(index), + handler(handler) + { + addRead(c, object, BytesPerWord, anyRegisterSite(c)); + addRead(c, index, BytesPerWord, registerOrConstantSite(c)); + } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "BoundsCheckEvent.compile\n"); + } + + Assembler* a = c->assembler; + + ConstantSite* constant = 0; + for (Site* s = index->sites; s; s = s->next) { + if (s->type(c) == ConstantOperand) { + constant = static_cast(s); + break; + } + } + + CodePromise* nextPromise = codePromise(c, -1); + CodePromise* outOfBoundsPromise; + + if (constant) { + expect(c, constant->value.value->value() >= 0); + } else { + outOfBoundsPromise = codePromise(c, -1); + + apply(c, Compare, 4, constantSite(c, resolved(c, 0)), index->source); + + Assembler::Constant outOfBoundsConstant(outOfBoundsPromise); + a->apply + (JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant); + } + + assert(c, object->source->type(c) == RegisterOperand); + int base = static_cast(object->source)->register_.low; + + Site* length = memorySite(c, base, lengthOffset); + length->acquire(c, 0, 0, 0); + + apply(c, Compare, BytesPerWord, index->source, length); + + length->release(c); + + Assembler::Constant nextConstant(nextPromise); + a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant); + + if (constant == 0) { + outOfBoundsPromise->offset = a->length(); + } + + ResolvedPromise handlerPromise(handler); + Assembler::Constant handlerConstant(&handlerPromise); + a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant); + + nextPromise->offset = a->length(); + + nextRead(c, object); + nextRead(c, index); + } + + Value* object; + unsigned lengthOffset; + Value* index; + intptr_t handler; +}; + +void +appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, + Value* index, intptr_t handler) +{ + if (DebugAppend) { + fprintf(stderr, "appendLocal\n"); + } + + new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent + (c, object, lengthOffset, index, handler); +} + Site* readSource(Context* c, Stack* stack, Read* r) { @@ -2420,8 +2516,9 @@ class Client: public Assembler::Client { class MyCompiler: public Compiler { public: - MyCompiler(System* s, Assembler* assembler, Zone* zone, void* indirection): - c(s, assembler, zone, indirection), client(&c) + MyCompiler(System* s, Assembler* assembler, Zone* zone, + Compiler::Client* compilerClient): + c(s, assembler, zone, compilerClient), client(&c) { assembler->setClient(&client); } @@ -2569,9 +2666,7 @@ class MyCompiler: public Compiler { } Promise* machineIp() { - Event* e = c.logicalCode[c.logicalIp].lastEvent; - return e->promises = new (c.zone->allocate(sizeof(CodePromise))) - CodePromise(&c, e->promises); + return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent); } virtual void mark(Operand* label) { @@ -2710,6 +2805,13 @@ class MyCompiler: public Compiler { return v; } + virtual void checkBounds(Operand* object, unsigned lengthOffset, + Operand* index, intptr_t handler) + { + appendBoundsCheck(&c, static_cast(object), + lengthOffset, static_cast(index), handler); + } + virtual void store(unsigned size, Operand* src, Operand* dst) { appendMove(&c, Move, size, static_cast(src), static_cast(dst)); @@ -2876,7 +2978,7 @@ class MyCompiler: public Compiler { } Context c; - Client client; + ::Client client; }; } // namespace @@ -2885,10 +2987,10 @@ namespace vm { Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, - void* indirection) + Compiler::Client* client) { return new (zone->allocate(sizeof(MyCompiler))) - MyCompiler(system, assembler, zone, indirection); + MyCompiler(system, assembler, zone, client); } } // namespace vm diff --git a/src/compiler.h b/src/compiler.h index 93d4d0a351..6d27a60cc1 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -19,9 +19,16 @@ namespace vm { class Compiler { public: + class Client { + public: + virtual ~Client() { } + + virtual intptr_t getThunk(UnaryOperation op, unsigned size) = 0; + virtual intptr_t getThunk(BinaryOperation op, unsigned size) = 0; + }; + static const unsigned Aligned = 1 << 0; static const unsigned NoReturn = 1 << 1; - static const unsigned Indirect = 1 << 2; class Operand { }; @@ -80,6 +87,9 @@ class Compiler { virtual void storeLocal(unsigned size, Operand* src, unsigned index) = 0; virtual Operand* loadLocal(unsigned size, unsigned index) = 0; + virtual void checkBounds(Operand* object, unsigned lengthOffset, + Operand* index, intptr_t handler) = 0; + virtual void store(unsigned size, Operand* src, Operand* dst) = 0; virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; @@ -114,7 +124,7 @@ class Compiler { Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, - void* indirection); + Compiler::Client* client); } // namespace vm diff --git a/src/thunks.cpp b/src/thunks.cpp new file mode 100644 index 0000000000..833ffd8114 --- /dev/null +++ b/src/thunks.cpp @@ -0,0 +1,44 @@ +THUNK(tryInitClass) +THUNK(findInterfaceMethodFromInstance) +THUNK(compareDoublesG) +THUNK(compareDoublesL) +THUNK(compareFloatsG) +THUNK(compareFloatsL) +THUNK(addDouble) +THUNK(subtractDouble) +THUNK(multiplyDouble) +THUNK(divideDouble) +THUNK(moduloDouble) +THUNK(negateDouble) +THUNK(doubleToFloat) +THUNK(doubleToInt) +THUNK(doubleToLong) +THUNK(addFloat) +THUNK(subtractFloat) +THUNK(multiplyFloat) +THUNK(divideFloat) +THUNK(moduloFloat) +THUNK(negateFloat) +THUNK(floatToDouble) +THUNK(floatToInt) +THUNK(floatToLong) +THUNK(intToDouble) +THUNK(intToFloat) +THUNK(longToDouble) +THUNK(longToFloat) +THUNK(divideLong) +THUNK(moduloLong) +THUNK(makeBlankObjectArray) +THUNK(makeBlankArray) +THUNK(lookUpAddress) +THUNK(setMaybeNull) +THUNK(acquireMonitorForObject) +THUNK(releaseMonitorForObject) +THUNK(makeMultidimensionalArray) +THUNK(throw_) +THUNK(checkCast) +THUNK(instanceOf) +THUNK(makeNewWeakReference) +THUNK(makeNew) +THUNK(set) +THUNK(gcIfNecessary) diff --git a/src/x86.cpp b/src/x86.cpp index 67a2e59eac..75334f5b84 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,18 +35,6 @@ enum { r15 = 15, }; -int64_t FORCE_ALIGN -divideLong(int64_t a, int64_t b) -{ - return a / b; -} - -int64_t FORCE_ALIGN -moduloLong(int64_t a, int64_t b) -{ - return a % b; -} - inline bool isInt8(intptr_t v) { @@ -364,16 +352,23 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) { assert(c, size == BytesPerWord); + if (a->low & 8) rex(c, 0x40, a->low); c->code.append(0xff); - c->code.append(0xe0 | a->low); + c->code.append(0xe0 | (a->low & 7)); } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +jumpC(Context* c, unsigned size, Assembler::Constant* a) { assert(c, size == BytesPerWord); - unconditional(c, 0xe9, a); + if (BytesPerWord == 8) { + Assembler::Register r(r10); + moveCR(c, size, a, &r); + jumpR(c, size, &r); + } else { + unconditional(c, 0xe9, a); + } } void @@ -660,7 +655,7 @@ moveCM(Context* c, unsigned size, Assembler::Constant* a, break; case 4: - encode(c, 0xc7, 0, b, true); + encode(c, 0xc7, 0, b, false); c->code.append4(a->value->value()); break; @@ -1940,7 +1935,7 @@ class MyAssembler: public Assembler { } virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask, - uint64_t* registerMask, uintptr_t* procedure) + uint64_t* registerMask, bool* thunk) { if (op == Negate and BytesPerWord == 4 and size == 8) { *typeMask = 1 << RegisterOperand; @@ -1950,12 +1945,12 @@ class MyAssembler: public Assembler { *typeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *registerMask = ~static_cast(0); } - *procedure = 0; + *thunk = false; } virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask, uint64_t* aRegisterMask, uint8_t* bTypeMask, - uint64_t* bRegisterMask, uintptr_t* procedure) + uint64_t* bRegisterMask, bool* thunk) { *aTypeMask = ~0; *aRegisterMask = ~static_cast(0); @@ -1963,7 +1958,7 @@ class MyAssembler: public Assembler { *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *bRegisterMask = ~static_cast(0); - *procedure = 0; + *thunk = false; switch (op) { case Compare: @@ -2004,7 +1999,7 @@ class MyAssembler: public Assembler { case Divide: if (BytesPerWord == 4 and size == 8) { *bTypeMask = ~0; - *procedure = reinterpret_cast(divideLong); + *thunk = true; } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax; @@ -2014,7 +2009,7 @@ class MyAssembler: public Assembler { case Remainder: if (BytesPerWord == 4 and size == 8) { *bTypeMask = ~0; - *procedure = reinterpret_cast(moduloLong); + *thunk = true; } else { *aRegisterMask = ~((1 << rax) | (1 << rdx)); *bRegisterMask = 1 << rax;