From 808b4780b169788555e0e7b487b575770be47a97 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 10 Oct 2007 15:34:04 -0600 Subject: [PATCH 1/3] progress towards stack mapping --- src/compile.cpp | 216 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 156 insertions(+), 60 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 2a1b193894..1b1a787c68 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -612,7 +612,7 @@ class Assembler { Assembler(System* s): code(s, 1024), - jumps(s, 32) + jumps(s, 256) { } void rex() { @@ -1145,47 +1145,111 @@ parameterOffset(unsigned index) Compiled* caller(MyThread* t); -class StackMap { +class StackMapper { public: - void mark(unsigned /*index*/) { - // todo + static const uint32_t Infinity = ~static_cast(0); + + enum { + PushLong, + PushInt, + PushObject, + Duplicate, + PopLong, + PopInt, + PopObject, + PopIntOrObject, + StoreObject, + Jump, + Branch + }; + + StackMapper(Thread* t, object method): + t(t), + method(method), + index(codeSize() ? static_cast + (t->m->system->allocate(codeSize() * 4)) : 0), + log(t->m->system, 1024), + calls(t->m->system, 256) + { } + + ~StackMapper() { + if (index) { + t->m->system->free(index); + } + } + + unsigned codeSize() { + return method ? codeLength(t, methodCode(t, method)) : 0; + } + + void newIp(unsigned javaIp) { + assert(t, javaIp < codeSize()); + index[javaIp] = log.length(); + } + + void called(unsigned javaIp, unsigned machineIp) { + calls.append4(javaIp); + calls.append4(machineIp); } void pushedLong() { - // todo + log.append(PushLong); } void pushedInt() { - // todo + log.append(PushInt); } void pushedObject() { - // todo + log.append(PushObject); } - void dup() { - // todo + void dupped() { + log.append(Duplicate); } void poppedLong() { - // todo + log.append(PopLong); } void poppedInt() { - // todo + log.append(PopInt); } void poppedObject() { - // todo + log.append(PopObject); } void poppedIntOrObject() { - // todo + log.append(PopIntOrObject); } - void unknownTerritory(unsigned) { - // todo + void storedObject(unsigned index) { + log.append(StoreObject); + log.append2(index); } + + void jumped(unsigned nextJavaIp) { + jumped(nextJavaIp, Infinity); + } + + void jumped(unsigned nextJavaIp, unsigned targetJavaIp) { + log.append(Jump); + log.append4(nextJavaIp); + log.append4(targetJavaIp); + } + + void branched(unsigned nextJavaIp, unsigned targetJavaIp) { + log.append(Branch); + log.append4(nextJavaIp); + log.append4(targetJavaIp); + } + + Thread* t; + object method; + uint32_t* index; + Buffer log; + Buffer calls; }; class Compiler: public Assembler { @@ -1194,6 +1258,8 @@ class Compiler: public Assembler { Assembler(t->m->system), t(t), method(method), + ip(0), + stackMapper(t, method), poolRegisterClobbered(true), machineIPs(method ? static_cast (t->m->system->allocate @@ -1215,39 +1281,53 @@ class Compiler: public Assembler { pool(t->m->system, 256) { } + ~Compiler() { + if (machineIPs) { + t->m->system->free(machineIPs); + } + + if (lineNumbers) { + t->m->system->free(lineNumbers); + } + + if (exceptionHandlers) { + t->m->system->free(exceptionHandlers); + } + } + void pushInt() { sub(BytesPerWord, rsp); - stackMap.pushedInt(); + stackMapper.pushedInt(); } void pushInt(int32_t v) { push(v); - stackMap.pushedInt(); + stackMapper.pushedInt(); } void pushInt(Register r) { push(r); - stackMap.pushedInt(); + stackMapper.pushedInt(); } void pushInt(Register r, int32_t offset) { push4(r, offset); - stackMap.pushedInt(); + stackMapper.pushedInt(); } void pushObject(int32_t v) { push(v); - stackMap.pushedObject(); + stackMapper.pushedObject(); } void pushObject(Register r) { push(r); - stackMap.pushedObject(); + stackMapper.pushedObject(); } void pushObject(Register r, int32_t offset) { push(r, offset); - stackMap.pushedObject(); + stackMapper.pushedObject(); } void pushLong(uint64_t v) { @@ -1258,28 +1338,28 @@ class Compiler: public Assembler { push((v >> 32) & 0xFFFFFFFF); push((v ) & 0xFFFFFFFF); } - stackMap.pushedLong(); + stackMapper.pushedLong(); } void pushLong(Register r) { assert(t, BytesPerWord == 8); push(r); sub(8, rsp); - stackMap.pushedLong(); + stackMapper.pushedLong(); } void pushLong(Register r, int32_t offset) { assert(t, BytesPerWord == 8); push(r, offset); sub(8, rsp); - stackMap.pushedLong(); + stackMapper.pushedLong(); } void pushLong(Register low, Register high) { assert(t, BytesPerWord == 4); push(high); push(low); - stackMap.pushedLong(); + stackMapper.pushedLong(); } void pushLong(Register low, int32_t lowOffset, @@ -1288,58 +1368,58 @@ class Compiler: public Assembler { assert(t, BytesPerWord == 4); push(high, highOffset); push(low, lowOffset); - stackMap.pushedLong(); + stackMapper.pushedLong(); } void popInt() { add(BytesPerWord, rsp); - stackMap.poppedInt(); + stackMapper.poppedInt(); } void popInt(Register r) { pop(r); - stackMap.poppedInt(); + stackMapper.poppedInt(); } void popInt(Register r, int32_t offset) { pop4(r, offset); - stackMap.poppedInt(); + stackMapper.poppedInt(); } void popObject(Register r) { pop(r); - stackMap.poppedObject(); + stackMapper.poppedObject(); } void popObject(Register r, int32_t offset) { pop(r, offset); - stackMap.poppedObject(); + stackMapper.poppedObject(); } void popLong() { add(BytesPerWord * 2, rsp); - stackMap.poppedLong(); + stackMapper.poppedLong(); } void popLong(Register r) { assert(t, BytesPerWord == 8); add(BytesPerWord, rsp); pop(r); - stackMap.poppedLong(); + stackMapper.poppedLong(); } void popLong(Register r, int32_t offset) { assert(t, BytesPerWord == 8); add(BytesPerWord, rsp); pop(r, offset); - stackMap.poppedLong(); + stackMapper.poppedLong(); } void popLong(Register low, Register high) { assert(t, BytesPerWord == 4); pop(low); pop(high); - stackMap.poppedLong(); + stackMapper.poppedLong(); } void popLong(Register low, int32_t lowOffset, @@ -1348,18 +1428,18 @@ class Compiler: public Assembler { assert(t, BytesPerWord == 4); pop(low, lowOffset); pop(high, highOffset); - stackMap.poppedLong(); + stackMapper.poppedLong(); } - void loadInt(uint64_t index) { + void loadInt(unsigned index) { pushInt(rbp, localOffset(t, index, method)); } - void loadObject(uint64_t index) { + void loadObject(unsigned index) { pushObject(rbp, localOffset(t, index, method)); } - void loadLong(uint64_t index) { + void loadLong(unsigned index) { if (BytesPerWord == 8) { pushLong(rbp, localOffset(t, index, method)); } else { @@ -1368,15 +1448,16 @@ class Compiler: public Assembler { } } - void storeInt(uint64_t index) { + void storeInt(unsigned index) { popInt(rbp, localOffset(t, index, method)); } - void storeObject(uint64_t index) { + void storeObject(unsigned index) { popObject(rbp, localOffset(t, index, method)); + stackMapper.storedObject(index); } - void storeLong(uint64_t index) { + void storeLong(unsigned index) { if (BytesPerWord == 8) { popLong(rbp, localOffset(t, index, method)); } else { @@ -1394,19 +1475,19 @@ class Compiler: public Assembler { case FloatField: case IntField: push(rax); - stackMap.pushedInt(); + stackMapper.pushedInt(); break; case ObjectField: push(rax); - stackMap.pushedObject(); + stackMapper.pushedObject(); break; case LongField: case DoubleField: push(rax); push(rdx); - stackMap.pushedLong(); + stackMapper.pushedLong(); break; case VoidField: @@ -1511,8 +1592,6 @@ class Compiler: public Assembler { } Compiled* compile() { - PROTECT(t, method); - object code = methodCode(t, method); PROTECT(t, code); @@ -1537,7 +1616,8 @@ class Compiler: public Assembler { lineNumberIndex = -1; } - for (unsigned ip = 0; ip < codeLength(t, code);) { + for (ip = 0; ip < codeLength(t, code);) { + stackMapper.newIp(ip); machineIPs[ip] = this->code.length(); if (lineNumberIndex >= 0) { @@ -1762,7 +1842,7 @@ class Compiler: public Assembler { mov(rbp, rsp); pop(rbp); ret(); - stackMap.unknownTerritory(this->code.length()); + stackMapper.jumped(ip); break; case arraylength: @@ -1829,7 +1909,7 @@ class Compiler: public Assembler { case dup: push(rsp, 0); - stackMap.dup(); + stackMapper.dupped(); break; case getfield: { @@ -1941,13 +2021,13 @@ class Compiler: public Assembler { case goto_: { int16_t offset = codeReadInt16(t, code, ip); jmp((ip - 3) + offset); - stackMap.unknownTerritory(this->code.length()); + stackMapper.jumped(ip, (ip - 3) + offset); } break; case goto_w: { int32_t offset = codeReadInt32(t, code, ip); jmp((ip - 5) + offset); - stackMap.unknownTerritory(this->code.length()); + stackMapper.jumped(ip, (ip - 5) + offset); } break; case i2b: @@ -2020,6 +2100,7 @@ class Compiler: public Assembler { popObject(rcx); cmp(rax, rcx); je((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_acmpne: { @@ -2029,6 +2110,7 @@ class Compiler: public Assembler { popObject(rcx); cmp(rax, rcx); jne((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmpeq: { @@ -2038,6 +2120,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); je((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmpne: { @@ -2047,6 +2130,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); jne((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmpgt: { @@ -2056,6 +2140,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); jg((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmpge: { @@ -2065,6 +2150,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); jge((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmplt: { @@ -2074,6 +2160,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); jl((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case if_icmple: { @@ -2083,6 +2170,7 @@ class Compiler: public Assembler { popInt(rcx); cmp(rax, rcx); jle((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifeq: { @@ -2099,6 +2187,7 @@ class Compiler: public Assembler { popObject(rax); cmp(0, rax); je((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifne: { @@ -2107,6 +2196,7 @@ class Compiler: public Assembler { popInt(rax); cmp(0, rax); jne((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifnonnull: { @@ -2115,6 +2205,7 @@ class Compiler: public Assembler { popObject(rax); cmp(0, rax); jne((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifgt: { @@ -2123,6 +2214,7 @@ class Compiler: public Assembler { popInt(rax); cmp(0, rax); jg((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifge: { @@ -2131,6 +2223,7 @@ class Compiler: public Assembler { popInt(rax); cmp(0, rax); jge((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case iflt: { @@ -2139,6 +2232,7 @@ class Compiler: public Assembler { popInt(rax); cmp(0, rax); jl((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case ifle: { @@ -2147,6 +2241,7 @@ class Compiler: public Assembler { popInt(rax); cmp(0, rax); jle((ip - 3) + offset); + stackMapper.branched(ip, (ip - 3) + offset); } break; case iinc: { @@ -2292,7 +2387,7 @@ class Compiler: public Assembler { mov(rbp, rsp); pop(rbp); ret(); - stackMap.unknownTerritory(this->code.length()); + stackMapper.jumped(ip); break; case istore: @@ -2328,7 +2423,7 @@ class Compiler: public Assembler { case l2i: if (BytesPerWord == 8) { popInt(); - stackMap.poppedInt(); + stackMapper.poppedInt(); } else { popInt(rax); mov(rax, rsp, 0); @@ -2647,7 +2742,7 @@ class Compiler: public Assembler { case pop_: { add(BytesPerWord, rsp); - stackMap.poppedIntOrObject(); + stackMapper.poppedIntOrObject(); } break; case putfield: { @@ -2765,7 +2860,7 @@ class Compiler: public Assembler { mov(rbp, rsp); pop(rbp); ret(); - stackMap.unknownTerritory(this->code.length()); + stackMapper.jumped(ip); break; case sipush: { @@ -2930,7 +3025,7 @@ class Compiler: public Assembler { mov(reinterpret_cast(function), rax); call(rax); - stackMap.mark(code.length()); + stackMapper.called(ip, code.length()); poolRegisterClobbered = true; } @@ -2938,13 +3033,14 @@ class Compiler: public Assembler { alignedMov(reinterpret_cast(function), rax); call(rax); - stackMap.mark(code.length()); + stackMapper.called(ip, code.length()); poolRegisterClobbered = true; } MyThread* t; object method; - StackMap stackMap; + unsigned ip; + StackMapper stackMapper; bool poolRegisterClobbered; uint32_t* machineIPs; NativeLineNumber* lineNumbers; From 69389ea8bec8f5c09019f73a2492588fba288e31 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 10 Oct 2007 16:39:40 -0600 Subject: [PATCH 2/3] more progress towards stack mapping --- src/compile.cpp | 514 ++++++++++++++++++++++++++++-------------------- src/types.def | 2 + 2 files changed, 306 insertions(+), 210 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 1b1a787c68..e970c4eaf4 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -124,6 +124,117 @@ class Buffer { unsigned minimumCapacity; }; +class StackMapper { + public: + static const uint32_t Infinity = ~static_cast(0); + + enum { + PushLong, + PushInt, + PushObject, + Duplicate, + PopLong, + PopInt, + PopObject, + PopIntOrObject, + StoreObject, + Jump, + Branch + }; + + StackMapper(Thread* t, object method): + t(t), + method(method), + index(codeSize() ? static_cast + (t->m->system->allocate(codeSize() * 4)) : 0), + log(t->m->system, 1024), + calls(t->m->system, 256) + { } + + ~StackMapper() { + if (index) { + t->m->system->free(index); + } + } + + unsigned codeSize() { + return codeLength(t, methodCode(t, method)); + } + + void newIp(unsigned javaIp) { + assert(t, javaIp < codeSize()); + index[javaIp] = log.length(); + } + + void called(unsigned nextJavaIp, unsigned nextMachineIp) { + calls.append4(nextJavaIp); + calls.append4(nextMachineIp); + } + + void pushedLong() { + log.append(PushLong); + } + + void pushedInt() { + log.append(PushInt); + } + + void pushedObject() { + log.append(PushObject); + } + + void dupped() { + log.append(Duplicate); + } + + void poppedLong() { + log.append(PopLong); + } + + void poppedInt() { + log.append(PopInt); + } + + void poppedObject() { + log.append(PopObject); + } + + void poppedIntOrObject() { + log.append(PopIntOrObject); + } + + void storedObject(unsigned index) { + log.append(StoreObject); + log.append2(index); + } + + void jumped(unsigned nextJavaIp) { + jumped(nextJavaIp, Infinity); + } + + void jumped(unsigned nextJavaIp, unsigned targetJavaIp) { + log.append(Jump); + log.append4(nextJavaIp); + log.append4(targetJavaIp); + } + + void branched(unsigned nextJavaIp, unsigned targetJavaIp) { + log.append(Branch); + log.append4(nextJavaIp); + log.append4(targetJavaIp); + } + + void writeTo(uintptr_t*) { + // todo + } + + Thread* t; + object method; + uint32_t* index; + Buffer log; + Buffer calls; +}; + class MyThread: public Thread { public: MyThread(Machine* m, object javaThread, vm::Thread* parent): @@ -208,58 +319,128 @@ compiledExceptionHandler(Thread* t, Compiled* code, unsigned index) { assert(t, index < compiledExceptionHandlerCount(t, code)); return reinterpret_cast - (compiledBody(code) + pad(compiledCodeLength(code)) + (compiledBody(code) + + pad(compiledCodeLength(code)) + pad(compiledLineNumberTableLength(code))) + index; } +inline unsigned +compiledStackMapSize(Thread*, Compiled* code) +{ + return ceiling(compiledMaxStack(code) + + compiledMaxLocals(code) + - compiledParameterFootprint(code), + BytesPerWord); +} + +inline unsigned +compiledStackMapCount(Thread* t, Compiled* code) +{ + return compiledStackMapTableLength(code) + / (compiledStackMapSize(t, code) * BytesPerWord); +} + +inline uintptr_t* +compiledStackMap(Thread* t, Compiled* code, unsigned index) +{ + assert(t, index < compiledStackMapCount(t, code)); + return reinterpret_cast + (compiledBody(code) + + pad(compiledCodeLength(code)) + + pad(compiledLineNumberTableLength(code)) + + pad(compiledExceptionHandlerTableLength(code))) + + (index * compiledStackMapSize(t, code)); +} + +inline Compiled* +makeCompiled(Thread* t, Buffer* code) +{ + Compiled* c = static_cast + (t->m->system->allocate(sizeof(Compiled) + pad(code->length()))); + + compiledMaxLocals(c) = 0; + compiledMaxStack(c) = 0; + compiledParameterFootprint(c) = 0; + compiledCodeLength(c) = code->length(); + compiledLineNumberTableLength(c) = 0; + compiledExceptionHandlerTableLength(c) = 0; + compiledStackMapTableLength(c) = 0; + + if (code->length()) { + code->copyTo(compiledCode(c)); + } + + return c; +} + inline Compiled* makeCompiled(Thread* t, object method, Buffer* code, NativeLineNumber* lineNumbers, - NativeExceptionHandler* exceptionHandlers) + NativeExceptionHandler* exceptionHandlers, + StackMapper* stackMapper) { unsigned lineNumberCount - = method and codeLineNumberTable(t, methodCode(t, method)) ? + = codeLineNumberTable(t, methodCode(t, method)) ? lineNumberTableLength (t, codeLineNumberTable(t, methodCode(t, method))) : 0; + unsigned exceptionHandlerCount - = method and codeExceptionHandlerTable(t, methodCode(t, method)) ? + = codeExceptionHandlerTable(t, methodCode(t, method)) ? exceptionHandlerTableLength (t, codeExceptionHandlerTable(t, methodCode(t, method))) : 0; + unsigned javaCodeSize = codeLength(t, methodCode(t, method)); + unsigned maxStack = codeMaxStack(t, methodCode(t, method)); + unsigned maxLocals = codeMaxLocals(t, methodCode(t, method)); + unsigned parameterFootprint = methodParameterFootprint(t, method); + + unsigned stackMapSize + = ceiling(maxStack + maxLocals - parameterFootprint, BytesPerWord); + Compiled* c = static_cast (t->m->system->allocate(sizeof(Compiled) + pad(code->length()) - + pad(lineNumberCount * sizeof(NativeLineNumber)) + + pad(lineNumberCount + * sizeof(NativeLineNumber)) + pad(exceptionHandlerCount - * sizeof(NativeExceptionHandler)))); + * sizeof(NativeExceptionHandler)) + + pad(javaCodeSize + * stackMapSize + * BytesPerWord))); - if (method) { - compiledMaxLocals(c) = codeMaxLocals(t, methodCode(t, method)); - compiledMaxStack(c) = codeMaxStack(t, methodCode(t, method)); - } else { - compiledMaxLocals(c) = 0; - compiledMaxStack(c) = 0; - } + compiledMaxLocals(c) = maxStack; + compiledMaxStack(c) = maxLocals; + compiledParameterFootprint(c) = parameterFootprint; compiledCodeLength(c) = code->length(); + compiledLineNumberTableLength(c) = lineNumberCount * sizeof(NativeLineNumber); + compiledExceptionHandlerTableLength(c) = exceptionHandlerCount * sizeof(NativeExceptionHandler); + compiledStackMapTableLength(c) = javaCodeSize * stackMapSize * BytesPerWord; + if (code->length()) { code->copyTo(compiledCode(c)); } + if (lineNumberCount) { memcpy(compiledLineNumber(t, c, 0), lineNumbers, lineNumberCount * sizeof(NativeLineNumber)); } + if (exceptionHandlerCount) { memcpy(compiledExceptionHandler(t, c, 0), exceptionHandlers, exceptionHandlerCount * sizeof(NativeExceptionHandler)); } + if (stackMapSize) { + stackMapper->writeTo(compiledStackMap(t, c, 0)); + } + return c; } @@ -1145,133 +1326,120 @@ parameterOffset(unsigned index) Compiled* caller(MyThread* t); -class StackMapper { - public: - static const uint32_t Infinity = ~static_cast(0); - - enum { - PushLong, - PushInt, - PushObject, - Duplicate, - PopLong, - PopInt, - PopObject, - PopIntOrObject, - StoreObject, - Jump, - Branch - }; - - StackMapper(Thread* t, object method): - t(t), - method(method), - index(codeSize() ? static_cast - (t->m->system->allocate(codeSize() * 4)) : 0), - log(t->m->system, 1024), - calls(t->m->system, 256) - { } - - ~StackMapper() { - if (index) { - t->m->system->free(index); - } - } - - unsigned codeSize() { - return method ? codeLength(t, methodCode(t, method)) : 0; - } - - void newIp(unsigned javaIp) { - assert(t, javaIp < codeSize()); - index[javaIp] = log.length(); - } - - void called(unsigned javaIp, unsigned machineIp) { - calls.append4(javaIp); - calls.append4(machineIp); - } - - void pushedLong() { - log.append(PushLong); - } - - void pushedInt() { - log.append(PushInt); - } - - void pushedObject() { - log.append(PushObject); - } - - void dupped() { - log.append(Duplicate); - } - - void poppedLong() { - log.append(PopLong); - } - - void poppedInt() { - log.append(PopInt); - } - - void poppedObject() { - log.append(PopObject); - } - - void poppedIntOrObject() { - log.append(PopIntOrObject); - } - - void storedObject(unsigned index) { - log.append(StoreObject); - log.append2(index); - } - - void jumped(unsigned nextJavaIp) { - jumped(nextJavaIp, Infinity); - } - - void jumped(unsigned nextJavaIp, unsigned targetJavaIp) { - log.append(Jump); - log.append4(nextJavaIp); - log.append4(targetJavaIp); - } - - void branched(unsigned nextJavaIp, unsigned targetJavaIp) { - log.append(Branch); - log.append4(nextJavaIp); - log.append4(targetJavaIp); - } - - Thread* t; - object method; - uint32_t* index; - Buffer log; - Buffer calls; -}; - class Compiler: public Assembler { public: - Compiler(MyThread* t, object method): + Compiler(MyThread* t): Assembler(t->m->system), - t(t), + t(t) + { } + + unsigned threadFrameOffset() { + return reinterpret_cast(&(t->frame)) + - reinterpret_cast(t); + } + + Compiled* compileStub() { + push(rbp); + mov(rsp, rbp); + + if (BytesPerWord == 4) { + push(rbp, FrameMethod); + push(rbp, FrameThread); + } else { + mov(rbp, FrameMethod, rsi); + mov(rbp, FrameThread, rdi); + } + + mov(reinterpret_cast(compileMethod), rbx); + callAddress(compiledCode(caller(t))); + + if (BytesPerWord == 4) { + add(BytesPerWord * 2, rsp); + } + + mov(rbp, FrameMethod, rax); + mov(rax, MethodCompiled, rax); // load compiled code + + mov(rbp, rsp); + pop(rbp); + + add(CompiledBody, rax); + jmp(rax); // call compiled code + + return finish(); + } + + Compiled* compileNativeInvoker() { + push(rbp); + mov(rsp, rbp); + + if (BytesPerWord == 4) { + push(rbp, FrameMethod); + push(rbp, FrameThread); + } else { + mov(rbp, FrameMethod, rsi); + mov(rbp, FrameThread, rdi); + } + + mov(reinterpret_cast(invokeNative), rbx); + callAddress(compiledCode(caller(t))); + + if (BytesPerWord == 4) { + add(BytesPerWord * 2, rsp); + } + + mov(rbp, rsp); + pop(rbp); + ret(); + + return finish(); + } + + Compiled* compileCaller() { + mov(rbp, FrameThread, rdi); + lea(rsp, FrameFootprint + BytesPerWord, rcx); + mov(rcx, rdi, threadFrameOffset()); // set thread frame to current + + jmp(rbx); + + return finish(); + } + + Compiled* finish() { + return makeCompiled(t, &code); + } + + void callAddress(void* function) { + mov(reinterpret_cast(function), rax); + call(rax); + } + + void callAlignedAddress(void* function) { + alignedMov(reinterpret_cast(function), rax); + call(rax); + } + + MyThread* t; +}; + +class JavaCompiler: public Compiler { + public: + JavaCompiler(MyThread* t, object method): + Compiler(t), method(method), ip(0), stackMapper(t, method), poolRegisterClobbered(true), - machineIPs(method ? static_cast + machineIPs(static_cast (t->m->system->allocate - (codeLength(t, methodCode(t, method)) * 4)) : 0), - lineNumbers(method and codeLineNumberTable(t, methodCode(t, method)) ? + (codeLength(t, methodCode(t, method)) * 4))), + lineNumbers(codeLineNumberTable(t, methodCode(t, method)) ? static_cast (t->m->system->allocate (lineNumberTableLength (t, codeLineNumberTable(t, methodCode(t, method))) * sizeof(NativeLineNumber))) : 0), - exceptionHandlers(method and codeExceptionHandlerTable - (t, methodCode(t, method)) ? + exceptionHandlers(codeExceptionHandlerTable(t, methodCode(t, method)) ? static_cast (t->m->system->allocate (exceptionHandlerTableLength @@ -1281,7 +1449,7 @@ class Compiler: public Assembler { pool(t->m->system, 256) { } - ~Compiler() { + ~JavaCompiler() { if (machineIPs) { t->m->system->free(machineIPs); } @@ -2921,80 +3089,9 @@ class Compiler: public Assembler { } } - unsigned threadFrameOffset() { - return reinterpret_cast(&(t->frame)) - - reinterpret_cast(t); - } - - Compiled* compileStub() { - push(rbp); - mov(rsp, rbp); - - if (BytesPerWord == 4) { - push(rbp, FrameMethod); - push(rbp, FrameThread); - } else { - mov(rbp, FrameMethod, rsi); - mov(rbp, FrameThread, rdi); - } - - mov(reinterpret_cast(compileMethod), rbx); - callAddress(compiledCode(caller(t))); - - if (BytesPerWord == 4) { - add(BytesPerWord * 2, rsp); - } - - mov(rbp, FrameMethod, rax); - mov(rax, MethodCompiled, rax); // load compiled code - - mov(rbp, rsp); - pop(rbp); - - add(CompiledBody, rax); - jmp(rax); // call compiled code - - return finish(); - } - - Compiled* compileNativeInvoker() { - push(rbp); - mov(rsp, rbp); - - if (BytesPerWord == 4) { - push(rbp, FrameMethod); - push(rbp, FrameThread); - } else { - mov(rbp, FrameMethod, rsi); - mov(rbp, FrameThread, rdi); - } - - mov(reinterpret_cast(invokeNative), rbx); - callAddress(compiledCode(caller(t))); - - if (BytesPerWord == 4) { - add(BytesPerWord * 2, rsp); - } - - mov(rbp, rsp); - pop(rbp); - ret(); - - return finish(); - } - - Compiled* compileCaller() { - mov(rbp, FrameThread, rdi); - lea(rsp, FrameFootprint + BytesPerWord, rcx); - mov(rcx, rdi, threadFrameOffset()); // set thread frame to current - - jmp(rbx); - - return finish(); - } - Compiled* finish() { - return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers); + return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers, + &stackMapper); } object makePool() { @@ -3022,22 +3119,19 @@ class Compiler: public Assembler { } void callAddress(void* function) { - mov(reinterpret_cast(function), rax); - call(rax); + Compiler::callAddress(function); stackMapper.called(ip, code.length()); poolRegisterClobbered = true; } void callAlignedAddress(void* function) { - alignedMov(reinterpret_cast(function), rax); - call(rax); + Compiler::callAlignedAddress(function); stackMapper.called(ip, code.length()); poolRegisterClobbered = true; } - MyThread* t; object method; unsigned ip; StackMapper stackMapper; @@ -3067,7 +3161,7 @@ compileMethod2(MyThread* t, object method) &byteArrayBody(t, methodName(t, method), 0)); } - Compiler c(t, method); + JavaCompiler c(t, method); Compiled* code = c.compile(); if (Verbose) { @@ -3358,7 +3452,7 @@ class MyProcessor: public Processor { methodStub(Thread* t) { if (methodStub_ == 0) { - Compiler c(static_cast(t), 0); + Compiler c(static_cast(t)); methodStub_ = c.compileStub(); } return methodStub_; @@ -3368,7 +3462,7 @@ class MyProcessor: public Processor { nativeInvoker(Thread* t) { if (nativeInvoker_ == 0) { - Compiler c(static_cast(t), 0); + Compiler c(static_cast(t)); nativeInvoker_ = c.compileNativeInvoker(); } return nativeInvoker_; @@ -3378,7 +3472,7 @@ class MyProcessor: public Processor { caller(Thread* t) { if (caller_ == 0) { - Compiler c(static_cast(t), 0); + Compiler c(static_cast(t)); caller_ = c.compileCaller(); } return caller_; diff --git a/src/types.def b/src/types.def index fc0656e807..322c0ac92a 100644 --- a/src/types.def +++ b/src/types.def @@ -41,9 +41,11 @@ (pod compiled (uint16_t maxLocals) (uint16_t maxStack) + (uint32_t parameterFootprint) (uint32_t codeLength) (uint32_t lineNumberTableLength) (uint32_t exceptionHandlerTableLength) + (uint32_t stackMapTableLength) (uint8_t[0] body)) (type method java/lang/reflect/Method From d5a8193614c91405625cbb713f3d207e9c4e3b63 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 11 Oct 2007 16:43:03 -0600 Subject: [PATCH 3/3] lots of work on stack mapping, plus a couple of bugfixes --- src/compile.cpp | 324 ++++++++++++++++++++++++++++++++++------- src/machine.cpp | 6 +- src/type-generator.cpp | 6 +- 3 files changed, 285 insertions(+), 51 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e970c4eaf4..614a56fb3c 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -28,6 +28,24 @@ const unsigned FrameFootprint = BytesPerWord * 3; class ArgumentList; +inline void +markBit(uintptr_t* map, unsigned i) +{ + map[wordOf(i)] |= static_cast(1) << bitOf(i); +} + +inline void +clearBit(uintptr_t* map, unsigned i) +{ + map[wordOf(i)] &= ~(static_cast(1) << bitOf(i)); +} + +inline unsigned +getBit(uintptr_t* map, unsigned i) +{ + return map[wordOf(i)] & (static_cast(1) << bitOf(i)); +} + class Buffer { public: Buffer(System* s, unsigned minimumCapacity): @@ -84,6 +102,11 @@ class Buffer { memcpy(data + offset, &v, 4); } + uint16_t get(unsigned offset) { + assert(s, offset + 1 <= position); + return data[offset]; + } + uint16_t get2(unsigned offset) { assert(s, offset + 2 <= position); uint16_t v; memcpy(&v, data + offset, 2); @@ -129,6 +152,7 @@ class StackMapper { static const uint32_t Infinity = ~static_cast(0); enum { + Call, PushLong, PushInt, PushObject, @@ -138,17 +162,20 @@ class StackMapper { PopObject, PopIntOrObject, StoreObject, + Return, Jump, - Branch + Branch, + End }; StackMapper(Thread* t, object method): t(t), method(method), + ip(-1), index(codeSize() ? static_cast (t->m->system->allocate(codeSize() * 4)) : 0), log(t->m->system, 1024), - calls(t->m->system, 256) + callCount(0) { } ~StackMapper() { @@ -161,14 +188,29 @@ class StackMapper { return codeLength(t, methodCode(t, method)); } + void end(unsigned nextIp) { + if (ip >= 0) { + log.append(End); + log.append2(nextIp); + } + ip = nextIp; + } + void newIp(unsigned javaIp) { assert(t, javaIp < codeSize()); + + end(javaIp); index[javaIp] = log.length(); } - void called(unsigned nextJavaIp, unsigned nextMachineIp) { - calls.append4(nextJavaIp); - calls.append4(nextMachineIp); + void finish() { + end(codeSize()); + } + + void called(unsigned nextMachineIp) { + log.append(Call); + log.append4(nextMachineIp); + ++ callCount; } void pushedLong() { @@ -205,34 +247,222 @@ class StackMapper { void storedObject(unsigned index) { log.append(StoreObject); - log.append2(index); + log.append2(index - parameterFootprint()); } - void jumped(unsigned nextJavaIp) { - jumped(nextJavaIp, Infinity); + void returned() { + log.append(Return); } - void jumped(unsigned nextJavaIp, unsigned targetJavaIp) { + void jumped(unsigned targetJavaIp) { log.append(Jump); - log.append4(nextJavaIp); - log.append4(targetJavaIp); + log.append2(targetJavaIp); } - void branched(unsigned nextJavaIp, unsigned targetJavaIp) { + void branched(unsigned targetJavaIp) { log.append(Branch); - log.append4(nextJavaIp); - log.append4(targetJavaIp); + log.append2(targetJavaIp); } - void writeTo(uintptr_t*) { - // todo + unsigned parameterFootprint() { + return methodParameterFootprint(t, method); + } + + unsigned localSize() { + return codeMaxLocals(t, methodCode(t, method)) + - parameterFootprint(); + } + + unsigned stackSize() { + return codeMaxStack(t, methodCode(t, method)); + } + + unsigned mapSize() { + return stackSize() + localSize(); + } + + unsigned mapSizeInWords() { + return ceiling(mapSize(), BytesPerWord); + } + + unsigned mapSizeInBytes() { + return mapSizeInWords() * BytesPerWord; + } + + unsigned callTableSize() { + return callCount * (mapSizeInBytes() + BytesPerWord); + } + + void populateCalls(uintptr_t* calls, unsigned& callIndex, uintptr_t* table, + uintptr_t* mask, uintptr_t* initialMap, + unsigned initialSp, unsigned ip) + { + uintptr_t map[mapSizeInWords()]; + memcpy(map, initialMap, mapSizeInBytes()); + + unsigned sp = initialSp; + + while (ip < codeSize()) { + if (getBit(mask, ip)) { + return; + } + + markBit(mask, ip); + memcpy(table + (ip * mapSizeInWords()), map, mapSizeInBytes()); + + unsigned i = index[ip]; + while (true) { + switch (log.get(i++)) { + case Call: { + assert(t, callIndex < callCount); + unsigned machineIp = log.get4(i); i += 4; + calls[callIndex * (mapSizeInWords() + 1)] = machineIp; + memcpy(calls + (callIndex * (mapSizeInWords() + 1)) + 1, + map, mapSizeInBytes()); + ++ callIndex; + } break; + + case PushLong: + assert(t, sp + 2 <= mapSize()); + sp += 2; + break; + + case PushInt: + assert(t, sp + 1 <= mapSize()); + ++ sp; + break; + + case PushObject: + assert(t, sp + 1 <= mapSize()); + markBit(map, sp++); + break; + + case Duplicate: + assert(t, sp + 1 <= mapSize()); + assert(t, sp - 1 >= localSize()); + if (getBit(map, sp - 1)) { + markBit(map, sp); + } + ++ sp; + break; + + case PopLong: + assert(t, sp - 2 >= localSize()); + assert(t, getBit(map, sp - 1) == 0); + assert(t, getBit(map, sp - 2) == 0); + sp -= 2; + break; + + case PopInt: + assert(t, sp - 1 >= localSize()); + assert(t, getBit(map, sp - 1) == 0); + -- sp; + break; + + case PopObject: + assert(t, sp - 1 >= localSize()); + assert(t, getBit(map, sp - 1) != 0); + clearBit(map, -- sp); + break; + + case PopIntOrObject: + assert(t, sp - 1 >= localSize()); + clearBit(map, -- sp); + break; + + case StoreObject: { + unsigned index = log.get2(i); i += 2; + assert(t, index < localSize()); + markBit(map, index); + } break; + + case Return: + ip = codeSize(); + goto loop; + + case Jump: + ip = log.get2(i); i += 2; + assert(t, ip < codeSize()); + goto loop; + + case Branch: { + unsigned target = log.get2(i); i += 2; + assert(t, target < codeSize()); + populateCalls(calls, callIndex, table, mask, map, sp, target); + } break; + + case End: + goto next; + + default: + abort(t); + } + } + + next: + ip = log.get2(i); + + loop:; + } + } + + static int compareCalls(const void* a, const void* b) { + return (*static_cast(a) > + *static_cast(b) ? 1 : -1); + } + + void writeCallTableTo(uintptr_t* calls) { + uintptr_t* table = static_cast + (t->m->system->allocate(codeSize() * mapSizeInBytes())); + + uintptr_t* mask = static_cast + (t->m->system->allocate + (ceiling(codeSize(), BytesPerWord) * BytesPerWord)); + memset(mask, 0, ceiling(codeSize(), BytesPerWord) * BytesPerWord); + + uintptr_t map[mapSizeInWords()]; + memset(map, 0, mapSizeInWords()); + + unsigned callIndex = 0; + + populateCalls(calls, callIndex, table, mask, map, localSize(), 0); + + object eht = codeExceptionHandlerTable(t, methodCode(t, method)); + if (eht) { + PROTECT(t, eht); + + for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { + ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); + + assert(t, getBit(mask, exceptionHandlerStart(eh))); + + memcpy(map, + table + (exceptionHandlerStart(eh) * mapSizeInBytes()), + mapSizeInBytes()); + + for (unsigned j = localSize() + 1; j < mapSize(); ++j) { + clearBit(map, j); + } + + markBit(map, localSize()); + + populateCalls(calls, callIndex, table, mask, map, localSize() + 1, + exceptionHandlerIp(eh)); + } + } + + t->m->system->free(mask); + + assert(t, callIndex == callCount); + qsort(calls, callCount, mapSizeInBytes() + BytesPerWord, compareCalls); } Thread* t; object method; + int ip; uint32_t* index; Buffer log; - Buffer calls; + unsigned callCount; }; class MyThread: public Thread { @@ -330,7 +560,7 @@ compiledStackMapSize(Thread*, Compiled* code) return ceiling(compiledMaxStack(code) + compiledMaxLocals(code) - compiledParameterFootprint(code), - BytesPerWord); + BytesPerWord) + 1; } inline unsigned @@ -389,7 +619,6 @@ makeCompiled(Thread* t, object method, Buffer* code, exceptionHandlerTableLength (t, codeExceptionHandlerTable(t, methodCode(t, method))) : 0; - unsigned javaCodeSize = codeLength(t, methodCode(t, method)); unsigned maxStack = codeMaxStack(t, methodCode(t, method)); unsigned maxLocals = codeMaxLocals(t, methodCode(t, method)); unsigned parameterFootprint = methodParameterFootprint(t, method); @@ -404,9 +633,7 @@ makeCompiled(Thread* t, object method, Buffer* code, * sizeof(NativeLineNumber)) + pad(exceptionHandlerCount * sizeof(NativeExceptionHandler)) - + pad(javaCodeSize - * stackMapSize - * BytesPerWord))); + + pad(stackMapper->callTableSize()))); compiledMaxLocals(c) = maxStack; compiledMaxStack(c) = maxLocals; @@ -419,7 +646,7 @@ makeCompiled(Thread* t, object method, Buffer* code, compiledExceptionHandlerTableLength(c) = exceptionHandlerCount * sizeof(NativeExceptionHandler); - compiledStackMapTableLength(c) = javaCodeSize * stackMapSize * BytesPerWord; + compiledStackMapTableLength(c) = stackMapper->callTableSize(); if (code->length()) { code->copyTo(compiledCode(c)); @@ -438,7 +665,7 @@ makeCompiled(Thread* t, object method, Buffer* code, } if (stackMapSize) { - stackMapper->writeTo(compiledStackMap(t, c, 0)); + stackMapper->writeCallTableTo(compiledStackMap(t, c, 0)); } return c; @@ -1427,7 +1654,6 @@ class JavaCompiler: public Compiler { JavaCompiler(MyThread* t, object method): Compiler(t), method(method), - ip(0), stackMapper(t, method), poolRegisterClobbered(true), machineIPs(static_cast @@ -1784,7 +2010,7 @@ class JavaCompiler: public Compiler { lineNumberIndex = -1; } - for (ip = 0; ip < codeLength(t, code);) { + for (unsigned ip = 0; ip < codeLength(t, code);) { stackMapper.newIp(ip); machineIPs[ip] = this->code.length(); @@ -2010,7 +2236,7 @@ class JavaCompiler: public Compiler { mov(rbp, rsp); pop(rbp); ret(); - stackMapper.jumped(ip); + stackMapper.returned(); break; case arraylength: @@ -2189,13 +2415,13 @@ class JavaCompiler: public Compiler { case goto_: { int16_t offset = codeReadInt16(t, code, ip); jmp((ip - 3) + offset); - stackMapper.jumped(ip, (ip - 3) + offset); + stackMapper.jumped((ip - 3) + offset); } break; case goto_w: { int32_t offset = codeReadInt32(t, code, ip); jmp((ip - 5) + offset); - stackMapper.jumped(ip, (ip - 5) + offset); + stackMapper.jumped((ip - 5) + offset); } break; case i2b: @@ -2268,7 +2494,7 @@ class JavaCompiler: public Compiler { popObject(rcx); cmp(rax, rcx); je((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_acmpne: { @@ -2278,7 +2504,7 @@ class JavaCompiler: public Compiler { popObject(rcx); cmp(rax, rcx); jne((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmpeq: { @@ -2288,7 +2514,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); je((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmpne: { @@ -2298,7 +2524,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); jne((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmpgt: { @@ -2308,7 +2534,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); jg((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmpge: { @@ -2318,7 +2544,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); jge((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmplt: { @@ -2328,7 +2554,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); jl((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case if_icmple: { @@ -2338,7 +2564,7 @@ class JavaCompiler: public Compiler { popInt(rcx); cmp(rax, rcx); jle((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifeq: { @@ -2355,7 +2581,7 @@ class JavaCompiler: public Compiler { popObject(rax); cmp(0, rax); je((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifne: { @@ -2364,7 +2590,7 @@ class JavaCompiler: public Compiler { popInt(rax); cmp(0, rax); jne((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifnonnull: { @@ -2373,7 +2599,7 @@ class JavaCompiler: public Compiler { popObject(rax); cmp(0, rax); jne((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifgt: { @@ -2382,7 +2608,7 @@ class JavaCompiler: public Compiler { popInt(rax); cmp(0, rax); jg((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifge: { @@ -2391,7 +2617,7 @@ class JavaCompiler: public Compiler { popInt(rax); cmp(0, rax); jge((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case iflt: { @@ -2400,7 +2626,7 @@ class JavaCompiler: public Compiler { popInt(rax); cmp(0, rax); jl((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case ifle: { @@ -2409,7 +2635,7 @@ class JavaCompiler: public Compiler { popInt(rax); cmp(0, rax); jle((ip - 3) + offset); - stackMapper.branched(ip, (ip - 3) + offset); + stackMapper.branched((ip - 3) + offset); } break; case iinc: { @@ -2555,7 +2781,7 @@ class JavaCompiler: public Compiler { mov(rbp, rsp); pop(rbp); ret(); - stackMapper.jumped(ip); + stackMapper.returned(); break; case istore: @@ -3028,7 +3254,7 @@ class JavaCompiler: public Compiler { mov(rbp, rsp); pop(rbp); ret(); - stackMapper.jumped(ip); + stackMapper.returned(); break; case sipush: { @@ -3090,6 +3316,7 @@ class JavaCompiler: public Compiler { } Compiled* finish() { + stackMapper.finish(); return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers, &stackMapper); } @@ -3121,19 +3348,18 @@ class JavaCompiler: public Compiler { void callAddress(void* function) { Compiler::callAddress(function); - stackMapper.called(ip, code.length()); + stackMapper.called(code.length()); poolRegisterClobbered = true; } void callAlignedAddress(void* function) { Compiler::callAlignedAddress(function); - stackMapper.called(ip, code.length()); + stackMapper.called(code.length()); poolRegisterClobbered = true; } object method; - unsigned ip; StackMapper stackMapper; bool poolRegisterClobbered; uint32_t* machineIPs; diff --git a/src/machine.cpp b/src/machine.cpp index 217ca8b350..76bd00b651 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2203,7 +2203,11 @@ resolveClass(Thread* t, object spec) class_ = hashMapFind (t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); - if (class_ == 0) { + if (class_) { + set(t, classVirtualTable(t, class_), + classVirtualTable + (t, arrayBody(t, t->m->types, Machine::JobjectType))); + } else { class_ = makeArrayClass(t, spec); } } else { diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 2a07cb66b8..6f21e3c487 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1411,8 +1411,12 @@ writeConstructors(Output* out, Object* declarations) out->write(" if (classVmFlags(t, class__) & BootstrapFlag) {\n"); out->write(" classVmFlags(t, class__) &= ~BootstrapFlag;\n"); + out->write("#ifndef NDEBUG\n"); + out->write(" object e = t->exception;\n"); + out->write(" PROTECT(t, e);\n"); + out->write("#endif\n"); out->write(" resolveClass(t, className(t, class__));\n"); - out->write(" assert(t, t->exception == 0);\n"); + out->write(" assert(t, t->exception == e);\n"); out->write(" }\n"); }