From 2f3f97d5506d537c9690d06daceec4e2412fb000 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 26 Sep 2007 17:23:03 -0600 Subject: [PATCH] clean up compile.cpp and support both x86_64 and i386; further refactoring to support JIT --- classpath/java/lang/reflect/Method.java | 14 +- makefile | 6 +- src/common.h | 16 - src/compile.cpp | 674 +++++++++++++++++++----- src/interpret.cpp | 260 ++++----- src/machine.cpp | 136 ++--- src/machine.h | 32 +- src/process.h | 137 +++++ src/processor.h | 6 + src/system.cpp | 20 +- src/types.def | 4 +- src/vmInvoke.S | 102 ++++ test/Instructions.java | 12 + 13 files changed, 964 insertions(+), 455 deletions(-) create mode 100644 src/process.h create mode 100644 src/vmInvoke.S diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 578d2fda6b..051309c05c 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -2,8 +2,9 @@ package java.lang.reflect; public class Method extends AccessibleObject implements Member { private byte vmFlags; + private byte returnCode; private byte parameterCount; - private short parameterFootprint; + private byte parameterFootprint; private short flags; private short offset; private byte[] name; @@ -45,9 +46,6 @@ public class Method extends AccessibleObject implements Member { public Class[] getParameterTypes() { int count = parameterCount; - if ((flags & Modifier.STATIC) == 0) { - -- count; - } Class[] types = new Class[count]; int index = 0; @@ -91,14 +89,8 @@ public class Method extends AccessibleObject implements Member { public Object invoke(Object instance, Object ... arguments) throws InvocationTargetException, IllegalAccessException { - if ((flags & Modifier.STATIC) != 0) { + if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) { if (arguments.length == parameterCount) { - return invoke(this, instance, arguments); - } else { - throw new ArrayIndexOutOfBoundsException(); - } - } else if (class_.isInstance(instance)) { - if (arguments.length == parameterCount - 1) { return invoke(this, instance, arguments); } else { throw new ArrayIndexOutOfBoundsException(); diff --git a/makefile b/makefile index 7f7b427d58..d0b19b42a1 100644 --- a/makefile +++ b/makefile @@ -111,11 +111,13 @@ interpreter-sources = \ $(src)/jnienv.cpp \ $(src)/main.cpp +interpreter-asm-sources = $(src)/vmInvoke.S + ifeq ($(arch),i386) - interpreter-asm-sources = $(src)/cdecl.S + interpreter-asm-sources += $(src)/cdecl.S endif ifeq ($(arch),x86_64) - interpreter-asm-sources = $(src)/amd64.S + interpreter-asm-sources += $(src)/amd64.S endif interpreter-cpp-objects = \ diff --git a/src/common.h b/src/common.h index 9a6f13cf8f..c1011c6cd7 100644 --- a/src/common.h +++ b/src/common.h @@ -45,22 +45,6 @@ inline void* operator new(size_t, void* p) throw() { return p; } -#ifdef __i386__ - -extern "C" uint64_t -cdeclCall(void* function, void* stack, unsigned stackSize, - unsigned returnType); - -#elif defined __x86_64__ - -extern "C" uint64_t -amd64Call(void* function, void* stack, unsigned stackSize, - void* gprTable, void* sseTable, unsigned returnType); - -#else -# error unsupported platform -#endif - namespace vm { const unsigned BytesPerWord = sizeof(uintptr_t); diff --git a/src/compile.cpp b/src/compile.cpp index e4dcbefb2c..f11985c581 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2,15 +2,21 @@ #include "system.h" #include "constants.h" #include "machine.h" +#include "processor.h" +#include "process.h" using namespace vm; +extern "C" uint64_t +vmInvoke(void* function, void* stack, unsigned stackSize, + unsigned returnType); + namespace { -const unsigned FrameThread = 8; -const unsigned FrameMethod = 12; -const unsigned FrameNext = 16; -const unsigned FrameFootprint = 12; +const unsigned FrameThread = BytesPerWord * 2; +const unsigned FrameMethod = FrameThread + BytesPerWord; +const unsigned FrameNext = FrameNext + BytesPerWord; +const unsigned FrameFootprint = BytesPerWord * 3; class Rope { public: @@ -56,7 +62,7 @@ class Rope { rear->data[position++] = v; } - void append4(uint32_t v) { + void appendAddress(uintptr_t v) { append((v >> 0) & 0xFF); append((v >> 8) & 0xFF); append((v >> 16) & 0xFF); @@ -110,178 +116,241 @@ class Assembler { public: class Snapshot { public: - Rope rope; + Rope code; unsigned ip; }; static const unsigned Capacity = 8; - Label(): + Label(Assembler* a): + code(&(a->code)), unresolvedCount(0), mark_(-1) { } - void reference(Rope* r, unsigned ip) { + void reference(unsigned ip) { if (mark_ == -1) { - expect(r->s, unresolvedCount < Capacity); - unresolved[unresolvedCount].rope = *r; + expect(code->s, unresolvedCount < Capacity); + unresolved[unresolvedCount].code = *code; unresolved[unresolvedCount].ip = ip; ++ unresolvedCount; - r->append4(0); + code->appendAddress(0); } else { - r->append4(mark_ - ip); + code->appendAddress(mark_ - ip); } } - void mark(Rope* r) { - mark_ = r->length(); + void mark() { + mark_ = code->length(); for (unsigned i = 0; i < unresolvedCount; ++i) { - unresolved[i].rope.append4(mark_ - unresolved[i].ip); + unresolved[i].code.appendAddress(mark_ - unresolved[i].ip); } } + Rope* code; Snapshot unresolved[Capacity]; unsigned unresolvedCount; int mark_; }; enum Register { - eax = 0, - ecx = 1, - edx = 2, - ebx = 3, - esp = 4, - ebp = 5 + rax = 0, + rcx = 1, + rdx = 2, + rbx = 3, + rsp = 4, + rbp = 5, + rsi = 6, + rdi = 7 }; Assembler(System* s): - r(s) + code(s) { } + void rex() { + if (BytesPerWord == 8) { + code.append(0x48); + } + } + void mov(Register src, Register dst) { - r.append(0x89); - r.append(0xc0 | (src << 3) | dst); + rex(); + code.append(0x89); + code.append(0xc0 | (src << 3) | dst); } void mov(Register src, int srcOffset, Register dst) { - r.append(0x8b); + rex(); + code.append(0x8b); if (srcOffset) { - r.append(0x40 | (dst << 3) | src); - r.append(srcOffset); + assert(code.s, (srcOffset & 0xFFFFFF00) == 0); // todo + + code.append(0x40 | (dst << 3) | src); + code.append(srcOffset); } else { - r.append((dst << 3) | src); + code.append((dst << 3) | src); } } void mov(Register src, Register dst, int dstOffset) { - r.append(0x89); + rex(); + code.append(0x89); if (dstOffset) { - r.append(0x40 | (src << 3) | dst); - r.append(dstOffset); + assert(code.s, (dstOffset & 0xFFFFFF00) == 0); // todo + + code.append(0x40 | (src << 3) | dst); + code.append(dstOffset); } else { - r.append((src << 3) | dst); + code.append((src << 3) | dst); } } - void mov(uintptr_t src, Register dst) { - r.append(0xb8 | dst); - r.append4(src); + void mov(uintptr_t v, Register dst) { + rex(); + code.append(0xb8 | dst); + code.appendAddress(v); + } + + void alignedMov(uintptr_t v, Register dst) { + while ((code.length() + (BytesPerWord == 8 ? 2 : 1)) % BytesPerWord) { + nop(); + } + rex(); + code.append(0xb8 | dst); + code.appendAddress(v); + } + + void nop() { + code.append(0x90); } void push(Register reg) { - r.append(0x50 | reg); + code.append(0x50 | reg); } void push(Register reg, int offset) { - r.append(0xff); - r.append(0x70 | reg); - r.append(offset); + assert(code.s, (offset & 0xFFFFFF00) == 0); // todo + + code.append(0xff); + code.append(0x70 | reg); + code.append(offset); } void push(int v) { - r.append(0x6a); - r.append(v); + assert(code.s, (v & 0xFFFFFF00) == 0); // todo + + code.append(0x6a); + code.append(v); } void pop(Register dst) { - r.append(0x58 | dst); + code.append(0x58 | dst); } void pop(Register dst, int offset) { - r.append(0x8f); - r.append(0x40 | dst); - r.append(offset); + assert(code.s, (offset & 0xFFFFFF00) == 0); // todo + + code.append(0x8f); + code.append(0x40 | dst); + code.append(offset); } void add(Register src, Register dst) { - r.append(0x01); - r.append(0xc0 | (src << 3) | dst); + rex(); + code.append(0x01); + code.append(0xc0 | (src << 3) | dst); } - void add(int src, Register dst) { - r.append(0x83); - r.append(0xc0 | dst); - r.append(src); + void add(int v, Register dst) { + assert(code.s, (v & 0xFFFFFF00) == 0); // todo + + rex(); + code.append(0x83); + code.append(0xc0 | dst); + code.append(v); } void sub(Register src, Register dst) { - r.append(0x29); - r.append(0xc0 | (src << 3) | dst); + rex(); + code.append(0x29); + code.append(0xc0 | (src << 3) | dst); } - void sub(int src, Register dst) { - r.append(0x83); - r.append(0xe8 | dst); - r.append(src); + void sub(int v, Register dst) { + assert(code.s, (v & 0xFFFFFF00) == 0); // todo + + rex(); + code.append(0x83); + code.append(0xe8 | dst); + code.append(v); } void or_(Register src, Register dst) { - r.append(0x09); - r.append(0xc0 | (src << 3) | dst); + rex(); + code.append(0x09); + code.append(0xc0 | (src << 3) | dst); } - void or_(int src, Register dst) { - r.append(0x83); - r.append(0xc8 | dst); - r.append(src); + void or_(int v, Register dst) { + assert(code.s, (v & 0xFFFFFF00) == 0); // todo + + rex(); + code.append(0x83); + code.append(0xc8 | dst); + code.append(v); } void and_(Register src, Register dst) { - r.append(0x21); - r.append(0xc0 | (src << 3) | dst); + rex(); + code.append(0x21); + code.append(0xc0 | (src << 3) | dst); } - void and_(int src, Register dst) { - r.append(0x83); - r.append(0xe0 | dst); - r.append(src); + void and_(int v, Register dst) { + assert(code.s, (v & 0xFFFFFF00) == 0); // todo + + rex(); + code.append(0x83); + code.append(0xe0 | dst); + code.append(v); } void ret() { - r.append(0xc3); + code.append(0xc3); } void jmp(Label& label) { - r.append(0xE9); - label.reference(&r, r.length() + 4); + code.append(0xE9); + label.reference(code.length() + BytesPerWord); } void jmp(Register reg) { - r.append(0xff); - r.append(0xe0 | reg); + code.append(0xff); + code.append(0xe0 | reg); } - void jmp(Register reg, int offset) { - r.append(0xff); - r.append(0x60 | reg); - r.append(offset); +// void jmp(Register reg, int offset) { +// code.append(0xff); +// code.append(0x60 | reg); +// code.append(offset); +// } + + void jz(Label& label) { + code.append(0x0F); + code.append(0x84); + label.reference(code.length() + BytesPerWord); + } + + void je(Label& label) { + jz(label); } void jnz(Label& label) { - r.append(0x0F); - r.append(0x85); - label.reference(&r, r.length() + 4); + code.append(0x0F); + code.append(0x85); + label.reference(code.length() + BytesPerWord); } void jne(Label& label) { @@ -289,30 +358,30 @@ class Assembler { } void cmp(int v, Register reg) { - r.append(0x83); - r.append(0xf8 | reg); - r.append(v); + code.append(0x83); + code.append(0xf8 | reg); + code.append(v); } void call(Register reg) { - r.append(0xff); - r.append(0xd0 | reg); + code.append(0xff); + code.append(0xd0 | reg); } - Rope r; + Rope code; }; void -compileMethod(Thread* t, object method); +compileMethod(MyThread* t, object method); int localOffset(int v, int parameterFootprint) { - v *= 4; + v *= BytesPerWord; if (v < parameterFootprint) { - return v + 8 + FrameFootprint; + return v + (BytesPerWord * 2) + FrameFootprint; } else { - return -(v + 4 - parameterFootprint); + return -(v + BytesPerWord - parameterFootprint); } } @@ -322,23 +391,133 @@ class Compiler: public Assembler { Assembler(s) { } + void pushReturnValue(Thread* t, unsigned code) { + switch (code) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + case ObjectField: + push(rax); + break; + + case LongField: + case DoubleField: + push(rax); + push(rdx); + break; + + case VoidField: + break; + + default: + abort(t); + } + } + void compile(Thread* t, object method) { - push(ebp); - mov(esp, ebp); + PROTECT(t, method); + + push(rbp); + mov(rsp, rbp); object code = methodCode(t, method); - unsigned parameterFootprint = methodParameterFootprint(t, method) * 4; + PROTECT(t, code); + + unsigned parameterFootprint + = methodParameterFootprint(t, method) * BytesPerWord; + + unsigned localFootprint = codeMaxLocals(t, code) * BytesPerWord; // reserve space for local variables - sub((codeMaxLocals(t, code) * 4) - parameterFootprint, esp); + sub(localFootprint - parameterFootprint, rsp); - for (unsigned i = 0; i < codeLength(t, code);) { - switch (codeBody(t, code, i++)) { + for (unsigned ip = 0; ip < codeLength(t, code);) { + unsigned instruction = codeBody(t, code, ip++); + + switch (instruction) { + case areturn: + pop(rax); + mov(rbp, rsp); + pop(rbp); + ret(); + break; + + case dup: + push(rsp, 4); + break; + + case getstatic: { + uint16_t index = codeReadInt16(t, code, ip); + + object field = resolveField(t, codePool(t, code), index - 1); + if (UNLIKELY(t->exception)) return; + PROTECT(t, field); + + initClass(t, fieldClass(t, field)); + if (UNLIKELY(t->exception)) return; + + object table = classStaticTable(t, fieldClass(t, field)); + + mov(reinterpret_cast(table), rax); + add(fieldOffset(t, field), rax); + + switch (fieldCode(t, field)) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: { + Label zero(this); + Label next(this); + + cmp(0, rax); + je(zero); + + push(rax, IntValue); + jmp(next); + + zero.mark(); + push(0); + + next.mark(); + } break; + + case DoubleField: + case LongField: { + Label zero(this); + Label next(this); + + cmp(0, rax); + je(zero); + + push(rax, LongValue); + push(rax, LongValue + 4); + jmp(next); + + zero.mark(); + push(0); + push(0); + + next.mark(); + } break; + + case ObjectField: { + push(rax); + } break; + + default: abort(t); + } + } break; + case iadd: - pop(eax); - pop(edx); - add(eax, edx); - push(edx); + pop(rax); + pop(rdx); + add(rax, rdx); + push(rdx); break; case iconst_m1: @@ -371,47 +550,139 @@ class Compiler: public Assembler { case iload_0: case fload_0: - push(ebp, localOffset(0, parameterFootprint)); + push(rbp, localOffset(0, parameterFootprint)); break; case iload_1: case fload_1: - push(ebp, localOffset(1, parameterFootprint)); + push(rbp, localOffset(1, parameterFootprint)); break; case iload_2: case fload_2: - push(ebp, localOffset(2, parameterFootprint)); + push(rbp, localOffset(2, parameterFootprint)); break; case iload_3: case fload_3: - push(ebp, localOffset(3, parameterFootprint)); + push(rbp, localOffset(3, parameterFootprint)); break; + case invokespecial: { + uint16_t index = codeReadInt16(t, code, ip); + + object target = resolveMethod(t, codePool(t, code), index - 1); + if (UNLIKELY(t->exception)) return; + + object class_ = methodClass(t, method); + if (isSpecialMethod(t, target, class_)) { + class_ = classSuper(t, class_); + target = findMethod(t, target, class_); + } + + unsigned footprint = FrameFootprint + + methodParameterFootprint(t, target) * BytesPerWord; + + uint8_t* code = &compiledBody(t, methodCompiled(t, target), 0); + + push(rbp, 0); + push(reinterpret_cast(target)); + push(rbp, FrameThread); + + alignedMov(reinterpret_cast(code), rax); + call(rax); + + add(footprint, rsp); // pop arguments + + pushReturnValue(t, methodReturnCode(t, method)); + } break; + + case invokevirtual: { + uint16_t index = codeReadInt16(t, code, ip); + + object target = resolveMethod(t, codePool(t, code), index - 1); + if (UNLIKELY(t->exception)) return; + + unsigned footprint = FrameFootprint + + methodParameterFootprint(t, target) * BytesPerWord; + + unsigned offset = ArrayBody + (methodOffset(t, target) * BytesPerWord); + + push(rbp, 0); + push(reinterpret_cast(target)); + push(rbp, FrameThread); + + mov(rsp, BytesPerWord * 3, rax); // load target object + mov(rax, 0, rax); // load target class + mov(rax, ClassVirtualTable, rax); // load vtable + mov(rax, offset, rax); // load method + mov(rax, MethodCompiled, rax); // load compiled code + add(CompiledBody, rax); + call(rax); // call compiled code + + add(footprint, rsp); // pop arguments + + pushReturnValue(t, methodReturnCode(t, method)); + } break; + case istore_0: case fstore_0: - pop(ebp, localOffset(0, parameterFootprint)); + pop(rbp, localOffset(0, parameterFootprint)); break; case istore_1: case fstore_1: - pop(ebp, localOffset(1, parameterFootprint)); + pop(rbp, localOffset(1, parameterFootprint)); break; case istore_2: case fstore_2: - pop(ebp, localOffset(2, parameterFootprint)); + pop(rbp, localOffset(2, parameterFootprint)); break; case istore_3: case fstore_3: - pop(ebp, localOffset(3, parameterFootprint)); + pop(rbp, localOffset(3, parameterFootprint)); break; + case ldc: + case ldc_w: { + uint16_t index; + + if (instruction == ldc) { + index = codeBody(t, code, ip++); + } else { + uint8_t index1 = codeBody(t, code, ip++); + uint8_t index2 = codeBody(t, code, ip++); + index = (index1 << 8) | index2; + } + + object v = arrayBody(t, codePool(t, code), index - 1); + + if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::IntType)) { + push(intValue(t, v)); + } else if (objectClass(t, v) + == arrayBody(t, t->m->types, Machine::FloatType)) + { + push(floatValue(t, v)); + } else if (objectClass(t, v) + == arrayBody(t, t->m->types, Machine::StringType)) + { + push(reinterpret_cast(v)); + } else { + object class_ = resolveClass(t, codePool(t, code), index - 1); + + push(reinterpret_cast(class_)); + } + } break; + + case pop_: { + add(BytesPerWord, rsp); + } break; + case return_: - mov(ebp, esp); - pop(ebp); + mov(rbp, rsp); + pop(rbp); ret(); break; @@ -425,31 +696,40 @@ class Compiler: public Assembler { unsigned frameOffset = reinterpret_cast(&(t->frame)) - reinterpret_cast(t); - push(ebp); - mov(esp, ebp); + push(rbp); + mov(rsp, rbp); - mov(ebp, FrameThread, eax); - mov(ebp, eax, frameOffset); // set thread frame to current + mov(rbp, FrameThread, rax); + mov(rbp, rax, frameOffset); // set thread frame to current - push(ebp, FrameMethod); - push(ebp, FrameThread); - mov(reinterpret_cast(compileMethod), eax); - call(eax); - add(8, esp); + if (BytesPerWord == 4) { + push(rbp, FrameMethod); + push(rbp, FrameThread); + } else { + mov(rbp, FrameMethod, rsi); + mov(rbp, FrameThread, rdi); + } - mov(ebp, FrameMethod, eax); - mov(eax, MethodCompiled, eax); // load compiled code + mov(reinterpret_cast(compileMethod), rax); + call(rax); - mov(ebp, esp); - pop(ebp); + 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, eax); - jmp(eax); // call compiled code + add(CompiledBody, rax); + jmp(rax); // call compiled code } }; void -compileMethod(Thread* t, object method) +compileMethod2(MyThread* t, object method) { if (methodCompiled(t, method) == t->m->processor->methodStub(t)) { PROTECT(t, method); @@ -460,22 +740,74 @@ compileMethod(Thread* t, object method) Compiler c(t->m->system); c.compile(t, method); - object compiled = makeCompiled(t, 0, c.r.length(), false); - c.r.copyTo(&compiledBody(t, compiled, 0)); + object compiled = makeCompiled(t, 0, c.code.length(), false); + if (UNLIKELY(t->exception)) return; + + c.code.copyTo(&compiledBody(t, compiled, 0)); set(t, methodCompiled(t, method), compiled); } } } +void +updateCaller(MyThread* t, object method) +{ + uintptr_t stub = reinterpret_cast + (&compiledBody(t, t->m->processor->methodStub(t), 0)); + + Assembler a(t->m->system); + a.mov(stub, Assembler::rax); + unsigned offset = a.code.length() - BytesPerWord; + + a.call(Assembler::rax); + + uint8_t* caller = static_cast(t->frame)[1] - a.code.length(); + if (memcmp(a.code.front->data, caller, a.code.length()) == 0) { + // it's a direct call - update caller to point to new code + + // address must be aligned on a word boundary for this write to + // be atomic + assert(t, reinterpret_cast(caller + offset) + % BytesPerWord == 0); + + *reinterpret_cast(caller + offset) + = &compiledBody(t, methodCompiled(t, method), 0); + } +} + +void +unwind(Thread* t) +{ + // todo + abort(t); +} + +void +compileMethod(MyThread* t, object method) +{ + if (methodVirtual(t, method)) { + object this_ = static_cast + (t->frame)[2 + (FrameFootprint / BytesPerWord)]; + method = findMethod(t, method, objectClass(t, this_)); + } + + compileMethod2(t, method); + if (UNLIKELY(t->exception)) { + unwind(t); + } else { + updateCaller(t, method); + } +} + object compileStub(Thread* t) { Compiler c(t->m->system); c.compileStub(static_cast(t)); - object stub = makeCompiled(t, 0, c.r.length(), false); - c.r.copyTo(&compiledBody(t, stub, 0)); + object stub = makeCompiled(t, 0, c.code.length(), false); + c.code.copyTo(&compiledBody(t, stub, 0)); return stub; } @@ -647,15 +979,12 @@ invoke(Thread* thread, object method, ArgumentList* arguments) arguments->array[1] = reinterpret_cast(method); - const char* s = reinterpret_cast - (&byteArrayBody(t, methodSpec(t, method), 0)); - while (*s and *s != ')') ++s; - unsigned returnCode = fieldCode(t, s[1]); + unsigned returnCode = methodReturnCode(t, method); unsigned returnType = fieldType(t, returnCode); - uint64_t result = cdeclCall + uint64_t result = vmInvoke (&compiledBody(t, methodCompiled(t, method), 0), arguments->array, - arguments->position * 4, returnType); + arguments->position * BytesPerWord, returnType); object r; switch (returnCode) { @@ -711,6 +1040,71 @@ class MyProcessor: public Processor { return stub; } + virtual unsigned + parameterFootprint(vm::Thread*, const char* s, bool static_) + { + unsigned footprint = 0; + ++ s; // skip '(' + while (*s and *s != ')') { + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + case '[': + while (*s == '[') ++ s; + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + default: + ++ s; + break; + } + break; + + case 'J': + case 'D': + ++ s; + if (BytesPerWord == 4) { + ++ footprint; + } + break; + + default: + ++ s; + break; + } + + ++ footprint; + } + + if (not static_) { + ++ footprint; + } + return footprint; + } + + virtual void + initClass(Thread* t, object c) + { + PROTECT(t, c); + + ACQUIRE(t, t->m->classLock); + if (classVmFlags(t, c) & NeedInitFlag + and (classVmFlags(t, c) & InitFlag) == 0) + { + invoke(t, classInitializer(t, c), 0); + if (t->exception) { + t->exception = makeExceptionInInitializerError(t, t->exception); + } + classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag); + } + } + virtual void visitObjects(Thread* t, Heap::Visitor*) { @@ -770,7 +1164,7 @@ class MyProcessor: public Processor { const char* spec = reinterpret_cast (&byteArrayBody(t, methodSpec(t, method), 0)); - unsigned size = methodParameterCount(t, method) * 2; + unsigned size = methodParameterFootprint(t, method) + FrameFootprint; uintptr_t array[size]; bool objectMask[size]; ArgumentList list(t, array, objectMask, this_, spec, arguments); @@ -790,7 +1184,7 @@ class MyProcessor: public Processor { const char* spec = reinterpret_cast (&byteArrayBody(t, methodSpec(t, method), 0)); - unsigned size = methodParameterCount(t, method) * 2; + unsigned size = methodParameterFootprint(t, method) + FrameFootprint; uintptr_t array[size]; bool objectMask[size]; ArgumentList list @@ -806,7 +1200,7 @@ class MyProcessor: public Processor { assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); - unsigned size = parameterCount(methodSpec) * 2; + unsigned size = parameterFootprint(t, methodSpec, false) + FrameFootprint; uintptr_t array[size]; bool objectMask[size]; ArgumentList list diff --git a/src/interpret.cpp b/src/interpret.cpp index 3b51924565..10f43551ad 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -3,6 +3,7 @@ #include "constants.h" #include "machine.h" #include "processor.h" +#include "process.h" using namespace vm; @@ -375,119 +376,16 @@ findInterfaceMethod(Thread* t, object method, object class_) abort(t); } -inline object -findMethod(Thread* t, object method, object class_) -{ - return arrayBody(t, classVirtualTable(t, class_), - methodOffset(t, method)); -} - -bool -isSuperclass(Thread* t, object class_, object base) -{ - for (object oc = classSuper(t, base); oc; oc = classSuper(t, oc)) { - if (oc == class_) { - return true; - } - } - return false; -} - -inline bool -isSpecialMethod(Thread* t, object method, object class_) -{ - return (classFlags(t, class_) & ACC_SUPER) - and strcmp(reinterpret_cast(""), - &byteArrayBody(t, methodName(t, method), 0)) != 0 - and isSuperclass(t, methodClass(t, method), class_); -} - -inline object -resolveClass(Thread* t, object pool, unsigned index) -{ - object o = arrayBody(t, pool, index); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { - PROTECT(t, pool); - - o = resolveClass(t, o); - if (UNLIKELY(t->exception)) return 0; - - set(t, arrayBody(t, pool, index), o); - } - return o; -} - -inline object -resolveClass(Thread* t, object container, - object& (*class_)(vm::Thread*, object)) -{ - object o = class_(t, container); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { - PROTECT(t, container); - - o = resolveClass(t, o); - if (UNLIKELY(t->exception)) return 0; - - set(t, class_(t, container), o); - } - return o; -} - -inline object -resolve(Thread* t, object pool, unsigned index, - object (*find)(vm::Thread*, object, object, object), - object (*makeError)(vm::Thread*, object)) -{ - object o = arrayBody(t, pool, index); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) - { - PROTECT(t, pool); - - object reference = o; - PROTECT(t, reference); - - object class_ = resolveClass(t, o, referenceClass); - if (UNLIKELY(t->exception)) return 0; - - o = findInHierarchy - (t, class_, referenceName(t, reference), referenceSpec(t, reference), - find, makeError); - if (UNLIKELY(t->exception)) return 0; - - set(t, arrayBody(t, pool, index), o); - } - - return o; -} - -inline object -resolveField(Thread* t, object pool, unsigned index) -{ - return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError); -} - -inline object -resolveMethod(Thread* t, object pool, unsigned index) -{ - return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError); -} - object makeNativeMethodData(Thread* t, object method, void* function) { PROTECT(t, method); - unsigned count = methodParameterCount(t, method) + 1; - if (methodFlags(t, method) & ACC_STATIC) { - ++ count; - } + unsigned count = methodParameterCount(t, method) + 2; object data = makeNativeMethodData(t, function, 0, // argument table size - 0, // return code, count, false); @@ -534,7 +432,6 @@ makeNativeMethodData(Thread* t, object method, void* function) } nativeMethodDataArgumentTableSize(t, data) = argumentTableSize; - nativeMethodDataReturnCode(t, data) = fieldCode(t, s[1]); return data; } @@ -598,10 +495,7 @@ invokeNative(Thread* t, object method) pushFrame(t, method); - unsigned count = methodParameterCount(t, method); - if (methodFlags(t, method) & ACC_STATIC) { - ++ count; - } + unsigned count = nativeMethodDataLength(t, data) - 1; unsigned size = nativeMethodDataArgumentTableSize(t, data); uintptr_t args[size / BytesPerWord]; @@ -648,7 +542,7 @@ invokeNative(Thread* t, object method) } } - unsigned returnCode = nativeMethodDataReturnCode(t, data); + unsigned returnCode = methodReturnCode(t, method); unsigned returnType = fieldType(t, returnCode); void* function = nativeMethodDataFunction(t, data); @@ -721,7 +615,7 @@ invokeNative(Thread* t, object method) default: abort(t); - }; + } return returnCode; } @@ -754,24 +648,6 @@ classInit(Thread* t, object class_, unsigned ipOffset) } } -inline int16_t -codeReadInt16(Thread* t, unsigned& i) -{ - uint8_t v1 = codeBody(t, t->code, i++); - uint8_t v2 = codeBody(t, t->code, i++); - return ((v1 << 8) | v2); -} - -inline int32_t -codeReadInt32(Thread* t, unsigned& i) -{ - uint8_t v1 = codeBody(t, t->code, i++); - uint8_t v2 = codeBody(t, t->code, i++); - uint8_t v3 = codeBody(t, t->code, i++); - uint8_t v4 = codeBody(t, t->code, i++); - return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); -} - inline void store(Thread* t, unsigned index) { @@ -929,7 +805,7 @@ interpret(Thread* t) int32_t count = popInt(t); if (LIKELY(count >= 0)) { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -1114,7 +990,7 @@ interpret(Thread* t) } goto loop; case checkcast: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); if (peekObject(t, sp - 1)) { object class_ = resolveClass(t, codePool(t, code), index - 1); @@ -1443,7 +1319,7 @@ interpret(Thread* t) case getfield: { if (LIKELY(peekObject(t, sp - 1))) { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -1485,7 +1361,7 @@ interpret(Thread* t) } goto loop; case getstatic: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -1520,12 +1396,12 @@ interpret(Thread* t) } goto loop; case goto_: { - int16_t offset = codeReadInt16(t, ip); + int16_t offset = codeReadInt16(t, code, ip); ip = (ip - 3) + offset; } goto loop; case goto_w: { - int32_t offset = codeReadInt32(t, ip); + int32_t offset = codeReadInt32(t, code, ip); ip = (ip - 5) + offset; } goto loop; @@ -1882,7 +1758,7 @@ interpret(Thread* t) } goto loop; case invokeinterface: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); ip += 2; @@ -1901,7 +1777,7 @@ interpret(Thread* t) } goto loop; case invokespecial: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -1935,7 +1811,7 @@ interpret(Thread* t) } goto loop; case invokestatic: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -1947,7 +1823,7 @@ interpret(Thread* t) } goto invoke; case invokevirtual: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -2253,8 +2129,8 @@ interpret(Thread* t) ip += 3; ip -= (ip % 4); - int32_t default_ = codeReadInt32(t, ip); - int32_t pairCount = codeReadInt32(t, ip); + int32_t default_ = codeReadInt32(t, code, ip); + int32_t pairCount = codeReadInt32(t, code, ip); int32_t key = popInt(t); @@ -2264,14 +2140,14 @@ interpret(Thread* t) int32_t middle = bottom + (span / 2); unsigned index = ip + (middle * 8); - int32_t k = codeReadInt32(t, index); + int32_t k = codeReadInt32(t, code, index); if (key < k) { top = middle; } else if (key > k) { bottom = middle + 1; } else { - ip = base + codeReadInt32(t, index); + ip = base + codeReadInt32(t, code, index); goto loop; } } @@ -2386,7 +2262,7 @@ interpret(Thread* t) } goto loop; case multianewarray: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); uint8_t dimensions = codeBody(t, code, ip++); object class_ = resolveClass(t, codePool(t, code), index - 1); @@ -2413,7 +2289,7 @@ interpret(Thread* t) } goto loop; case new_: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClass(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -2487,7 +2363,7 @@ interpret(Thread* t) } goto loop; case putfield: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -2552,7 +2428,7 @@ interpret(Thread* t) } goto loop; case putstatic: { - uint16_t index = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, codePool(t, code), index - 1); if (UNLIKELY(exception)) goto throw_; @@ -2664,15 +2540,15 @@ interpret(Thread* t) ip += 3; ip -= (ip % 4); - int32_t default_ = codeReadInt32(t, ip); - int32_t bottom = codeReadInt32(t, ip); - int32_t top = codeReadInt32(t, ip); + int32_t default_ = codeReadInt32(t, code, ip); + int32_t bottom = codeReadInt32(t, code, ip); + int32_t top = codeReadInt32(t, code, ip); int32_t key = popInt(t); if (key >= bottom and key <= top) { unsigned index = ip + ((key - bottom) * 4); - ip = base + codeReadInt32(t, index); + ip = base + codeReadInt32(t, code, index); } else { ip = base + default_; } @@ -2686,38 +2562,38 @@ interpret(Thread* t) wide: switch (codeBody(t, code, ip++)) { case aload: { - pushObject(t, localObject(t, codeReadInt16(t, ip))); + pushObject(t, localObject(t, codeReadInt16(t, code, ip))); } goto loop; case astore: { - setLocalObject(t, codeReadInt16(t, ip), popObject(t)); + setLocalObject(t, codeReadInt16(t, code, ip), popObject(t)); } goto loop; case iinc: { - uint16_t index = codeReadInt16(t, ip); - uint16_t count = codeReadInt16(t, ip); + uint16_t index = codeReadInt16(t, code, ip); + uint16_t count = codeReadInt16(t, code, ip); setLocalInt(t, index, localInt(t, index) + count); } goto loop; case iload: { - pushInt(t, localInt(t, codeReadInt16(t, ip))); + pushInt(t, localInt(t, codeReadInt16(t, code, ip))); } goto loop; case istore: { - setLocalInt(t, codeReadInt16(t, ip), popInt(t)); + setLocalInt(t, codeReadInt16(t, code, ip), popInt(t)); } goto loop; case lload: { - pushLong(t, localLong(t, codeReadInt16(t, ip))); + pushLong(t, localLong(t, codeReadInt16(t, code, ip))); } goto loop; case lstore: { - setLocalLong(t, codeReadInt16(t, ip), popLong(t)); + setLocalLong(t, codeReadInt16(t, code, ip), popLong(t)); } goto loop; case ret: { - ip = localInt(t, codeReadInt16(t, ip)); + ip = localInt(t, codeReadInt16(t, code, ip)); } goto loop; default: abort(t); @@ -3024,6 +2900,68 @@ class MyProcessor: public Processor { return 0; } + virtual unsigned + parameterFootprint(vm::Thread*, const char* s, bool static_) + { + unsigned footprint = 0; + ++ s; // skip '(' + while (*s and *s != ')') { + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + case '[': + while (*s == '[') ++ s; + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + default: + ++ s; + break; + } + break; + + case 'J': + case 'D': + ++ s; + ++ footprint; + break; + + default: + ++ s; + break; + } + + ++ footprint; + } + + if (not static_) { + ++ footprint; + } + return footprint; + } + + virtual void + initClass(vm::Thread* t, object c) + { + PROTECT(t, c); + + acquire(t, t->m->classLock); + if (classVmFlags(t, c) & NeedInitFlag + and (classVmFlags(t, c) & InitFlag) == 0) + { + classVmFlags(t, c) |= InitFlag; + t->m->processor->invoke(t, classInitializer(t, c), 0); + } else { + release(t, t->m->classLock); + } + } + virtual void visitObjects(vm::Thread* vmt, Heap::Visitor* v) { @@ -3156,7 +3094,7 @@ class MyProcessor: public Processor { assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); - if (UNLIKELY(t->sp + parameterFootprint(methodSpec) + 1 + if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) > Thread::StackSizeInWords / 2)) { t->exception = makeStackOverflowError(t); diff --git a/src/machine.cpp b/src/machine.cpp index afb5616b11..e64a18fb78 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -876,6 +876,45 @@ parseCode(Thread* t, Stream& s, object pool) return code; } +void +scanMethodSpec(Thread* t, const char* s, unsigned* parameterCount, + unsigned* returnCode) +{ + unsigned count = 0; + ++ s; // skip '(' + while (*s and *s != ')') { + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + case '[': + while (*s == '[') ++ s; + switch (*s) { + case 'L': + while (*s and *s != ';') ++ s; + ++ s; + break; + + default: + ++ s; + break; + } + break; + + default: + ++ s; + break; + } + + ++ count; + } + + *parameterCount = count; + *returnCode = fieldCode(t, s[1]); +} + void parseMethodTable(Thread* t, Stream& s, object class_, object pool) { @@ -910,6 +949,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) method = makeMethod (t, methodVmFlags(t, method), + methodReturnCode(t, method), methodParameterCount(t, method), methodParameterFootprint(t, method), methodFlags(t, method), @@ -967,19 +1007,19 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } - unsigned parameterCount = ::parameterCount - (t, arrayBody(t, pool, spec - 1)); + const char* specString = reinterpret_cast + (&byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)); - unsigned parameterFootprint = ::parameterFootprint - (t, arrayBody(t, pool, spec - 1)); + unsigned parameterCount; + unsigned returnCode; + scanMethodSpec(t, specString, ¶meterCount, &returnCode); - if ((flags & ACC_STATIC) == 0) { - ++ parameterCount; - ++ parameterFootprint; - } + unsigned parameterFootprint = t->m->processor->parameterFootprint + (t, specString, flags & ACC_STATIC); object method = makeMethod(t, 0, // vm flags + returnCode, parameterCount, parameterFootprint, flags, @@ -1793,86 +1833,6 @@ classInitializer(Thread* t, object class_) abort(t); } -unsigned -parameterFootprint(const char* s) -{ - unsigned footprint = 0; - ++ s; // skip '(' - while (*s and *s != ')') { - switch (*s) { - case 'L': - while (*s and *s != ';') ++ s; - ++ s; - break; - - case '[': - while (*s == '[') ++ s; - switch (*s) { - case 'L': - while (*s and *s != ';') ++ s; - ++ s; - break; - - default: - ++ s; - break; - } - break; - - case 'J': - case 'D': - ++ s; - ++ footprint; - break; - - default: - ++ s; - break; - } - - ++ footprint; - } - - return footprint; -} - -unsigned -parameterCount(const char* s) -{ - unsigned count = 0; - ++ s; // skip '(' - while (*s and *s != ')') { - switch (*s) { - case 'L': - while (*s and *s != ';') ++ s; - ++ s; - break; - - case '[': - while (*s == '[') ++ s; - switch (*s) { - case 'L': - while (*s and *s != ';') ++ s; - ++ s; - break; - - default: - ++ s; - break; - } - break; - - default: - ++ s; - break; - } - - ++ count; - } - - return count; -} - object hashMapFindNode(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), diff --git a/src/machine.h b/src/machine.h index c2a625a4b9..33fb03ac62 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1841,17 +1841,7 @@ resolveObjectArrayClass(Thread* t, object elementSpec); inline void initClass(Thread* t, object c) { - PROTECT(t, c); - - acquire(t, t->m->classLock); - if (classVmFlags(t, c) & NeedInitFlag - and (classVmFlags(t, c) & InitFlag) == 0) - { - classVmFlags(t, c) |= InitFlag; - t->m->processor->invoke(t, classInitializer(t, c), 0); - } else { - release(t, t->m->classLock); - } + t->m->processor->initClass(t, c); } object @@ -1914,26 +1904,6 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index) return cast(array, (2 + index) * BytesPerWord); } -unsigned -parameterFootprint(const char* s); - -inline unsigned -parameterFootprint(Thread* t, object spec) -{ - return parameterFootprint - (reinterpret_cast(&byteArrayBody(t, spec, 0))); -} - -unsigned -parameterCount(const char* s); - -inline unsigned -parameterCount(Thread* t, object spec) -{ - return parameterCount - (reinterpret_cast(&byteArrayBody(t, spec, 0))); -} - int lineNumber(Thread* t, object method, unsigned ip); diff --git a/src/process.h b/src/process.h new file mode 100644 index 0000000000..4dcfbe68e0 --- /dev/null +++ b/src/process.h @@ -0,0 +1,137 @@ +#ifndef PROCESS_H +#define PROCESS_H + +#include "common.h" +#include "system.h" +#include "machine.h" +#include "constants.h" + +namespace vm { + +inline int16_t +codeReadInt16(Thread* t, object code, unsigned& ip) +{ + uint8_t v1 = codeBody(t, code, ip++); + uint8_t v2 = codeBody(t, code, ip++); + return ((v1 << 8) | v2); +} + +inline int32_t +codeReadInt32(Thread* t, object code, unsigned& ip) +{ + uint8_t v1 = codeBody(t, code, ip++); + uint8_t v2 = codeBody(t, code, ip++); + uint8_t v3 = codeBody(t, code, ip++); + uint8_t v4 = codeBody(t, code, ip++); + return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); +} + +inline object +resolveClass(Thread* t, object container, + object& (*class_)(vm::Thread*, object)) +{ + object o = class_(t, container); + if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) + { + PROTECT(t, container); + + o = resolveClass(t, o); + if (UNLIKELY(t->exception)) return 0; + + set(t, class_(t, container), o); + } + return o; +} + +inline object +resolveClass(Thread* t, object pool, unsigned index) +{ + object o = arrayBody(t, pool, index); + if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) + { + PROTECT(t, pool); + + o = resolveClass(t, o); + if (UNLIKELY(t->exception)) return 0; + + set(t, arrayBody(t, pool, index), o); + } + return o; +} + +inline object +resolve(Thread* t, object pool, unsigned index, + object (*find)(vm::Thread*, object, object, object), + object (*makeError)(vm::Thread*, object)) +{ + object o = arrayBody(t, pool, index); + if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) + { + PROTECT(t, pool); + + object reference = o; + PROTECT(t, reference); + + object class_ = resolveClass(t, o, referenceClass); + if (UNLIKELY(t->exception)) return 0; + + o = findInHierarchy + (t, class_, referenceName(t, reference), referenceSpec(t, reference), + find, makeError); + if (UNLIKELY(t->exception)) return 0; + + set(t, arrayBody(t, pool, index), o); + } + + return o; +} + +inline object +resolveField(Thread* t, object pool, unsigned index) +{ + return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError); +} + +inline object +resolveMethod(Thread* t, object pool, unsigned index) +{ + return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError); +} + +inline bool +isSuperclass(Thread* t, object class_, object base) +{ + for (object oc = classSuper(t, base); oc; oc = classSuper(t, oc)) { + if (oc == class_) { + return true; + } + } + return false; +} + +inline bool +isSpecialMethod(Thread* t, object method, object class_) +{ + return (classFlags(t, class_) & ACC_SUPER) + and strcmp(reinterpret_cast(""), + &byteArrayBody(t, methodName(t, method), 0)) != 0 + and isSuperclass(t, methodClass(t, method), class_); +} + +inline object +findMethod(Thread* t, object method, object class_) +{ + return arrayBody(t, classVirtualTable(t, class_), + methodOffset(t, method)); +} + +inline bool +methodVirtual(Thread* t, object method) +{ + return (methodFlags(t, method) & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) + != 0; +} + +} // namespace vm + +#endif//PROCESS_H diff --git a/src/processor.h b/src/processor.h index cd4165057a..0d72d21d02 100644 --- a/src/processor.h +++ b/src/processor.h @@ -17,6 +17,12 @@ class Processor { virtual object methodStub(Thread* t) = 0; + virtual unsigned + parameterFootprint(Thread* t, const char* spec, bool static_) = 0; + + virtual void + initClass(Thread* t, object c) = 0; + virtual void visitObjects(Thread* t, Heap::Visitor* v) = 0; diff --git a/src/system.cpp b/src/system.cpp index 67e7ca96cf..493d311833 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -15,10 +15,14 @@ #define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x) -namespace { - #ifdef __i386__ +extern "C" uint64_t +cdeclCall(void* function, void* stack, unsigned stackSize, + unsigned returnType); + +namespace { + inline uint64_t dynamicCall(void* function, uintptr_t* arguments, uint8_t*, unsigned, unsigned argumentsSize, unsigned returnType) @@ -26,8 +30,16 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*, return cdeclCall(function, arguments, argumentsSize, returnType); } +} // namespace + #elif defined __x86_64__ +extern "C" uint64_t +amd64Call(void* function, void* stack, unsigned stackSize, + void* gprTable, void* sseTable, unsigned returnType); + +namespace { + uint64_t dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes, unsigned argumentCount, unsigned, unsigned returnType) @@ -68,12 +80,12 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes, (sseIndex ? sseTable : 0), returnType); } +} // namespace + #else # error unsupported platform #endif -} - using namespace vm; namespace { diff --git a/src/types.def b/src/types.def index 4e0dfe8bfe..ab6dec5a8b 100644 --- a/src/types.def +++ b/src/types.def @@ -41,8 +41,9 @@ (type method java/lang/reflect/Method (extends accessibleObject) (uint8_t vmFlags) + (uint8_t returnCode) (uint8_t parameterCount) - (uint16_t parameterFootprint) + (uint8_t parameterFootprint) (uint16_t flags) (uint16_t offset) (object name) @@ -58,7 +59,6 @@ (type nativeMethodData (void* function) (uint16_t argumentTableSize) - (uint8_t returnCode) (array uint8_t parameterTypes)) (type pointer diff --git a/src/vmInvoke.S b/src/vmInvoke.S new file mode 100644 index 0000000000..300355018b --- /dev/null +++ b/src/vmInvoke.S @@ -0,0 +1,102 @@ +#include "types.h" + +.text + +.globl vmInvoke +vmInvoke: +#ifdef __x86_64__ + + pushq %rbp + movq %rsp,%rbp + + // %rdi: function + // %rsi: stack + // %rdx: stackSize + // %rcx: returnType + + // reserve space for arguments + subq %rdx,%rsp + + // copy memory arguments into place + movq $0,%r8 + jmp test + +loop: + movq %r8,%rax + movq %r8,%r9 + addq %rsp,%r9 + addq %rsi,%rax + movq (%rax),%rax + movq %rax,(%r9) + addq $8,%r8 + +test: + cmpq %rdx,%r8 + jb loop + + // call function + call *%rdi + + movq %rbp,%rsp + popq %rbp + ret + +#elif defined __i386__ + + pushl %ebp + movl %esp,%ebp + + // 8(%ebp): function + // 12(%ebp): stack + // 16(%ebp): stackSize + // 20(%ebp): returnType + + // reserve space for arguments + movl 16(%ebp),%ecx + + subl %ecx,%esp + + // copy arguments into place + movl $0,%ecx + jmp test + +loop: + movl %ecx,%eax + movl %ecx,%edx + addl %esp,%edx + addl 12(%ebp),%eax + movl (%eax),%eax + movl %eax,(%edx) + addl $4,%ecx + +test: + cmpl 16(%ebp),%ecx + jb loop + + // call function + call *8(%ebp) + + // handle return value based on expected type + movl 20(%ebp),%ecx + +void: + cmpl $VOID_TYPE,%ecx + jne int64 + jmp exit + +int64: + cmpl $INT64_TYPE,%ecx + jne int32 + jmp exit + +int32: + movl $0,%edx + +exit: + movl %ebp,%esp + popl %ebp + ret + +#else +# error unsupported platform +#endif diff --git a/test/Instructions.java b/test/Instructions.java index 9e60fd904c..d0c3416c71 100644 --- a/test/Instructions.java +++ b/test/Instructions.java @@ -1,7 +1,19 @@ public class Instructions { + private String foo(String s) { + return s; + } + + public String bar(String s) { + return s; + } + public static void main(String[] args) { int a = 2; int b = 2; int c = a + b; + +// Instructions i = new Instructions(); +// i.foo("hello"); +// i.bar("hello"); } }