diff --git a/makefile b/makefile index 068b0b04bb..9cdd151cdb 100644 --- a/makefile +++ b/makefile @@ -161,7 +161,8 @@ vm-sources = \ $(src)/heap.cpp \ $(src)/$(process).cpp \ $(src)/builtin.cpp \ - $(src)/jnienv.cpp + $(src)/jnienv.cpp \ + $(src)/process.cpp vm-asm-sources = $(src)/$(asm).S diff --git a/src/compile.cpp b/src/compile.cpp index 44b450616e..3b36ccfeb3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3917,9 +3917,7 @@ invokeNative2(MyThread* t, object method) initClass(t, methodClass(t, method)); if (UNLIKELY(t->exception)) return 0; - if (objectClass(t, methodCode(t, method)) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (methodCode(t, method) == 0) { void* function = resolveNativeMethod(t, method); if (UNLIKELY(function == 0)) { object message = makeString diff --git a/src/machine.cpp b/src/machine.cpp index 3edbf8700f..8a25341aa9 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -511,121 +511,6 @@ makeByteArray(Thread* t, const char* format, va_list a) return s; } -unsigned -mangledSize(int8_t c) -{ - switch (c) { - case '_': - case ';': - case '[': - return 2; - - case '$': - return 6; - - default: - return 1; - } -} - -unsigned -mangle(int8_t c, int8_t* dst) -{ - switch (c) { - case '/': - dst[0] = '_'; - return 1; - - case '_': - dst[0] = '_'; - dst[1] = '1'; - return 2; - - case ';': - dst[0] = '_'; - dst[1] = '2'; - return 2; - - case '[': - dst[0] = '_'; - dst[1] = '3'; - return 2; - - case '$': - memcpy(dst, "_00024", 6); - return 6; - - default: - dst[0] = c; - return 1; - } -} - -object -makeJNIName(Thread* t, object method, bool decorate) -{ - unsigned size = 5; - object className = ::className(t, methodClass(t, method)); - PROTECT(t, className); - for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) { - size += mangledSize(byteArrayBody(t, className, i)); - } - - ++ size; - - object methodName = ::methodName(t, method); - PROTECT(t, methodName); - for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) { - size += mangledSize(byteArrayBody(t, methodName, i)); - } - - object methodSpec = ::methodSpec(t, method); - PROTECT(t, methodSpec); - if (decorate) { - size += 2; - for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1 - and byteArrayBody(t, methodSpec, i) != ')'; ++i) - { - size += mangledSize(byteArrayBody(t, methodSpec, i)); - } - } - - object name = makeByteArray(t, size + 1, false); - unsigned index = 0; - - memcpy(&byteArrayBody(t, name, index), "Java_", 5); - index += 5; - - for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) { - index += mangle(byteArrayBody(t, className, i), - &byteArrayBody(t, name, index)); - } - - byteArrayBody(t, name, index++) = '_'; - - for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) { - index += mangle(byteArrayBody(t, methodName, i), - &byteArrayBody(t, name, index)); - } - - if (decorate) { - byteArrayBody(t, name, index++) = '_'; - byteArrayBody(t, name, index++) = '_'; - for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1 - and byteArrayBody(t, methodSpec, i) != ')'; ++i) - { - index += mangle(byteArrayBody(t, methodSpec, i), - &byteArrayBody(t, name, index)); - } - } - - byteArrayBody(t, name, index++) = 0; - - assert(t, index == size + 1); - - return name; -} - object parseUtf8(Thread* t, Stream& s, unsigned length) { @@ -1180,9 +1065,6 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) object virtualMap = makeHashMap(t, 0, 0); PROTECT(t, virtualMap); - object nativeMap = makeHashMap(t, 0, 0); - PROTECT(t, nativeMap); - unsigned virtualCount = 0; unsigned declaredVirtualCount = 0; @@ -1313,34 +1195,9 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) } } - if (flags & ACC_NATIVE) { - object p = hashMapFindNode - (t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual); - - if (p) { - set(t, p, TripleSecond, method); - } else { - hashMapInsert(t, nativeMap, methodName(t, method), 0, byteArrayHash); - } - } - set(t, methodTable, ArrayBody + (i * BytesPerWord), method); } - for (unsigned i = 0; i < count; ++i) { - object method = arrayBody(t, methodTable, i); - - if (methodFlags(t, method) & ACC_NATIVE) { - PROTECT(t, method); - - object overloaded = hashMapFind - (t, nativeMap, methodName(t, method), byteArrayHash, byteArrayEqual); - - object jniName = makeJNIName(t, method, overloaded); - set(t, method, MethodCode, jniName); - } - } - set(t, class_, ClassMethodTable, methodTable); } diff --git a/src/process.cpp b/src/process.cpp new file mode 100644 index 0000000000..74a5c36a77 --- /dev/null +++ b/src/process.cpp @@ -0,0 +1,250 @@ +#include "process.h" + +using namespace vm; + +namespace { + +unsigned +mangledSize(int8_t c) +{ + switch (c) { + case '_': + case ';': + case '[': + return 2; + + case '$': + return 6; + + default: + return 1; + } +} + +unsigned +mangle(int8_t c, char* dst) +{ + switch (c) { + case '/': + dst[0] = '_'; + return 1; + + case '_': + dst[0] = '_'; + dst[1] = '1'; + return 2; + + case ';': + dst[0] = '_'; + dst[1] = '2'; + return 2; + + case '[': + dst[0] = '_'; + dst[1] = '3'; + return 2; + + case '$': + memcpy(dst, "_00024", 6); + return 6; + + default: + dst[0] = c; + return 1; + } +} + +unsigned +jniNameLength(Thread* t, object method, bool decorate) +{ + unsigned size = 5; + + object className = ::className(t, methodClass(t, method)); + for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) { + size += mangledSize(byteArrayBody(t, className, i)); + } + + ++ size; + + object methodName = ::methodName(t, method); + for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) { + size += mangledSize(byteArrayBody(t, methodName, i)); + } + + if (decorate) { + size += 2; + + object methodSpec = ::methodSpec(t, method); + for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1 + and byteArrayBody(t, methodSpec, i) != ')'; ++i) + { + size += mangledSize(byteArrayBody(t, methodSpec, i)); + } + } + + return size; +} + +void +makeJNIName(Thread* t, char* name, object method, bool decorate) +{ + memcpy(name, "Java_", 5); + name += 5; + + object className = ::className(t, methodClass(t, method)); + for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) { + name += mangle(byteArrayBody(t, className, i), name); + } + + *(name++) = '_'; + + object methodName = ::methodName(t, method); + for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) { + name += mangle(byteArrayBody(t, methodName, i), name); + } + + if (decorate) { + *(name++) = '_'; + *(name++) = '_'; + + object methodSpec = ::methodSpec(t, method); + for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1 + and byteArrayBody(t, methodSpec, i) != ')'; ++i) + { + name += mangle(byteArrayBody(t, methodSpec, i), name); + } + } + + *(name++) = 0; +} + +void* +resolveNativeMethod(Thread* t, const char* name) +{ + for (System::Library* lib = t->m->firstLibrary; lib; lib = lib->next()) { + void* p = lib->resolve(name); + if (p) { + return p; + } + } + + return 0; +} + +} // namespace + +namespace vm { + +void* +resolveNativeMethod(Thread* t, object method, bool decorate) +{ + unsigned size = jniNameLength(t, method, decorate); + char name[size + 5]; // extra 5 is for code below + makeJNIName(t, name, method, decorate); + void* p = ::resolveNativeMethod(t, name); + if (p) { + return p; + } + +#ifdef __MINGW32__ + // on windows, we also try the _%s@%d variant, since the SWT + // libraries use it. + unsigned footprint = methodParameterFootprint(t, method) + 1; + if (methodFlags(t, method) & ACC_STATIC) { + ++ footprint; + } + + snprintf(name + size - 1, 5, "@%d", footprint * BytesPerWord); + + p = resolveNativeMethod(t, reinterpret_cast(name)); + if (p) { + return p; + } +#endif + + return 0; +} + +ExceptionHandler* +findExceptionHandler(Thread* t, object method, unsigned ip) +{ + PROTECT(t, method); + + object eht = codeExceptionHandlerTable(t, methodCode(t, method)); + + if (eht) { + for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { + ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); + + if (ip - 1 >= exceptionHandlerStart(eh) + and ip - 1 < exceptionHandlerEnd(eh)) + { + object catchType = 0; + if (exceptionHandlerCatchType(eh)) { + object e = t->exception; + t->exception = 0; + PROTECT(t, e); + + PROTECT(t, eht); + catchType = resolveClassInPool + (t, codePool(t, methodCode(t, method)), + exceptionHandlerCatchType(eh) - 1); + + if (catchType) { + eh = exceptionHandlerTableBody(t, eht, i); + t->exception = e; + } else { + // can't find what we're supposed to catch - move on. + continue; + } + } + + if (catchType == 0 or instanceOf(t, catchType, t->exception)) { + return eh; + } + } + } + } + + return 0; +} + +int +findLineNumber(Thread* t, object method, unsigned ip) +{ + if (methodFlags(t, method) & ACC_NATIVE) { + return NativeLine; + } + + // our parameter indicates the instruction following the one we care + // about, so we back up first: + -- ip; + + object code = methodCode(t, method); + object lnt = codeLineNumberTable(t, code); + if (lnt) { + unsigned bottom = 0; + unsigned top = lineNumberTableLength(t, lnt); + for (unsigned span = top - bottom; span; span = top - bottom) { + unsigned middle = bottom + (span / 2); + LineNumber* ln = lineNumberTableBody(t, lnt, middle); + + if (ip >= lineNumberIp(ln) + and (middle + 1 == lineNumberTableLength(t, lnt) + or ip < lineNumberIp(lineNumberTableBody(t, lnt, middle + 1)))) + { + return lineNumberLine(ln); + } else if (ip < lineNumberIp(ln)) { + top = middle; + } else if (ip > lineNumberIp(ln)) { + bottom = middle + 1; + } + } + + abort(t); + } else { + return UnknownLine; + } +} + +} // namespace vm diff --git a/src/process.h b/src/process.h index 80bb26b658..edc648c521 100644 --- a/src/process.h +++ b/src/process.h @@ -124,39 +124,22 @@ findMethod(Thread* t, object method, object class_) methodOffset(t, method)); } +void* +resolveNativeMethod(Thread* t, object method, bool decorate); + inline void* resolveNativeMethod(Thread* t, object method) { - for (System::Library* lib = t->m->firstLibrary; lib; lib = lib->next()) { - void* p = lib->resolve(reinterpret_cast - (&byteArrayBody(t, methodCode(t, method), 0))); + if (methodCode(t, method)) { + return pointerValue(t, methodCode(t, method)); + } else { + void* p = resolveNativeMethod(t, method, false); if (p) { return p; + } else { + return resolveNativeMethod(t, method, true); } -#ifdef __MINGW32__ - else { - // on windows, we also try the _%s@%d variant, since the SWT - // libraries use it. - - unsigned footprint = methodParameterFootprint(t, method) + 1; - if (methodFlags(t, method) & ACC_STATIC) { - ++ footprint; - } - - unsigned size = byteArrayLength(t, methodCode(t, method)) + 5; - char buffer[size]; - snprintf(buffer, size, "_%s@%d", - &byteArrayBody(t, methodCode(t, method), 0), - footprint * BytesPerWord); - - p = lib->resolve(buffer); - if (p) { - return p; - } - } -#endif } - return 0; } inline object @@ -206,87 +189,11 @@ populateMultiArray(Thread* t, object array, int32_t* counts, } } -inline ExceptionHandler* -findExceptionHandler(Thread* t, object method, unsigned ip) -{ - PROTECT(t, method); +ExceptionHandler* +findExceptionHandler(Thread* t, object method, unsigned ip); - object eht = codeExceptionHandlerTable(t, methodCode(t, method)); - - if (eht) { - for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { - ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); - - if (ip - 1 >= exceptionHandlerStart(eh) - and ip - 1 < exceptionHandlerEnd(eh)) - { - object catchType = 0; - if (exceptionHandlerCatchType(eh)) { - object e = t->exception; - t->exception = 0; - PROTECT(t, e); - - PROTECT(t, eht); - catchType = resolveClassInPool - (t, codePool(t, methodCode(t, method)), - exceptionHandlerCatchType(eh) - 1); - - if (catchType) { - eh = exceptionHandlerTableBody(t, eht, i); - t->exception = e; - } else { - // can't find what we're supposed to catch - move on. - continue; - } - } - - if (catchType == 0 or instanceOf(t, catchType, t->exception)) { - return eh; - } - } - } - } - - return 0; -} - -inline int -findLineNumber(Thread* t, object method, unsigned ip) -{ - if (methodFlags(t, method) & ACC_NATIVE) { - return NativeLine; - } - - // our parameter indicates the instruction following the one we care - // about, so we back up first: - -- ip; - - object code = methodCode(t, method); - object lnt = codeLineNumberTable(t, code); - if (lnt) { - unsigned bottom = 0; - unsigned top = lineNumberTableLength(t, lnt); - for (unsigned span = top - bottom; span; span = top - bottom) { - unsigned middle = bottom + (span / 2); - LineNumber* ln = lineNumberTableBody(t, lnt, middle); - - if (ip >= lineNumberIp(ln) - and (middle + 1 == lineNumberTableLength(t, lnt) - or ip < lineNumberIp(lineNumberTableBody(t, lnt, middle + 1)))) - { - return lineNumberLine(ln); - } else if (ip < lineNumberIp(ln)) { - top = middle; - } else if (ip > lineNumberIp(ln)) { - bottom = middle + 1; - } - } - - abort(t); - } else { - return UnknownLine; - } -} +int +findLineNumber(Thread* t, object method, unsigned ip); } // namespace vm