lots of work on stack mapping, plus a couple of bugfixes

This commit is contained in:
Joel Dice 2007-10-11 16:43:03 -06:00
parent 69389ea8be
commit d5a8193614
3 changed files with 285 additions and 51 deletions

View File

@ -28,6 +28,24 @@ const unsigned FrameFootprint = BytesPerWord * 3;
class ArgumentList; class ArgumentList;
inline void
markBit(uintptr_t* map, unsigned i)
{
map[wordOf(i)] |= static_cast<uintptr_t>(1) << bitOf(i);
}
inline void
clearBit(uintptr_t* map, unsigned i)
{
map[wordOf(i)] &= ~(static_cast<uintptr_t>(1) << bitOf(i));
}
inline unsigned
getBit(uintptr_t* map, unsigned i)
{
return map[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i));
}
class Buffer { class Buffer {
public: public:
Buffer(System* s, unsigned minimumCapacity): Buffer(System* s, unsigned minimumCapacity):
@ -84,6 +102,11 @@ class Buffer {
memcpy(data + offset, &v, 4); memcpy(data + offset, &v, 4);
} }
uint16_t get(unsigned offset) {
assert(s, offset + 1 <= position);
return data[offset];
}
uint16_t get2(unsigned offset) { uint16_t get2(unsigned offset) {
assert(s, offset + 2 <= position); assert(s, offset + 2 <= position);
uint16_t v; memcpy(&v, data + offset, 2); uint16_t v; memcpy(&v, data + offset, 2);
@ -129,6 +152,7 @@ class StackMapper {
static const uint32_t Infinity = ~static_cast<uint32_t>(0); static const uint32_t Infinity = ~static_cast<uint32_t>(0);
enum { enum {
Call,
PushLong, PushLong,
PushInt, PushInt,
PushObject, PushObject,
@ -138,17 +162,20 @@ class StackMapper {
PopObject, PopObject,
PopIntOrObject, PopIntOrObject,
StoreObject, StoreObject,
Return,
Jump, Jump,
Branch Branch,
End
}; };
StackMapper(Thread* t, object method): StackMapper(Thread* t, object method):
t(t), t(t),
method(method), method(method),
ip(-1),
index(codeSize() ? static_cast<uint32_t*> index(codeSize() ? static_cast<uint32_t*>
(t->m->system->allocate(codeSize() * 4)) : 0), (t->m->system->allocate(codeSize() * 4)) : 0),
log(t->m->system, 1024), log(t->m->system, 1024),
calls(t->m->system, 256) callCount(0)
{ } { }
~StackMapper() { ~StackMapper() {
@ -161,14 +188,29 @@ class StackMapper {
return codeLength(t, methodCode(t, method)); 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) { void newIp(unsigned javaIp) {
assert(t, javaIp < codeSize()); assert(t, javaIp < codeSize());
end(javaIp);
index[javaIp] = log.length(); index[javaIp] = log.length();
} }
void called(unsigned nextJavaIp, unsigned nextMachineIp) { void finish() {
calls.append4(nextJavaIp); end(codeSize());
calls.append4(nextMachineIp); }
void called(unsigned nextMachineIp) {
log.append(Call);
log.append4(nextMachineIp);
++ callCount;
} }
void pushedLong() { void pushedLong() {
@ -205,34 +247,222 @@ class StackMapper {
void storedObject(unsigned index) { void storedObject(unsigned index) {
log.append(StoreObject); log.append(StoreObject);
log.append2(index); log.append2(index - parameterFootprint());
} }
void jumped(unsigned nextJavaIp) { void returned() {
jumped(nextJavaIp, Infinity); log.append(Return);
} }
void jumped(unsigned nextJavaIp, unsigned targetJavaIp) { void jumped(unsigned targetJavaIp) {
log.append(Jump); log.append(Jump);
log.append4(nextJavaIp); log.append2(targetJavaIp);
log.append4(targetJavaIp);
} }
void branched(unsigned nextJavaIp, unsigned targetJavaIp) { void branched(unsigned targetJavaIp) {
log.append(Branch); log.append(Branch);
log.append4(nextJavaIp); log.append2(targetJavaIp);
log.append4(targetJavaIp);
} }
void writeTo(uintptr_t*) { unsigned parameterFootprint() {
// todo 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<const uintptr_t*>(a) >
*static_cast<const uintptr_t*>(b) ? 1 : -1);
}
void writeCallTableTo(uintptr_t* calls) {
uintptr_t* table = static_cast<uintptr_t*>
(t->m->system->allocate(codeSize() * mapSizeInBytes()));
uintptr_t* mask = static_cast<uintptr_t*>
(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; Thread* t;
object method; object method;
int ip;
uint32_t* index; uint32_t* index;
Buffer log; Buffer log;
Buffer calls; unsigned callCount;
}; };
class MyThread: public Thread { class MyThread: public Thread {
@ -330,7 +560,7 @@ compiledStackMapSize(Thread*, Compiled* code)
return ceiling(compiledMaxStack(code) return ceiling(compiledMaxStack(code)
+ compiledMaxLocals(code) + compiledMaxLocals(code)
- compiledParameterFootprint(code), - compiledParameterFootprint(code),
BytesPerWord); BytesPerWord) + 1;
} }
inline unsigned inline unsigned
@ -389,7 +619,6 @@ makeCompiled(Thread* t, object method, Buffer* code,
exceptionHandlerTableLength exceptionHandlerTableLength
(t, codeExceptionHandlerTable(t, methodCode(t, method))) : 0; (t, codeExceptionHandlerTable(t, methodCode(t, method))) : 0;
unsigned javaCodeSize = codeLength(t, methodCode(t, method));
unsigned maxStack = codeMaxStack(t, methodCode(t, method)); unsigned maxStack = codeMaxStack(t, methodCode(t, method));
unsigned maxLocals = codeMaxLocals(t, methodCode(t, method)); unsigned maxLocals = codeMaxLocals(t, methodCode(t, method));
unsigned parameterFootprint = methodParameterFootprint(t, method); unsigned parameterFootprint = methodParameterFootprint(t, method);
@ -404,9 +633,7 @@ makeCompiled(Thread* t, object method, Buffer* code,
* sizeof(NativeLineNumber)) * sizeof(NativeLineNumber))
+ pad(exceptionHandlerCount + pad(exceptionHandlerCount
* sizeof(NativeExceptionHandler)) * sizeof(NativeExceptionHandler))
+ pad(javaCodeSize + pad(stackMapper->callTableSize())));
* stackMapSize
* BytesPerWord)));
compiledMaxLocals(c) = maxStack; compiledMaxLocals(c) = maxStack;
compiledMaxStack(c) = maxLocals; compiledMaxStack(c) = maxLocals;
@ -419,7 +646,7 @@ makeCompiled(Thread* t, object method, Buffer* code,
compiledExceptionHandlerTableLength(c) compiledExceptionHandlerTableLength(c)
= exceptionHandlerCount * sizeof(NativeExceptionHandler); = exceptionHandlerCount * sizeof(NativeExceptionHandler);
compiledStackMapTableLength(c) = javaCodeSize * stackMapSize * BytesPerWord; compiledStackMapTableLength(c) = stackMapper->callTableSize();
if (code->length()) { if (code->length()) {
code->copyTo(compiledCode(c)); code->copyTo(compiledCode(c));
@ -438,7 +665,7 @@ makeCompiled(Thread* t, object method, Buffer* code,
} }
if (stackMapSize) { if (stackMapSize) {
stackMapper->writeTo(compiledStackMap(t, c, 0)); stackMapper->writeCallTableTo(compiledStackMap(t, c, 0));
} }
return c; return c;
@ -1427,7 +1654,6 @@ class JavaCompiler: public Compiler {
JavaCompiler(MyThread* t, object method): JavaCompiler(MyThread* t, object method):
Compiler(t), Compiler(t),
method(method), method(method),
ip(0),
stackMapper(t, method), stackMapper(t, method),
poolRegisterClobbered(true), poolRegisterClobbered(true),
machineIPs(static_cast<uint32_t*> machineIPs(static_cast<uint32_t*>
@ -1784,7 +2010,7 @@ class JavaCompiler: public Compiler {
lineNumberIndex = -1; lineNumberIndex = -1;
} }
for (ip = 0; ip < codeLength(t, code);) { for (unsigned ip = 0; ip < codeLength(t, code);) {
stackMapper.newIp(ip); stackMapper.newIp(ip);
machineIPs[ip] = this->code.length(); machineIPs[ip] = this->code.length();
@ -2010,7 +2236,7 @@ class JavaCompiler: public Compiler {
mov(rbp, rsp); mov(rbp, rsp);
pop(rbp); pop(rbp);
ret(); ret();
stackMapper.jumped(ip); stackMapper.returned();
break; break;
case arraylength: case arraylength:
@ -2189,13 +2415,13 @@ class JavaCompiler: public Compiler {
case goto_: { case goto_: {
int16_t offset = codeReadInt16(t, code, ip); int16_t offset = codeReadInt16(t, code, ip);
jmp((ip - 3) + offset); jmp((ip - 3) + offset);
stackMapper.jumped(ip, (ip - 3) + offset); stackMapper.jumped((ip - 3) + offset);
} break; } break;
case goto_w: { case goto_w: {
int32_t offset = codeReadInt32(t, code, ip); int32_t offset = codeReadInt32(t, code, ip);
jmp((ip - 5) + offset); jmp((ip - 5) + offset);
stackMapper.jumped(ip, (ip - 5) + offset); stackMapper.jumped((ip - 5) + offset);
} break; } break;
case i2b: case i2b:
@ -2268,7 +2494,7 @@ class JavaCompiler: public Compiler {
popObject(rcx); popObject(rcx);
cmp(rax, rcx); cmp(rax, rcx);
je((ip - 3) + offset); je((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_acmpne: { case if_acmpne: {
@ -2278,7 +2504,7 @@ class JavaCompiler: public Compiler {
popObject(rcx); popObject(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jne((ip - 3) + offset); jne((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmpeq: { case if_icmpeq: {
@ -2288,7 +2514,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
je((ip - 3) + offset); je((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmpne: { case if_icmpne: {
@ -2298,7 +2524,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jne((ip - 3) + offset); jne((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmpgt: { case if_icmpgt: {
@ -2308,7 +2534,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jg((ip - 3) + offset); jg((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmpge: { case if_icmpge: {
@ -2318,7 +2544,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jge((ip - 3) + offset); jge((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmplt: { case if_icmplt: {
@ -2328,7 +2554,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jl((ip - 3) + offset); jl((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case if_icmple: { case if_icmple: {
@ -2338,7 +2564,7 @@ class JavaCompiler: public Compiler {
popInt(rcx); popInt(rcx);
cmp(rax, rcx); cmp(rax, rcx);
jle((ip - 3) + offset); jle((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifeq: { case ifeq: {
@ -2355,7 +2581,7 @@ class JavaCompiler: public Compiler {
popObject(rax); popObject(rax);
cmp(0, rax); cmp(0, rax);
je((ip - 3) + offset); je((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifne: { case ifne: {
@ -2364,7 +2590,7 @@ class JavaCompiler: public Compiler {
popInt(rax); popInt(rax);
cmp(0, rax); cmp(0, rax);
jne((ip - 3) + offset); jne((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifnonnull: { case ifnonnull: {
@ -2373,7 +2599,7 @@ class JavaCompiler: public Compiler {
popObject(rax); popObject(rax);
cmp(0, rax); cmp(0, rax);
jne((ip - 3) + offset); jne((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifgt: { case ifgt: {
@ -2382,7 +2608,7 @@ class JavaCompiler: public Compiler {
popInt(rax); popInt(rax);
cmp(0, rax); cmp(0, rax);
jg((ip - 3) + offset); jg((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifge: { case ifge: {
@ -2391,7 +2617,7 @@ class JavaCompiler: public Compiler {
popInt(rax); popInt(rax);
cmp(0, rax); cmp(0, rax);
jge((ip - 3) + offset); jge((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case iflt: { case iflt: {
@ -2400,7 +2626,7 @@ class JavaCompiler: public Compiler {
popInt(rax); popInt(rax);
cmp(0, rax); cmp(0, rax);
jl((ip - 3) + offset); jl((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case ifle: { case ifle: {
@ -2409,7 +2635,7 @@ class JavaCompiler: public Compiler {
popInt(rax); popInt(rax);
cmp(0, rax); cmp(0, rax);
jle((ip - 3) + offset); jle((ip - 3) + offset);
stackMapper.branched(ip, (ip - 3) + offset); stackMapper.branched((ip - 3) + offset);
} break; } break;
case iinc: { case iinc: {
@ -2555,7 +2781,7 @@ class JavaCompiler: public Compiler {
mov(rbp, rsp); mov(rbp, rsp);
pop(rbp); pop(rbp);
ret(); ret();
stackMapper.jumped(ip); stackMapper.returned();
break; break;
case istore: case istore:
@ -3028,7 +3254,7 @@ class JavaCompiler: public Compiler {
mov(rbp, rsp); mov(rbp, rsp);
pop(rbp); pop(rbp);
ret(); ret();
stackMapper.jumped(ip); stackMapper.returned();
break; break;
case sipush: { case sipush: {
@ -3090,6 +3316,7 @@ class JavaCompiler: public Compiler {
} }
Compiled* finish() { Compiled* finish() {
stackMapper.finish();
return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers, return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers,
&stackMapper); &stackMapper);
} }
@ -3121,19 +3348,18 @@ class JavaCompiler: public Compiler {
void callAddress(void* function) { void callAddress(void* function) {
Compiler::callAddress(function); Compiler::callAddress(function);
stackMapper.called(ip, code.length()); stackMapper.called(code.length());
poolRegisterClobbered = true; poolRegisterClobbered = true;
} }
void callAlignedAddress(void* function) { void callAlignedAddress(void* function) {
Compiler::callAlignedAddress(function); Compiler::callAlignedAddress(function);
stackMapper.called(ip, code.length()); stackMapper.called(code.length());
poolRegisterClobbered = true; poolRegisterClobbered = true;
} }
object method; object method;
unsigned ip;
StackMapper stackMapper; StackMapper stackMapper;
bool poolRegisterClobbered; bool poolRegisterClobbered;
uint32_t* machineIPs; uint32_t* machineIPs;

View File

@ -2203,7 +2203,11 @@ resolveClass(Thread* t, object spec)
class_ = hashMapFind class_ = hashMapFind
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); (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); class_ = makeArrayClass(t, spec);
} }
} else { } else {

View File

@ -1411,8 +1411,12 @@ writeConstructors(Output* out, Object* declarations)
out->write(" if (classVmFlags(t, class__) & BootstrapFlag) {\n"); out->write(" if (classVmFlags(t, class__) & BootstrapFlag) {\n");
out->write(" 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(" 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"); out->write(" }\n");
} }