From afabe8e07e1b2a5b0cdfbd0b1bed88a94ea68c44 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 27 Dec 2010 15:55:23 -0700 Subject: [PATCH] rework VM exception handling; throw OOMEs when appropriate This rather large commit modifies the VM to use non-local returns to throw exceptions instead of simply setting Thread::exception and returning frame-by-frame as it used to. This has several benefits: * Functions no longer need to check Thread::exception after each call which might throw an exception (which would be especially tedious and error-prone now that any function which allocates objects directly or indirectly might throw an OutOfMemoryError) * There's no need to audit the code for calls to functions which previously did not throw exceptions but later do * Performance should be improved slightly due to both the reduced need for conditionals and because undwinding now occurs in a single jump instead of a series of returns The main disadvantages are: * Slightly higher overhead for entering and leaving the VM via the JNI and JDK methods * Non-local returns can make the code harder to read * We must be careful to register destructors for stack-allocated resources with the Thread so they can be called prior to a non-local return The non-local return implementation is similar to setjmp/longjmp, except it uses continuation-passing style to avoid the need for cooperation from the C/C++ compiler. Native C++ exceptions would have also been an option, but that would introduce a dependence on libstdc++, which we're trying to avoid for portability reasons. Finally, this commit ensures that the VM throws an OutOfMemoryError instead of aborting when it reaches its memory ceiling. Currently, we treat the ceiling as a soft limit and temporarily exceed it as necessary to allow garbage collection and certain internal allocations to succeed, but refuse to allocate any Java objects until the heap size drops back below the ceiling. --- src/bootimage.cpp | 46 ++- src/builtin.cpp | 31 +- src/classpath-avian.cpp | 50 +-- src/classpath-common.h | 31 +- src/classpath-openjdk.cpp | 828 ++++++++++++++++++++++++-------------- src/compile-x86.S | 4 +- src/compile.cpp | 560 +++++++++++--------------- src/continuations-x86.S | 16 +- src/heap.cpp | 31 +- src/heap.h | 1 + src/interpret.cpp | 267 ++++++------ src/jnienv.cpp | 633 ++++++++++++++++++++--------- src/machine.cpp | 371 +++++++++-------- src/machine.h | 390 ++++++++++++++---- src/process.cpp | 21 +- src/x86.S | 128 +++++- test/OutOfMemory.java | 62 +++ 17 files changed, 2165 insertions(+), 1305 deletions(-) create mode 100644 test/OutOfMemory.java diff --git a/src/bootimage.cpp b/src/bootimage.cpp index cd0092f0d5..4bd1f8a33d 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -92,8 +92,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, (t, root(t, Machine::BootLoader), makeByteArray(t, "%.*s", nameSize - 6, name), true); - if (t->exception) return 0; - PROTECT(t, c); if (classMethodTable(t, c)) { @@ -138,8 +136,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, if (objectClass(t, o) == type(t, Machine::ReferenceType)) { o = resolveClass (t, root(t, Machine::BootLoader), referenceName(t, o)); - - if (t->exception) return 0; set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord), o); @@ -360,9 +356,9 @@ offset(object a, uintptr_t* b) } void -writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code, - unsigned codeCapacity, const char* className, - const char* methodName, const char* methodSpec) +writeBootImage2(Thread* t, FILE* out, BootImage* image, uint8_t* code, + unsigned codeCapacity, const char* className, + const char* methodName, const char* methodSpec) { Zone zone(t->m->system, t->m->heap, 64 * 1024); @@ -373,8 +369,6 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code, object constants = makeCodeImage (t, &zone, image, code, codeMap, className, methodName, methodSpec); - if (t->exception) return; - PROTECT(t, constants); // this map will not be used when the bootimage is loaded, so @@ -505,6 +499,23 @@ writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code, } } +uint64_t +writeBootImage(Thread* t, uintptr_t* arguments) +{ + FILE* out = reinterpret_cast(arguments[0]); + BootImage* image = reinterpret_cast(arguments[1]); + uint8_t* code = reinterpret_cast(arguments[2]); + unsigned codeCapacity = arguments[3]; + const char* className = reinterpret_cast(arguments[4]); + const char* methodName = reinterpret_cast(arguments[5]); + const char* methodSpec = reinterpret_cast(arguments[6]); + + writeBootImage2 + (t, out, image, code, codeCapacity, className, methodName, methodSpec); + + return 1; +} + } // namespace int @@ -540,15 +551,22 @@ main(int ac, const char** av) return -1; } - writeBootImage - (t, output, &image, code, CodeCapacity, - (ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0)); + uintptr_t arguments[] = { reinterpret_cast(output), + reinterpret_cast(&image), + reinterpret_cast(code), + CodeCapacity, + reinterpret_cast(ac > 3 ? av[3] : 0), + reinterpret_cast(ac > 4 ? av[4] : 0), + reinterpret_cast(ac > 5 ? av[5] : 0) }; + + run(t, writeBootImage, arguments); fclose(output); if (t->exception) { printTrace(t, t->exception); + return -1; + } else { + return 0; } - - return 0; } diff --git a/src/builtin.cpp b/src/builtin.cpp index dd8ece531a..240ec9628a 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -33,15 +33,9 @@ search(Thread* t, object loader, object name, replace('.', '/', s); } - object r = op(t, loader, n); - if (t->exception) { - return 0; - } - - return reinterpret_cast(r); + return reinterpret_cast(op(t, loader, n)); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - return 0; + throwNew(t, Machine::NullPointerExceptionType); } } @@ -81,7 +75,7 @@ Avian_avian_SystemClassLoader_resourceExists object name = reinterpret_cast(arguments[1]); if (LIKELY(name)) { - RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); + THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); unsigned length; @@ -92,8 +86,7 @@ Avian_avian_SystemClassLoader_resourceExists return r; } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - return 0; + throwNew(t, Machine::NullPointerExceptionType); } } @@ -114,17 +107,16 @@ Avian_avian_Machine_dumpHeap object outputFile = reinterpret_cast(*arguments); unsigned length = stringLength(t, outputFile); - char n[length + 1]; - stringChars(t, outputFile, n); - FILE* out = vm::fopen(n, "wb"); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, outputFile, RUNTIME_ARRAY_BODY(n)); + FILE* out = vm::fopen(RUNTIME_ARRAY_BODY(n), "wb"); if (out) { { ENTER(t, Thread::ExclusiveState); dumpHeap(t, out); } fclose(out); } else { - object message = makeString(t, "file not found: %s", n); - t->exception = makeThrowable(t, Machine::RuntimeExceptionType, message); + throwNew(t, Machine::RuntimeExceptionType, "file not found: %s", n); } } @@ -146,7 +138,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength object path = reinterpret_cast(*arguments); if (LIKELY(path)) { - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p)); @@ -170,7 +162,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open object path = reinterpret_cast(*arguments); if (LIKELY(path)) { - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p)); @@ -180,8 +172,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open return reinterpret_cast(r); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - return 0; + throwNew(t, Machine::NullPointerExceptionType); } } diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 51f5058713..656086f4c1 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -60,9 +60,7 @@ class MyClasspath : public Classpath { (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "(Ljava/lang/Thread;)V"); - if (t->exception == 0) { - t->m->processor->invoke(t, method, 0, t->javaThread); - } + t->m->processor->invoke(t, method, 0, t->javaThread); } virtual void @@ -134,9 +132,8 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Object_getVMClass (Thread* t, object, uintptr_t* arguments) { - object o = reinterpret_cast(arguments[0]); - - return reinterpret_cast(objectClass(t, o)); + return reinterpret_cast + (objectClass(t, reinterpret_cast(arguments[0]))); } extern "C" JNIEXPORT void JNICALL @@ -307,12 +304,16 @@ Avian_java_lang_reflect_Method_invoke object instance = reinterpret_cast(arguments[1]); object args = reinterpret_cast(arguments[2]); - object v = t->m->processor->invokeArray(t, method, instance, args); - if (t->exception) { - t->exception = makeThrowable - (t, Machine::InvocationTargetExceptionType, 0, 0, t->exception); - } - return reinterpret_cast(v); + THREAD_RESOURCE0(t, { + if (t->exception) { + object exception = t->exception; + t->exception = makeThrowable + (t, Machine::InvocationTargetExceptionType, 0, 0, exception); + } + }); + + return reinterpret_cast + (t->m->processor->invokeArray(t, method, instance, args)); } extern "C" JNIEXPORT int64_t JNICALL @@ -327,12 +328,11 @@ Avian_java_lang_reflect_Array_getLength if (LIKELY(elementSize)) { return cast(array, BytesPerWord); } else { - t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); + throwNew(t, Machine::IllegalArgumentExceptionType); } } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); + throwNew(t, Machine::NullPointerExceptionType); } - return 0; } extern "C" JNIEXPORT int64_t JNICALL @@ -394,7 +394,7 @@ Avian_java_lang_System_getVMProperty PROTECT(t, found); unsigned length = stringLength(t, name); - RUNTIME_ARRAY(char, n, length + 1); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); int64_t r = 0; @@ -439,8 +439,7 @@ Avian_java_lang_System_identityHashCode if (LIKELY(o)) { return objectHash(t, o); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - return 0; + throwNew(t, Machine::NullPointerExceptionType); } } @@ -452,7 +451,7 @@ Avian_java_lang_Runtime_load bool mapName = arguments[1]; unsigned length = stringLength(t, name); - RUNTIME_ARRAY(char, n, length + 1); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), mapName, true); @@ -622,11 +621,13 @@ Avian_avian_Classes_defineVMClass uint8_t* buffer = static_cast (t->m->heap->allocate(length)); - memcpy(buffer, &byteArrayBody(t, b, offset), length); - object c = defineClass(t, loader, buffer, length); - t->m->heap->free(buffer, length); + + THREAD_RESOURCE2(t, uint8_t*, buffer, int, length, + t->m->heap->free(buffer, length)); - return reinterpret_cast(c); + memcpy(buffer, &byteArrayBody(t, b, offset), length); + + return reinterpret_cast(defineClass(t, loader, buffer, length)); } extern "C" JNIEXPORT void JNICALL @@ -648,8 +649,7 @@ Avian_avian_Classes_isAssignableFrom if (LIKELY(that)) { return vm::isAssignableFrom(t, this_, that); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - return 0; + throwNew(t, Machine::NullPointerExceptionType); } } diff --git a/src/classpath-common.h b/src/classpath-common.h index 7d17a74673..6efc0a1424 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -101,9 +101,7 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, return; } else { - t->exception = makeThrowable - (t, Machine::IndexOutOfBoundsExceptionType); - return; + throwNew(t, Machine::IndexOutOfBoundsExceptionType); } } else { return; @@ -111,11 +109,11 @@ arrayCopy(Thread* t, object src, int32_t srcOffset, object dst, } } } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); + throwNew(t, Machine::NullPointerExceptionType); return; } - t->exception = makeThrowable(t, Machine::ArrayStoreExceptionType); + throwNew(t, Machine::ArrayStoreExceptionType); } void @@ -158,6 +156,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, { ACQUIRE(t, t->m->classLock); + char* mappedName; unsigned nameLength = strlen(name); if (mapName) { const char* builtins = findProperty(t, "avian.builtins"); @@ -186,15 +185,22 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, const char* suffix = t->m->system->librarySuffix(); unsigned mappedNameLength = nameLength + strlen(prefix) + strlen(suffix); - char* mappedName = static_cast + mappedName = static_cast (t->m->heap->allocate(mappedNameLength + 1)); snprintf(mappedName, mappedNameLength + 1, "%s%s%s", prefix, name, suffix); name = mappedName; nameLength = mappedNameLength; + } else { + mappedName = 0; } + THREAD_RESOURCE2 + (t, char*, mappedName, unsigned, nameLength, if (mappedName) { + t->m->heap->free(mappedName, nameLength + 1); + }); + System::Library* lib = 0; for (Tokenizer tokenizer(path, t->m->system->pathSeparator()); tokenizer.hasMore();) @@ -202,7 +208,7 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, Tokenizer::Token token(tokenizer.next()); unsigned fullNameLength = token.length + 1 + nameLength; - RUNTIME_ARRAY(char, fullName, fullNameLength + 1); + THREAD_RUNTIME_ARRAY(t, char, fullName, fullNameLength + 1); snprintf(RUNTIME_ARRAY_BODY(fullName), fullNameLength + 1, "%*s/%s", token.length, token.s, name); @@ -220,13 +226,8 @@ loadLibrary(Thread* t, const char* path, const char* name, bool mapName, runOnLoadIfFound(t, lib); } } else { - object message = makeString(t, "library not found: %s", name); - t->exception = makeThrowable - (t, Machine::UnsatisfiedLinkErrorType, message); - } - - if (mapName) { - t->m->heap->free(name, nameLength + 1); + throwNew(t, Machine::UnsatisfiedLinkErrorType, "library not found: %s", + name); } return lib; @@ -264,7 +265,7 @@ makeStackTraceElement(Thread* t, object e) object class_ = className(t, methodClass(t, traceElementMethod(t, e))); PROTECT(t, class_); - RUNTIME_ARRAY(char, s, byteArrayLength(t, class_)); + THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, class_)); replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast(&byteArrayBody(t, class_, 0))); class_ = makeString(t, "%s", s); diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bb4bdb33e4..8882976f3c 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -158,7 +158,7 @@ getClassName(Thread* t, object c) object makeClassNameString(Thread* t, object name) { - RUNTIME_ARRAY(char, s, byteArrayLength(t, name)); + THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, name)); replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast(&byteArrayBody(t, name, 0))); @@ -320,9 +320,7 @@ class MyClasspath : public Classpath { object method = resolveMethod (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); - if (LIKELY(t->exception == 0)) { - t->m->processor->invoke(t, method, t->javaThread); - } + t->m->processor->invoke(t, method, t->javaThread); acquire(t, t->javaThread); t->flags &= ~Thread::ActiveFlag; @@ -337,11 +335,9 @@ class MyClasspath : public Classpath { resolveSystemClass(t, root(t, Machine::BootLoader), className(t, type(t, Machine::ClassLoaderType))); - if (UNLIKELY(t->exception)) return; #ifdef AVIAN_OPENJDK_SRC interceptFileOperations(t); - if (UNLIKELY(t->exception)) return; #else // not AVIAN_OPENJDK_SRC if (loadLibrary(t, libraryPath, "verify", true, true) == 0 or loadLibrary(t, libraryPath, "java", true, true) == 0) @@ -353,25 +349,22 @@ class MyClasspath : public Classpath { object constructor = resolveMethod (t, type(t, Machine::ClassLoaderType), "", "(Ljava/lang/ClassLoader;)V"); - if (UNLIKELY(t->exception)) return; + PROTECT(t, constructor); t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0); - if (UNLIKELY(t->exception)) return; t->m->processor->invoke (t, constructor, root(t, Machine::AppLoader), root(t, Machine::BootLoader)); - if (UNLIKELY(t->exception)) return; object scl = resolveField (t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;"); - if (UNLIKELY(t->exception)) return; + PROTECT(t, scl); object sclSet = resolveField (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); - if (UNLIKELY(t->exception)) return; set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), fieldOffset(t, scl), root(t, Machine::AppLoader)); @@ -453,6 +446,7 @@ getFinder(Thread* t, const char* name, unsigned nameLength) void* p = t->m->libraries->resolve (reinterpret_cast(&byteArrayBody(t, n, 0))); + if (p) { uint8_t* (*function)(unsigned*); memcpy(&function, &p, BytesPerWord); @@ -544,7 +538,7 @@ getFileAttributes object file = reinterpret_cast(arguments[1]); object path = cast(file, cp->filePathField); - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); replace('\\', '/', RUNTIME_ARRAY_BODY(p)); @@ -573,12 +567,11 @@ getFileAttributes return 0; } } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - reinterpret_cast(arguments[0]), file); - - return (r ? intValue(t, r) : 0); + return intValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + reinterpret_cast(arguments[0]), file)); } } @@ -594,7 +587,7 @@ checkFileAccess unsigned mask = arguments[2]; object path = cast(file, cp->filePathField); - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); replace('\\', '/', RUNTIME_ARRAY_BODY(p)); @@ -623,12 +616,11 @@ checkFileAccess return 0; } } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - reinterpret_cast(arguments[0]), file, mask); - - return (r ? booleanValue(t, r) : false); + return booleanValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + reinterpret_cast(arguments[0]), file, mask)); } } @@ -641,7 +633,7 @@ getFileLength object file = reinterpret_cast(arguments[1]); object path = cast(file, cp->filePathField); - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); replace('\\', '/', RUNTIME_ARRAY_BODY(p)); @@ -664,12 +656,11 @@ getFileLength return 0; } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - reinterpret_cast(arguments[0]), file); - - return (r ? longValue(t, r) : 0); + return longValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + reinterpret_cast(arguments[0]), file)); } } @@ -681,27 +672,24 @@ openFile(Thread* t, object method, uintptr_t* arguments) MyClasspath* cp = static_cast(t->m->classpath); - RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); + THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); replace('\\', '/', RUNTIME_ARRAY_BODY(p)); EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path)); if (ef.jar) { if (ef.jarLength == 0 or ef.pathLength == 0) { - t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); - return; + throwNew(t, Machine::FileNotFoundExceptionType); } Finder* finder = getFinder(t, ef.jar, ef.jarLength); if (finder == 0) { - t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); - return; + throwNew(t, Machine::FileNotFoundExceptionType); } System::Region* r = finder->find(ef.path); if (r == 0) { - t->exception = makeThrowable(t, Machine::FileNotFoundExceptionType); - return; + throwNew(t, Machine::FileNotFoundExceptionType); } PROTECT(t, this_); @@ -768,16 +756,14 @@ readByteFromFile(Thread* t, object method, uintptr_t* arguments) return -1; } } else { - t->exception = makeThrowable(t, Machine::IoExceptionType); - return 0; + throwNew(t, Machine::IoExceptionType); } } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - this_); - - return r ? intValue(t, r) : 0; + return intValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + this_)); } } @@ -822,16 +808,14 @@ readBytesFromFile(Thread* t, object method, uintptr_t* arguments) return length; } else { - t->exception = makeThrowable(t, Machine::IoExceptionType); - return 0; + throwNew(t, Machine::IoExceptionType); } } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - this_, dst, offset, length); - - return r ? intValue(t, r) : 0; + return intValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + this_, dst, offset, length)); } } @@ -866,16 +850,14 @@ skipBytesInFile(Thread* t, object method, uintptr_t* arguments) return count; } else { - t->exception = makeThrowable(t, Machine::IoExceptionType); - return 0; + throwNew(t, Machine::IoExceptionType); } } else { - object r = t->m->processor->invoke - (t, nativeInterceptOriginal - (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), - this_, count); - - return r ? longValue(t, r) : 0; + return longValue + (t, t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + this_, count)); } } @@ -900,8 +882,7 @@ availableBytesInFile(Thread* t, object method, uintptr_t* arguments) return static_cast(regionRegion(t, region))->length() - regionPosition(t, region); } else { - t->exception = makeThrowable(t, Machine::IoExceptionType); - return 0; + throwNew(t, Machine::IoExceptionType); } } else { object r = t->m->processor->invoke @@ -987,7 +968,7 @@ void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) { object name = reinterpret_cast(arguments[1]); - RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); + THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); bool absolute = arguments[2]; @@ -1207,14 +1188,14 @@ resolveClassBySpec(Thread* t, object loader, const char* spec, { switch (*spec) { case 'L': { - RUNTIME_ARRAY(char, s, specLength - 1); + THREAD_RUNTIME_ARRAY(t, char, s, specLength - 1); memcpy(RUNTIME_ARRAY_BODY(s), spec + 1, specLength - 2); RUNTIME_ARRAY_BODY(s)[specLength - 2] = 0; return resolveClass(t, loader, s); } case '[': { - RUNTIME_ARRAY(char, s, specLength + 1); + THREAD_RUNTIME_ARRAY(t, char, s, specLength + 1); memcpy(RUNTIME_ARRAY_BODY(s), spec, specLength); RUNTIME_ARRAY_BODY(s)[specLength] = 0; return resolveClass(t, loader, s); @@ -1228,11 +1209,7 @@ resolveClassBySpec(Thread* t, object loader, const char* spec, object resolveJType(Thread* t, object loader, const char* spec, unsigned specLength) { - object c = resolveClassBySpec(t, loader, spec, specLength); - - if (UNLIKELY(t->exception)) return 0; - - return getJClass(t, c); + return getJClass(t, resolveClassBySpec(t, loader, spec, specLength)); } object @@ -1258,9 +1235,6 @@ resolveParameterTypes(Thread* t, object loader, object spec, object type = resolveClassBySpec (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), offset - start); - if (UNLIKELY(t->exception)) { - return 0; - } list = makePair(t, type, list); @@ -1285,9 +1259,6 @@ resolveParameterTypes(Thread* t, object loader, object spec, object type = resolveClassBySpec (t, loader, reinterpret_cast(&byteArrayBody(t, spec, start)), offset - start); - if (UNLIKELY(t->exception)) { - return 0; - } list = makePair(t, type, list); ++ count; @@ -1314,8 +1285,6 @@ resolveParameterJTypes(Thread* t, object loader, object spec, object list = resolveParameterTypes (t, loader, spec, parameterCount, returnTypeSpec); - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, list); object array = makeObjectArray @@ -1356,7 +1325,6 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum) if (objectClass(t, o) == type(t, Machine::ReferenceType)) { o = resolveClass(t, loader, referenceName(t, o)); - if (UNLIKELY(t->exception)) return 0; set(t, addendumPool(t, addendum), SingletonBody + (index * BytesPerWord), o); @@ -1471,12 +1439,15 @@ Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoade object loader = reinterpret_cast(arguments[5]); //object domain = reinterpret_cast(arguments[6]); - uint8_t* buffer = static_cast - (t->m->heap->allocate(length)); - memcpy(buffer, &byteArrayBody(t, data, offset), length); - object c = defineClass(t, loader, buffer, length); + uint8_t* buffer = static_cast(t->m->heap->allocate(length)); - return c ? reinterpret_cast(getJClass(t, c)) : 0; + THREAD_RESOURCE2(t, uint8_t*, buffer, int, length, + t->m->heap->free(buffer, length)); + + memcpy(buffer, &byteArrayBody(t, data, offset), length); + + return reinterpret_cast + (getJClass(t, defineClass(t, loader, buffer, length))); } extern "C" JNIEXPORT int64_t @@ -1487,7 +1458,6 @@ Avian_sun_misc_Unsafe_allocateInstance PROTECT(t, c); initClass(t, c); - if (UNLIKELY(t->exception)) return 0; return reinterpret_cast(make(t, c)); } @@ -1707,8 +1677,7 @@ Avian_sun_misc_Unsafe_allocateMemory if (p) { return reinterpret_cast(p); } else { - t->exception = makeThrowable(t, Machine::OutOfMemoryErrorType); - return 0; + throwNew(t, Machine::OutOfMemoryErrorType); } } @@ -1819,6 +1788,10 @@ Avian_sun_misc_Unsafe_park monitorRelease(t, local::interruptLock(t, t->javaThread)); } +namespace { + +namespace local { + extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_GetInterfaceVersion)() { @@ -1857,20 +1830,36 @@ EXPORT(JVM_MonitorNotifyAll)(Thread* t, jobject o) notifyAll(t, *o); } +uint64_t +jvmClone(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + return reinterpret_cast(makeLocalReference(t, clone(t, *o))); +} + extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_Clone)(Thread* t, jobject o) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o) }; - return makeLocalReference(t, clone(t, *o)); + return reinterpret_cast(run(t, jvmClone, arguments)); +} + +uint64_t +jvmInternString(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + + return reinterpret_cast(makeLocalReference(t, intern(t, *o))); } extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_InternString)(Thread* t, jstring s) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(s) }; - return makeLocalReference(t, intern(t, *s)); + return reinterpret_cast(run(t, jvmInternString, arguments)); } extern "C" JNIEXPORT jlong JNICALL @@ -1885,28 +1874,42 @@ EXPORT(JVM_NanoTime)(Thread* t, jclass) return t->m->system->now() * 1000 * 1000; } +uint64_t +jvmArrayCopy(Thread* t, uintptr_t* arguments) +{ + jobject src = reinterpret_cast(arguments[0]); + jint srcOffset = arguments[1]; + jobject dst = reinterpret_cast(arguments[2]); + jint dstOffset = arguments[3]; + jint length = arguments[4]; + + arrayCopy(t, *src, srcOffset, *dst, dstOffset, length); + + return 1; +} + extern "C" JNIEXPORT void JNICALL EXPORT(JVM_ArrayCopy)(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, jint dstOffset, jint length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(src), + srcOffset, + reinterpret_cast(dst), + dstOffset, + length }; - arrayCopy(t, *src, srcOffset, *dst, dstOffset, length); + run(t, jvmArrayCopy, arguments); } -extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_InitProperties)(Thread* t, jobject properties) +uint64_t +jvmInitProperties(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject properties = reinterpret_cast(arguments[0]); object method = resolveMethod (t, root(t, Machine::BootLoader), "java/util/Properties", "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); - if (UNLIKELY(t->exception)) { - return 0; - } - PROTECT(t, method); #ifdef PLATFORM_WINDOWS @@ -1970,15 +1973,23 @@ EXPORT(JVM_InitProperties)(Thread* t, jobject properties) while (*p and *p != '=') ++p; if (*p == '=') { - RUNTIME_ARRAY(char, name, (p - start) + 1); + THREAD_RUNTIME_ARRAY(t, char, name, (p - start) + 1); memcpy(name, start, p - start); name[p - start] = 0; local::setProperty (t, method, *properties, RUNTIME_ARRAY_BODY(name), p + 1); } - } + } - return properties; + return reinterpret_cast(properties); +} + +extern "C" JNIEXPORT jobject JNICALL +EXPORT(JVM_InitProperties)(Thread* t, jobject properties) +{ + uintptr_t arguments[] = { reinterpret_cast(properties) }; + + return reinterpret_cast(run(t, jvmInitProperties, arguments)); } extern "C" JNIEXPORT void JNICALL @@ -1996,14 +2007,20 @@ EXPORT(JVM_Halt)(jint code) exit(code); } +uint64_t +jvmGC(Thread* t, uintptr_t*) +{ + collect(t, Heap::MajorCollection); + + return 1; +} + extern "C" JNIEXPORT void JNICALL EXPORT(JVM_GC)() { Thread* t = static_cast(local::globalMachine->localThread->get()); - ENTER(t, Thread::ActiveState); - - collect(t, Heap::MajorCollection); + run(t, jvmGC, 0); } extern "C" JNIEXPORT jlong JNICALL @@ -2039,17 +2056,28 @@ EXPORT(JVM_ActiveProcessorCount)() return 1; } +uint64_t +jvmLoadLibrary(Thread* t, uintptr_t* arguments) +{ + const char* path = reinterpret_cast(arguments[0]); + + THREAD_RUNTIME_ARRAY(t, char, p, strlen(path) + 1); + replace('\\', '/', RUNTIME_ARRAY_BODY(p), path); + + return reinterpret_cast + (loadLibrary + (t, static_cast(t->m->classpath)->libraryPath, + RUNTIME_ARRAY_BODY(p), false, false)); +} + extern "C" JNIEXPORT void* JNICALL EXPORT(JVM_LoadLibrary)(const char* path) { Thread* t = static_cast(local::globalMachine->localThread->get()); + + uintptr_t arguments[] = { reinterpret_cast(path) }; - RUNTIME_ARRAY(char, p, strlen(path) + 1); - replace('\\', '/', RUNTIME_ARRAY_BODY(p), path); - - return loadLibrary - (t, static_cast(t->m->classpath)->libraryPath, - RUNTIME_ARRAY_BODY(p), false, false); + return reinterpret_cast(run(t, jvmLoadLibrary, arguments)); } extern "C" JNIEXPORT void JNICALL @@ -2078,13 +2106,23 @@ EXPORT(JVM_IsSupportedJNIVersion)(jint version) extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_IsNaN)(jdouble) { abort(); } -extern "C" JNIEXPORT void JNICALL -EXPORT(JVM_FillInStackTrace)(Thread* t, jobject throwable) +uint64_t +jvmFillInStackTrace(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject throwable = reinterpret_cast(arguments[0]); object trace = getTrace(t, 1); set(t, *throwable, ThrowableTrace, trace); + + return 1; +} + +extern "C" JNIEXPORT void JNICALL +EXPORT(JVM_FillInStackTrace)(Thread* t, jobject throwable) +{ + uintptr_t arguments[] = { reinterpret_cast(throwable) }; + + run(t, jvmFillInStackTrace, arguments); } extern "C" JNIEXPORT void JNICALL @@ -2098,14 +2136,24 @@ EXPORT(JVM_GetStackTraceDepth)(Thread* t, jobject throwable) return objectArrayLength(t, throwableTrace(t, *throwable)); } +uint64_t +jvmGetStackTraceElement(Thread* t, uintptr_t* arguments) +{ + jobject throwable = reinterpret_cast(arguments[0]); + jint index = arguments[1]; + + return reinterpret_cast + (makeLocalReference + (t, makeStackTraceElement + (t, objectArrayBody(t, throwableTrace(t, *throwable), index)))); +} + extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetStackTraceElement)(Thread* t, jobject throwable, jint index) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(throwable), index }; - return makeLocalReference - (t, makeStackTraceElement - (t, objectArrayBody(t, throwableTrace(t, *throwable), index))); + return reinterpret_cast(run(t, jvmGetStackTraceElement, arguments)); } extern "C" JNIEXPORT void JNICALL @@ -2171,10 +2219,10 @@ EXPORT(JVM_Yield)(Thread*, jclass) #endif } -extern "C" JNIEXPORT void JNICALL -EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds) +uint64_t +jvmSleep(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jlong milliseconds; memcpy(&milliseconds, arguments, sizeof(jlong)); if (threadSleepLock(t, t->javaThread) == 0) { object lock = makeJobject(t); @@ -2184,6 +2232,17 @@ EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds) acquire(t, threadSleepLock(t, t->javaThread)); vm::wait(t, threadSleepLock(t, t->javaThread), milliseconds); release(t, threadSleepLock(t, t->javaThread)); + + return 1; +} + +extern "C" JNIEXPORT void JNICALL +EXPORT(JVM_Sleep)(Thread* t, jclass, jlong milliseconds) +{ + uintptr_t arguments[sizeof(jlong) / BytesPerWord]; + memcpy(arguments, &milliseconds, sizeof(jlong)); + + run(t, jvmSleep, arguments); } extern "C" JNIEXPORT jobject JNICALL @@ -2197,10 +2256,10 @@ EXPORT(JVM_CurrentThread)(Thread* t, jclass) extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_CountStackFrames)(Thread*, jobject) { abort(); } -extern "C" JNIEXPORT void JNICALL -EXPORT(JVM_Interrupt)(Thread* t, jobject thread) +uint64_t +jvmInterrupt(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject thread = reinterpret_cast(arguments[0]); monitorAcquire(t, local::interruptLock(t, *thread)); Thread* p = reinterpret_cast(threadPeer(t, *thread)); @@ -2210,12 +2269,23 @@ EXPORT(JVM_Interrupt)(Thread* t, jobject thread) threadInterrupted(t, *thread) = true; } monitorRelease(t, local::interruptLock(t, *thread)); + + return 1; } -extern "C" JNIEXPORT jboolean JNICALL -EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) +extern "C" JNIEXPORT void JNICALL +EXPORT(JVM_Interrupt)(Thread* t, jobject thread) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(thread) }; + + run(t, jvmInterrupt, arguments); +} + +uint64_t +jvmIsInterrupted(Thread* t, uintptr_t* arguments) +{ + jobject thread = reinterpret_cast(arguments[0]); + jboolean clear = arguments[1]; monitorAcquire(t, local::interruptLock(t, *thread)); bool v = threadInterrupted(t, *thread); @@ -2227,6 +2297,14 @@ EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) return v; } +extern "C" JNIEXPORT jboolean JNICALL +EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) +{ + uintptr_t arguments[] = { reinterpret_cast(thread), clear }; + + return run(t, jvmIsInterrupted, arguments); +} + extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_HoldsLock)(Thread*, jclass, jobject) { abort(); } @@ -2236,10 +2314,10 @@ EXPORT(JVM_DumpAllStacks)(Thread*, jclass) { abort(); } extern "C" JNIEXPORT jobjectArray JNICALL EXPORT(JVM_GetAllThreads)(Thread*, jclass) { abort(); } -extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads) +uint64_t +jvmDumpThreads(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobjectArray threads = reinterpret_cast(arguments[0]); unsigned threadsLength = objectArrayLength(t, *threads); object arrayClass = resolveObjectArrayClass @@ -2273,7 +2351,15 @@ EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads) } } - return makeLocalReference(t, result); + return reinterpret_cast(makeLocalReference(t, result)); +} + +extern "C" JNIEXPORT jobjectArray JNICALL +EXPORT(JVM_DumpThreads)(Thread* t, jclass, jobjectArray threads) +{ + uintptr_t arguments[] = { reinterpret_cast(threads) }; + + return reinterpret_cast(run(t, jvmDumpThreads, arguments)); } extern "C" JNIEXPORT jclass JNICALL @@ -2282,11 +2368,9 @@ EXPORT(JVM_CurrentLoadedClass)(Thread*) { abort(); } extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_CurrentClassLoader)(Thread*) { abort(); } -extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetClassContext)(Thread* t) +uint64_t +jvmGetClassContext(Thread* t, uintptr_t*) { - ENTER(t, Thread::ActiveState); - object trace = getTrace(t, 1); PROTECT(t, trace); @@ -2301,7 +2385,13 @@ EXPORT(JVM_GetClassContext)(Thread* t) set(t, context, ArrayBody + (i * BytesPerWord), c); } - return makeLocalReference(t, context); + return reinterpret_cast(makeLocalReference(t, context)); +} + +extern "C" JNIEXPORT jobjectArray JNICALL +EXPORT(JVM_GetClassContext)(Thread* t) +{ + return reinterpret_cast(run(t, jvmGetClassContext, 0)); } extern "C" JNIEXPORT jint JNICALL @@ -2366,10 +2456,11 @@ extern "C" JNIEXPORT void JNICALL EXPORT(JVM_SetPrimitiveArrayElement)(Thread*, jobject, jint, jvalue, unsigned char) { abort(); } -extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) +uint64_t +jvmNewArray(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jclass elementClass = reinterpret_cast(arguments[0]); + jint length = arguments[1]; object c = jclassVmClass(t, *elementClass); @@ -2380,23 +2471,41 @@ EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) switch (*name) { case 'b': if (name[1] == 'o') { - return makeLocalReference(t, makeBooleanArray(t, length)); + return reinterpret_cast + (makeLocalReference(t, makeBooleanArray(t, length))); } else { - return makeLocalReference(t, makeByteArray(t, length)); + return reinterpret_cast + (makeLocalReference(t, makeByteArray(t, length))); } - case 'c': return makeLocalReference(t, makeCharArray(t, length)); - case 'd': return makeLocalReference(t, makeDoubleArray(t, length)); - case 'f': return makeLocalReference(t, makeFloatArray(t, length)); - case 'i': return makeLocalReference(t, makeIntArray(t, length)); - case 'l': return makeLocalReference(t, makeLongArray(t, length)); - case 's': return makeLocalReference(t, makeShortArray(t, length)); + case 'c': return reinterpret_cast + (makeLocalReference(t, makeCharArray(t, length))); + case 'd': return reinterpret_cast + (makeLocalReference(t, makeDoubleArray(t, length))); + case 'f': return reinterpret_cast + (makeLocalReference(t, makeFloatArray(t, length))); + case 'i': return reinterpret_cast + (makeLocalReference(t, makeIntArray(t, length))); + case 'l': return reinterpret_cast + (makeLocalReference(t, makeLongArray(t, length))); + case 's': return reinterpret_cast + (makeLocalReference(t, makeShortArray(t, length))); default: abort(t); } } else { - return makeLocalReference(t, makeObjectArray(t, c, length)); + return reinterpret_cast + (makeLocalReference(t, makeObjectArray(t, c, length))); } } +extern "C" JNIEXPORT jobject JNICALL +EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) +{ + uintptr_t arguments[] = { reinterpret_cast(elementClass), + length }; + + return reinterpret_cast(run(t, jvmNewArray, arguments)); +} + extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_NewMultiArray)(Thread*, jclass, jintArray) { abort(); } @@ -2445,33 +2554,36 @@ EXPORT(JVM_FindPrimitiveClass)(Thread* t, const char* name) return makeLocalReference (t, getJClass(t, type(t, Machine::JvoidType))); default: - t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); - return 0; + throwNew(t, Machine::IllegalArgumentExceptionType); } } extern "C" JNIEXPORT void JNICALL EXPORT(JVM_ResolveClass)(Thread*, jclass) { abort(); } -extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, - jboolean init, jobject loader, - jboolean throwError) +uint64_t +jvmFindClassFromClassLoader(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + const char* name = reinterpret_cast(arguments[0]); + jboolean init = arguments[1]; + jobject loader = reinterpret_cast(arguments[2]); + jboolean throwError = arguments[3]; + + THREAD_RESOURCE(t, jboolean, throwError, { + if (t->exception and throwError) { + object exception = t->exception; + t->exception = 0; + + t->exception = makeThrowable + (t, Machine::NoClassDefFoundErrorType, + throwableMessage(t, exception), + throwableTrace(t, exception), + throwableCause(t, exception)); + } + }); object c = resolveClass (t, loader ? *loader : root(t, Machine::BootLoader), name); - if (t->exception) { - if (throwError) { - t->exception = makeThrowable - (t, Machine::NoClassDefFoundErrorType, - throwableMessage(t, t->exception), - throwableTrace(t, t->exception), - throwableCause(t, t->exception)); - } - return 0; - } if (init) { PROTECT(t, c); @@ -2479,7 +2591,21 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, initClass(t, c); } - return makeLocalReference(t, getJClass(t, c)); + return reinterpret_cast(makeLocalReference(t, getJClass(t, c))); +} + +extern "C" JNIEXPORT jclass JNICALL +EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, + jboolean init, jobject loader, + jboolean throwError) +{ + uintptr_t arguments[] = { reinterpret_cast(name), + init, + reinterpret_cast(loader), + throwError }; + + return reinterpret_cast + (run(t, jvmFindClassFromClassLoader, arguments)); } extern "C" JNIEXPORT jclass JNICALL @@ -2490,13 +2616,14 @@ EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name, } extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindClassFromClass)(Thread*, const char*, jboolean, - jclass) { abort(); } +EXPORT(JVM_FindClassFromClass)(Thread*, const char*, jboolean, jclass) +{ abort(); } -extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name) +uint64_t +jvmFindLoadedClass(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject loader = reinterpret_cast(arguments[0]); + jstring name = reinterpret_cast(arguments[1]); object spec = makeByteArray(t, stringLength(t, *name) + 1); @@ -2507,18 +2634,40 @@ EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name) object c = findLoadedClass(t, *loader, spec); - return c ? makeLocalReference(t, getJClass(t, c)) : 0; + return reinterpret_cast + (c ? makeLocalReference(t, getJClass(t, c)) : 0); +} + +extern "C" JNIEXPORT jclass JNICALL +EXPORT(JVM_FindLoadedClass)(Thread* t, jobject loader, jstring name) +{ + uintptr_t arguments[] = { reinterpret_cast(loader), + reinterpret_cast(name) }; + + return reinterpret_cast(run(t, jvmFindLoadedClass, arguments)); +} + +uint64_t +jvmDefineClass(Thread* t, uintptr_t* arguments) +{ + jobject loader = reinterpret_cast(arguments[0]); + const uint8_t* data = reinterpret_cast(arguments[1]); + jsize length = arguments[2]; + + return reinterpret_cast + (makeLocalReference + (t, getJClass(t, defineClass(t, *loader, data, length)))); } extern "C" JNIEXPORT jclass JNICALL EXPORT(JVM_DefineClass)(Thread* t, const char*, jobject loader, const uint8_t* data, jsize length, jobject) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(loader), + reinterpret_cast(data), + length }; - object c = defineClass(t, *loader, data, length); - - return c ? makeLocalReference(t, getJClass(t, c)) : 0; + return reinterpret_cast(run(t, jvmDefineClass, arguments)); } extern "C" JNIEXPORT jclass JNICALL @@ -2537,10 +2686,10 @@ EXPORT(JVM_GetClassName)(Thread* t, jclass c) return makeLocalReference(t, jclassName(t, *c)); } -extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c) +uint64_t +jvmGetClassInterfaces(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jclass c = reinterpret_cast(arguments[0]); object table = classInterfaceTable(t, jclassVmClass(t, *c)); if (table) { @@ -2556,13 +2705,22 @@ EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c) set(t, array, ArrayBody + (i * BytesPerWord), interface); } - return makeLocalReference(t, array); + return reinterpret_cast(makeLocalReference(t, array)); } else { - return makeLocalReference - (t, makeObjectArray(t, type(t, Machine::JclassType), 0)); + return reinterpret_cast + (makeLocalReference + (t, makeObjectArray(t, type(t, Machine::JclassType), 0))); } } +extern "C" JNIEXPORT jobjectArray JNICALL +EXPORT(JVM_GetClassInterfaces)(Thread* t, jclass c) +{ + uintptr_t arguments[] = { reinterpret_cast(c) }; + + return reinterpret_cast(run(t, jvmGetClassInterfaces, arguments)); +} + extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetClassLoader)(Thread* t, jclass c) { @@ -2618,20 +2776,23 @@ EXPORT(JVM_SetClassSigners)(Thread* t, jclass c, jobjectArray signers) set(t, runtimeData, ClassRuntimeDataSigners, *signers); } -extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_GetProtectionDomain)(Thread* t, jclass) +uint64_t +jvmGetProtectionDomain(Thread* t, uintptr_t*) { - ENTER(t, Thread::ActiveState); - object openJDK = resolveClass (t, root(t, Machine::BootLoader), "avian/OpenJDK"); - if (UNLIKELY(t->exception)) return 0; object method = resolveMethod (t, openJDK, "getProtectionDomain", "()Ljava/security/ProtectionDomain;"); - if (UNLIKELY(t->exception)) return 0; - return makeLocalReference(t, t->m->processor->invoke(t, method, 0)); + return reinterpret_cast + (makeLocalReference(t, t->m->processor->invoke(t, method, 0))); +} + +extern "C" JNIEXPORT jobject JNICALL +EXPORT(JVM_GetProtectionDomain)(Thread* t, jclass) +{ + return reinterpret_cast(run(t, jvmGetProtectionDomain, 0)); } extern "C" JNIEXPORT void JNICALL @@ -2694,10 +2855,11 @@ EXPORT(JVM_GetClassAnnotations)(Thread* t, jclass c) ? makeLocalReference(t, addendumAnnotationTable(t, addendum)) : 0; } -extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly) +uint64_t +jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; object table = classMethodTable(t, jclassVmClass(t, *c)); if (table) { @@ -2727,26 +2889,17 @@ EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly) object parameterTypes = local::resolveParameterJTypes (t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod), ¶meterCount, &returnTypeSpec); - - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, parameterTypes); object returnType = local::resolveJType (t, classLoader(t, jclassVmClass(t, *c)), reinterpret_cast (&byteArrayBody(t, methodSpec(t, vmMethod), returnTypeSpec)), byteArrayLength(t, methodSpec(t, vmMethod)) - 1 - returnTypeSpec); - - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, returnType); object exceptionTypes = local::resolveExceptionJTypes (t, classLoader(t, jclassVmClass(t, *c)), methodAddendum(t, vmMethod)); - - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, exceptionTypes); object signature = t->m->classpath->makeString @@ -2777,18 +2930,28 @@ EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly) } } - return makeLocalReference(t, array); + return reinterpret_cast(makeLocalReference(t, array)); } else { - return makeLocalReference - (t, makeObjectArray(t, type(t, Machine::JmethodType), 0)); + return reinterpret_cast + (makeLocalReference + (t, makeObjectArray(t, type(t, Machine::JmethodType), 0))); } } extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly) +EXPORT(JVM_GetClassDeclaredMethods)(Thread* t, jclass c, jboolean publicOnly) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), publicOnly }; + return reinterpret_cast + (run(t, jvmGetClassDeclaredMethods, arguments)); +} + +uint64_t +jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; object table = classFieldTable(t, jclassVmClass(t, *c)); if (table) { PROTECT(t, table); @@ -2815,11 +2978,6 @@ EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly) reinterpret_cast (&byteArrayBody(t, fieldSpec(t, vmField), 0)), byteArrayLength(t, fieldSpec(t, vmField)) - 1); - - if (UNLIKELY(t->exception)) { - return 0; - } - PROTECT(t, type); type = getJClass(t, type); @@ -2852,18 +3010,28 @@ EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly) } assert(t, ai == objectArrayLength(t, array)); - return makeLocalReference(t, array); + return reinterpret_cast(makeLocalReference(t, array)); } else { - return makeLocalReference - (t, makeObjectArray(t, type(t, Machine::JfieldType), 0)); + return reinterpret_cast + (makeLocalReference + (t, makeObjectArray(t, type(t, Machine::JfieldType), 0))); } } extern "C" JNIEXPORT jobjectArray JNICALL -EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c, - jboolean publicOnly) +EXPORT(JVM_GetClassDeclaredFields)(Thread* t, jclass c, jboolean publicOnly) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), publicOnly }; + + return reinterpret_cast + (run(t, jvmGetClassDeclaredFields, arguments)); +} + +uint64_t +jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jboolean publicOnly = arguments[1]; object table = classMethodTable(t, jclassVmClass(t, *c)); if (table) { @@ -2889,17 +3057,11 @@ EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c, object parameterTypes = local::resolveParameterJTypes (t, classLoader(t, jclassVmClass(t, *c)), methodSpec(t, vmMethod), ¶meterCount, &returnTypeSpec); - - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, parameterTypes); object exceptionTypes = local::resolveExceptionJTypes (t, classLoader(t, jclassVmClass(t, *c)), methodAddendum(t, vmMethod)); - - if (UNLIKELY(t->exception)) return 0; - PROTECT(t, exceptionTypes); object signature = t->m->classpath->makeString @@ -2929,24 +3091,36 @@ EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c, } } - return makeLocalReference(t, array); + return reinterpret_cast(makeLocalReference(t, array)); } else { - return makeLocalReference - (t, makeObjectArray(t, type(t, Machine::JconstructorType), 0)); + return reinterpret_cast + (makeLocalReference + (t, makeObjectArray(t, type(t, Machine::JconstructorType), 0))); } } +extern "C" JNIEXPORT jobjectArray JNICALL +EXPORT(JVM_GetClassDeclaredConstructors)(Thread* t, jclass c, + jboolean publicOnly) +{ + uintptr_t arguments[] = { reinterpret_cast(c), publicOnly }; + + return reinterpret_cast + (run(t, jvmGetClassDeclaredConstructors, arguments)); +} + extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_GetClassAccessFlags)(Thread* t, jclass c) { return EXPORT(JVM_GetClassModifiers)(t, c); } -extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_InvokeMethod)(Thread* t, jobject method, jobject instance, - jobjectArray arguments) +uint64_t +jvmInvokeMethod(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject method = reinterpret_cast(arguments[0]); + jobject instance = reinterpret_cast(arguments[1]); + jobjectArray args = reinterpret_cast(arguments[2]); object vmMethod = arrayBody (t, classMethodTable @@ -2960,19 +3134,30 @@ EXPORT(JVM_InvokeMethod)(Thread* t, jobject method, jobject instance, object result; if (arguments) { result = t->m->processor->invokeArray - (t, vmMethod, instance ? *instance : 0, *arguments); + (t, vmMethod, instance ? *instance : 0, *args); } else { result = t->m->processor->invoke(t, vmMethod, instance ? *instance : 0); } - return result ? makeLocalReference(t, result) : 0; + return reinterpret_cast(makeLocalReference(t, result)); } extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, jobject constructor, - jobjectArray arguments) +EXPORT(JVM_InvokeMethod)(Thread* t, jobject method, jobject instance, + jobjectArray args) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(method), + reinterpret_cast(instance), + reinterpret_cast(args) }; + + return reinterpret_cast(run(t, jvmInvokeMethod, arguments)); +} + +uint64_t +jvmNewInstanceFromConstructor(Thread* t, uintptr_t* arguments) +{ + jobject constructor = reinterpret_cast(arguments[0]); + jobjectArray args = reinterpret_cast(arguments[1]); object instance = make (t, jclassVmClass(t, jconstructorClazz(t, *constructor))); @@ -2983,17 +3168,24 @@ EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, jobject constructor, (t, jclassVmClass(t, jconstructorClazz(t, *constructor))), jconstructorSlot(t, *constructor)); - if (arguments) { - t->m->processor->invokeArray(t, method, instance, *arguments); + if (args) { + t->m->processor->invokeArray(t, method, instance, *args); } else { t->m->processor->invoke(t, method, instance); } - if (UNLIKELY(t->exception)) { - return 0; - } else { - return makeLocalReference(t, instance); - } + return reinterpret_cast(makeLocalReference(t, instance)); +} + +extern "C" JNIEXPORT jobject JNICALL +EXPORT(JVM_NewInstanceFromConstructor)(Thread* t, jobject constructor, + jobjectArray args) +{ + uintptr_t arguments[] = { reinterpret_cast(constructor), + reinterpret_cast(args) }; + + return reinterpret_cast + (run(t, jvmNewInstanceFromConstructor, arguments)); } extern "C" JNIEXPORT jobject JNICALL @@ -3079,33 +3271,72 @@ extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_ConstantPoolGetStringAt)(Thread*, jobject, jobject, jint) { abort(); } -extern "C" JNIEXPORT jstring JNICALL -EXPORT(JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index) +uint64_t +jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jobject pool = reinterpret_cast(arguments[0]); + jint index = arguments[1]; object array = singletonObject(t, *pool, index - 1); - return makeLocalReference - (t, t->m->classpath->makeString - (t, array, 0, cast(array, BytesPerWord) - 1)); + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeString + (t, array, 0, cast(array, BytesPerWord) - 1))); } -extern "C" JNIEXPORT jobject JNICALL -EXPORT(JVM_DoPrivileged) -(Thread* t, jclass, jobject action, jobject, jboolean wrapException) +extern "C" JNIEXPORT jstring JNICALL +EXPORT(JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(pool), index }; + + return reinterpret_cast + (run(t, jvmConstantPoolGetUTF8At, arguments)); +} + +void +maybeWrap(Thread* t, bool wrapException) +{ + if (t->exception + and wrapException + and not (instanceOf(t, type(t, Machine::ErrorType), t->exception) + or instanceOf + (t, type(t, Machine::RuntimeExceptionType), t->exception))) + { + object exception = t->exception; + t->exception = 0; + + PROTECT(t, exception); + + object paeClass = resolveClass + (t, root(t, Machine::BootLoader), + "java/security/PrivilegedActionException"); + PROTECT(t, paeClass); + + object paeConstructor = resolveMethod + (t, paeClass, "", "(Ljava/lang/Exception;)V"); + PROTECT(t, paeConstructor); + + object result = make(t, paeClass); + PROTECT(t, result); + + t->m->processor->invoke(t, paeConstructor, result, exception); + + t->exception = result; + } +} + +uint64_t +jvmDoPrivileged(Thread* t, uintptr_t* arguments) +{ + jobject action = reinterpret_cast(arguments[0]); + jboolean wrapException = arguments[1]; // todo: cache these class and method lookups in the t->m->classpath // object: object privilegedAction = resolveClass (t, root(t, Machine::BootLoader), "java/security/PrivilegedAction"); - - if (UNLIKELY(t->exception)) { - return 0; - } object method; if (instanceOf(t, privilegedAction, *action)) { @@ -3115,58 +3346,25 @@ EXPORT(JVM_DoPrivileged) object privilegedExceptionAction = resolveClass (t, root(t, Machine::BootLoader), "java/security/PrivilegedExceptionAction"); - - if (UNLIKELY(t->exception)) { - return 0; - } method = resolveMethod (t, privilegedExceptionAction, "run", "()Ljava/lang/Object;"); } - if (LIKELY(t->exception == 0)) { - object result = t->m->processor->invoke(t, method, *action); + THREAD_RESOURCE(t, jboolean, wrapException, maybeWrap(t, wrapException)); - if (LIKELY(t->exception == 0)) { - return makeLocalReference(t, result); - } else { - if (wrapException and not - (instanceOf(t, type(t, Machine::ErrorType), t->exception) - or instanceOf(t, type(t, Machine::RuntimeExceptionType), - t->exception))) - { - object cause = t->exception; - PROTECT(t, cause); + return reinterpret_cast + (makeLocalReference(t, t->m->processor->invoke(t, method, *action))); +} - t->exception = 0; +extern "C" JNIEXPORT jobject JNICALL +EXPORT(JVM_DoPrivileged) +(Thread* t, jclass, jobject action, jobject, jboolean wrapException) +{ + uintptr_t arguments[] = { reinterpret_cast(action), + wrapException }; - object paeClass = resolveClass - (t, root(t, Machine::BootLoader), - "java/security/PrivilegedActionException"); - - if (LIKELY(t->exception == 0)) { - PROTECT(t, paeClass); - - object paeConstructor = resolveMethod - (t, paeClass, "", "(Ljava/lang/Exception;)V"); - PROTECT(t, paeConstructor); - - if (LIKELY(t->exception == 0)) { - object result = make(t, paeClass); - PROTECT(t, result); - - t->m->processor->invoke(t, paeConstructor, result, cause); - - if (LIKELY(t->exception == 0)) { - t->exception = result; - } - } - } - } - } - } - - return 0; + return reinterpret_cast(run(t, jvmDoPrivileged, arguments)); } extern "C" JNIEXPORT jobject JNICALL @@ -3574,6 +3772,10 @@ extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) { abort(); } +} // namespace local + +} // namespace + extern "C" JNIEXPORT int jio_vsnprintf(char* dst, size_t size, const char* format, va_list a) { @@ -3622,7 +3824,7 @@ Avian_java_util_TimeZone_getSystemTimeZoneID object country = reinterpret_cast(arguments[1]); - RUNTIME_ARRAY(char, countryChars, stringLength(t, country) + 1); + THREAD_RUNTIME_ARRAY(t, char, countryChars, stringLength(t, country) + 1); stringChars(t, country, RUNTIME_ARRAY_BODY(countryChars)); local::MyClasspath* cp = static_cast(t->m->classpath); @@ -3642,7 +3844,7 @@ Avian_java_util_TimeZone_getSystemTimeZoneID return 0; } - RESOURCE(System::Region*, r, r->dispose()); + THREAD_RESOURCE(t, System::Region*, r, r->dispose()); char tmpPath[MAX_PATH + 1]; GetTempPathA(MAX_PATH, tmpPath); @@ -3653,7 +3855,7 @@ Avian_java_util_TimeZone_getSystemTimeZoneID return 0; } - RESOURCE(char*, tmpDir, rmdir(tmpDir)); + THREAD_RESOURCE(t, char*, tmpDir, rmdir(tmpDir)); char libDir[MAX_PATH + 1]; vm::snprintf(libDir, MAX_PATH, "%s/lib", tmpDir); @@ -3661,7 +3863,7 @@ Avian_java_util_TimeZone_getSystemTimeZoneID return 0; } - RESOURCE(char*, libDir, rmdir(libDir)); + THREAD_RESOURCE(t, char*, libDir, rmdir(libDir)); char file[MAX_PATH + 1]; vm::snprintf(file, MAX_PATH, "%s/tzmappings", libDir); @@ -3670,8 +3872,8 @@ Avian_java_util_TimeZone_getSystemTimeZoneID return 0; } - RESOURCE(char*, file, unlink(file)); - RESOURCE(FILE*, out, fclose(out)); + THREAD_RESOURCE(t, char*, file, unlink(file)); + THREAD_RESOURCE(t, FILE*, out, fclose(out)); if (fwrite(r->start(), 1, r->length(), out) != r->length() or fflush(out) != 0) @@ -3681,9 +3883,9 @@ Avian_java_util_TimeZone_getSystemTimeZoneID char* javaTZ = findJavaTZ_md(tmpDir, RUNTIME_ARRAY_BODY(countryChars)); if (javaTZ) { - object result = makeString(t, "%s", javaTZ); - free(javaTZ); - return reinterpret_cast(result); + THREAD_RESOURCE(t, char*, javaTZ, free(javaTZ)); + + return reinterpret_cast(makeString(t, "%s", javaTZ)); } else { return 0; } diff --git a/src/compile-x86.S b/src/compile-x86.S index 41a0d2ae07..4b79aa4e38 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -23,7 +23,7 @@ #ifdef __x86_64__ -#define THREAD_STACK 2216 +#define THREAD_STACK 2232 #if defined __MINGW32__ || defined __CYGWIN32__ @@ -306,7 +306,7 @@ LOCAL(vmJumpAndInvoke_argumentTest): #elif defined __i386__ -#define THREAD_STACK 2144 +#define THREAD_STACK 2152 #define CALLEE_SAVED_REGISTER_FOOTPRINT 16 diff --git a/src/compile.cpp b/src/compile.cpp index 686d68e1f0..6069a0dc13 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -294,7 +294,6 @@ resolveTarget(MyThread* t, void* stack, object method) PROTECT(t, class_); resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_)); - if (UNLIKELY(t->exception)) return 0; } if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) { @@ -311,7 +310,6 @@ resolveTarget(MyThread* t, object class_, unsigned index) PROTECT(t, class_); resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_)); - if (UNLIKELY(t->exception)) return 0; } return arrayBody(t, classVirtualTable(t, class_), index); @@ -910,6 +908,17 @@ class BootContext { class Context { public: + class MyResource: public Thread::Resource { + public: + MyResource(Context* c): Resource(c->thread), c(c) { } + + virtual void release() { + c->dispose(); + } + + Context* c; + }; + class MyProtector: public Thread::Protector { public: MyProtector(Context* c): Protector(c->thread), c(c) { } @@ -1125,6 +1134,9 @@ class Context { visitTable(makeVisitTable(t, &zone, method)), rootTable(makeRootTable(t, &zone, method)), subroutineTable(0), + executableAllocator(0), + executableStart(0), + executableSize(0), objectPoolCount(0), traceLogCount(0), dirtyRoots(false), @@ -1147,6 +1159,9 @@ class Context { visitTable(0), rootTable(0), subroutineTable(0), + executableAllocator(0), + executableStart(0), + executableSize(0), objectPoolCount(0), traceLogCount(0), dirtyRoots(false), @@ -1156,8 +1171,19 @@ class Context { { } ~Context() { - if (compiler) compiler->dispose(); + dispose(); + } + + void dispose() { + if (compiler) { + compiler->dispose(); + } + assembler->dispose(); + + if (executableAllocator) { + executableAllocator->free(executableStart, executableSize); + } } MyThread* thread; @@ -1173,6 +1199,9 @@ class Context { uint16_t* visitTable; uintptr_t* rootTable; Subroutine** subroutineTable; + Allocator* executableAllocator; + void* executableStart; + unsigned executableSize; unsigned objectPoolCount; unsigned traceLogCount; bool dirtyRoots; @@ -1249,10 +1278,8 @@ class Frame { } ~Frame() { - if (t->exception == 0) { - if (level > 1) { - context->eventLog.append(PopContextEvent); - } + if (level > 1) { + context->eventLog.append(PopContextEvent); } } @@ -2100,6 +2127,15 @@ unwind(MyThread* t) vmJump(ip, base, stack, t, 0, 0); } +class MyCheckpoint: public Thread::Checkpoint { + public: + MyCheckpoint(MyThread* t): Checkpoint(t) { } + + virtual void unwind() { + local::unwind(static_cast(t)); + } +}; + uintptr_t defaultThunk(MyThread* t); @@ -2135,7 +2171,6 @@ void tryInitClass(MyThread* t, object class_) { initClass(t, class_); - if (UNLIKELY(t->exception)) unwind(t); } FixedAllocator* @@ -2157,17 +2192,12 @@ findInterfaceMethodFromInstance(MyThread* t, object method, object instance) compile(t, codeAllocator(t), 0, target); } - if (UNLIKELY(t->exception)) { - unwind(t); - } else { - if (methodFlags(t, target) & ACC_NATIVE) { - t->trace->nativeMethod = target; - } - return methodAddress(t, target); + if (methodFlags(t, target) & ACC_NATIVE) { + t->trace->nativeMethod = target; } + return methodAddress(t, target); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - unwind(t); + throwNew(t, Machine::NullPointerExceptionType); } } @@ -2371,8 +2401,7 @@ divideLong(MyThread* t, int64_t b, int64_t a) if (LIKELY(b)) { return a / b; } else { - t->exception = makeThrowable(t, Machine::ArithmeticExceptionType); - unwind(t); + throwNew(t, Machine::ArithmeticExceptionType); } } @@ -2382,8 +2411,7 @@ divideInt(MyThread* t, int32_t b, int32_t a) if (LIKELY(b)) { return a / b; } else { - t->exception = makeThrowable(t, Machine::ArithmeticExceptionType); - unwind(t); + throwNew(t, Machine::ArithmeticExceptionType); } } @@ -2393,8 +2421,7 @@ moduloLong(MyThread* t, int64_t b, int64_t a) if (LIKELY(b)) { return a % b; } else { - t->exception = makeThrowable(t, Machine::ArithmeticExceptionType); - unwind(t); + throwNew(t, Machine::ArithmeticExceptionType); } } @@ -2404,8 +2431,7 @@ moduloInt(MyThread* t, int32_t b, int32_t a) if (LIKELY(b)) { return a % b; } else { - t->exception = makeThrowable(t, Machine::ArithmeticExceptionType); - unwind(t); + throwNew(t, Machine::ArithmeticExceptionType); } } @@ -2457,10 +2483,7 @@ makeBlankObjectArray(MyThread* t, object class_, int32_t length) if (length >= 0) { return reinterpret_cast(makeObjectArray(t, class_, length)); } else { - object message = makeString(t, "%d", length); - t->exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); - unwind(t); + throwNew(t, Machine::NegativeArraySizeExceptionType, "%d", length); } } @@ -2507,10 +2530,7 @@ makeBlankArray(MyThread* t, unsigned type, int32_t length) return reinterpret_cast(constructor(t, length)); } else { - object message = makeString(t, "%d", length); - t->exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); - unwind(t); + throwNew(t, Machine::NegativeArraySizeExceptionType, "%d", length); } } @@ -2543,8 +2563,7 @@ setMaybeNull(MyThread* t, object o, unsigned offset, object value) if (LIKELY(o)) { set(t, o, offset, value); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - unwind(t); + throwNew(t, Machine::NullPointerExceptionType); } } @@ -2554,8 +2573,7 @@ acquireMonitorForObject(MyThread* t, object o) if (LIKELY(o)) { acquire(t, o); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - unwind(t); + throwNew(t, Machine::NullPointerExceptionType); } } @@ -2565,8 +2583,7 @@ releaseMonitorForObject(MyThread* t, object o) if (LIKELY(o)) { release(t, o); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); - unwind(t); + throwNew(t, Machine::NullPointerExceptionType); } } @@ -2576,13 +2593,12 @@ makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* countStack, { PROTECT(t, class_); - RUNTIME_ARRAY(int32_t, counts, dimensions); + THREAD_RUNTIME_ARRAY(t, int32_t, counts, dimensions); for (int i = dimensions - 1; i >= 0; --i) { RUNTIME_ARRAY_BODY(counts)[i] = countStack[dimensions - i - 1]; if (UNLIKELY(RUNTIME_ARRAY_BODY(counts)[i] < 0)) { - object message = makeString(t, "%d", RUNTIME_ARRAY_BODY(counts)[i]); - t->exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); + throwNew(t, Machine::NegativeArraySizeExceptionType, "%d", + RUNTIME_ARRAY_BODY(counts)[i]); return 0; } } @@ -2600,14 +2616,9 @@ uint64_t makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions, int32_t offset) { - object r = makeMultidimensionalArray2 - (t, class_, static_cast(t->stack) + offset, dimensions); - - if (UNLIKELY(t->exception)) { - unwind(t); - } else { - return reinterpret_cast(r); - } + return reinterpret_cast + (makeMultidimensionalArray2 + (t, class_, static_cast(t->stack) + offset, dimensions)); } unsigned @@ -2636,50 +2647,40 @@ throwArrayIndexOutOfBounds(MyThread* t) { if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) { atomicOr(&(t->flags), Thread::TracingFlag); - t->exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType); - atomicAnd(&(t->flags), ~Thread::TracingFlag); + THREAD_RESOURCE0(t, atomicAnd(&(t->flags), ~Thread::TracingFlag)); + + throwNew(t, Machine::ArrayIndexOutOfBoundsExceptionType); } else { // not enough memory available for a new exception and stack trace // -- use a preallocated instance instead - t->exception = root(t, Machine::ArrayIndexOutOfBoundsException); + throw_(t, root(t, Machine::ArrayIndexOutOfBoundsException)); } - - unwind(t); } void NO_RETURN throwStackOverflow(MyThread* t) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); - - unwind(t); + throwNew(t, Machine::StackOverflowErrorType); } void NO_RETURN throw_(MyThread* t, object o) { if (LIKELY(o)) { - t->exception = o; + vm::throw_(t, o); } else { - t->exception = makeThrowable(t, Machine::NullPointerExceptionType); + throwNew(t, Machine::NullPointerExceptionType); } - - // printTrace(t, t->exception); - - unwind(t); } void checkCast(MyThread* t, object class_, object o) { if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, o)))) { - object message = makeString - (t, "%s as %s", + throwNew + (t, Machine::ClassCastExceptionType, "%s as %s", &byteArrayBody(t, className(t, objectClass(t, o)), 0), &byteArrayBody(t, className(t, class_), 0)); - t->exception = makeThrowable(t, Machine::ClassCastExceptionType, message); - unwind(t); } } @@ -3115,7 +3116,7 @@ integerBranch(MyThread* t, Frame* frame, object code, unsigned& ip, } saveStateAndCompile(t, frame, newIp); - return t->exception == 0; + return true; } bool @@ -3182,7 +3183,7 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, } saveStateAndCompile(t, frame, newIp); - return t->exception == 0; + return true; } bool @@ -3221,7 +3222,7 @@ void compile(MyThread* t, Frame* initialFrame, unsigned ip, int exceptionHandlerStart) { - RUNTIME_ARRAY(uint8_t, stackMap, + THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, codeMaxStack(t, methodCode(t, initialFrame->context->method))); Frame myFrame(initialFrame, RUNTIME_ARRAY_BODY(stackMap)); Frame* frame = &myFrame; @@ -3457,7 +3458,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; Compiler::Operand* length = frame->popInt(); @@ -3528,7 +3528,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; Compiler::Operand* instance = c->peek(1, 0); @@ -3565,8 +3564,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popLong(); if (not floatBranch(t, frame, code, ip, 8, false, a, b)) { - if (UNLIKELY(t->exception)) return; - frame->pushInt (c->call (c->constant @@ -3582,8 +3579,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popLong(); if (not floatBranch(t, frame, code, ip, 8, true, a, b)) { - if (UNLIKELY(t->exception)) return; - frame->pushInt (c->call (c->constant @@ -3682,8 +3677,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popInt(); if (not floatBranch(t, frame, code, ip, 4, false, a, b)) { - if (UNLIKELY(t->exception)) return; - frame->pushInt (c->call (c->constant @@ -3697,8 +3690,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popInt(); if (not floatBranch(t, frame, code, ip, 4, true, a, b)) { - if (UNLIKELY(t->exception)) return; - frame->pushInt (c->call (c->constant @@ -3756,7 +3747,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; if ((fieldFlags(t, field) & ACC_VOLATILE) and BytesPerWord == 4 @@ -4004,7 +3994,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } saveStateAndCompile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; } break; case if_icmpeq: @@ -4045,7 +4034,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } saveStateAndCompile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; } break; case ifeq: @@ -4087,7 +4075,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } saveStateAndCompile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; } break; case ifnull: @@ -4107,7 +4094,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } saveStateAndCompile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; } break; case iinc: { @@ -4161,7 +4147,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; frame->pushInt (c->call @@ -4178,7 +4163,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, ip += 2; object target = resolveMethod(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); @@ -4219,7 +4203,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object target = resolveMethod(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; object class_ = methodClass(t, context->method); if (isSpecialMethod(t, target, class_)) { @@ -4239,7 +4222,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object target = resolveMethod(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; assert(t, methodFlags(t, target) & ACC_STATIC); @@ -4255,7 +4237,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object target = resolveMethod(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); @@ -4389,7 +4370,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jmp(frame->machineIp(newIp)); saveStateAndCompile(t, frame, newIp); - if (UNLIKELY(t->exception)) return; frame->endSubroutine(start); } break; @@ -4423,8 +4403,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* b = frame->popLong(); if (not integerBranch(t, frame, code, ip, 8, a, b)) { - if (UNLIKELY(t->exception)) return; - frame->pushInt (c->call (c->constant @@ -4459,7 +4437,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object v = singletonObject(t, pool, index - 1); if (objectClass(t, v) == type(t, Machine::ReferenceType)) { v = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; } if (objectClass(t, v) == type(t, Machine::ClassType)) { @@ -4561,7 +4538,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (pairCount) { Compiler::Operand* start = 0; - RUNTIME_ARRAY(uint32_t, ipTable, pairCount); + THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, pairCount); for (int32_t i = 0; i < pairCount; ++i) { unsigned index = ip + (i * 8); int32_t key = codeReadInt32(t, code, index); @@ -4590,7 +4567,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, for (int32_t i = 0; i < pairCount; ++i) { compile(t, frame, RUNTIME_ARRAY_BODY(ipTable)[i]); - if (UNLIKELY(t->exception)) return; c->restoreState(state); } @@ -4704,7 +4680,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint8_t dimensions = codeBody(t, code, ip++); object class_ = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; PROTECT(t, class_); unsigned offset @@ -4731,7 +4706,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; if (classVmFlags(t, class_) & (WeakReferenceFlag | HasFinalizerFlag)) { frame->pushObject @@ -4786,7 +4760,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, context->method, index - 1); - if (UNLIKELY(t->exception)) return; object staticTable = 0; @@ -4986,7 +4959,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, int32_t top = codeReadInt32(t, code, ip); Compiler::Operand* start = 0; - RUNTIME_ARRAY(uint32_t, ipTable, top - bottom + 1); + THREAD_RUNTIME_ARRAY(t, uint32_t, ipTable, top - bottom + 1); for (int32_t i = 0; i < top - bottom + 1; ++i) { unsigned index = ip + (i * 4); uint32_t newIp = base + codeReadInt32(t, code, index); @@ -5032,7 +5005,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, for (int32_t i = 0; i < top - bottom + 1; ++i) { compile(t, frame, RUNTIME_ARRAY_BODY(ipTable)[i]); - if (UNLIKELY(t->exception)) return; c->restoreState(state); } @@ -5154,7 +5126,6 @@ translateExceptionHandlerTable(MyThread* t, Compiler* c, object method, if (exceptionHandlerCatchType(oldHandler)) { type = resolveClassInPool (t, method, exceptionHandlerCatchType(oldHandler) - 1); - if (UNLIKELY(t->exception)) return 0; } else { type = 0; } @@ -5277,7 +5248,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, unsigned mapSize = frameMapSizeInWords(t, context->method); - RUNTIME_ARRAY(uintptr_t, roots, mapSize); + THREAD_RUNTIME_ARRAY(t, uintptr_t, roots, mapSize); if (originalRoots) { memcpy(RUNTIME_ARRAY_BODY(roots), originalRoots, mapSize * BytesPerWord); } else { @@ -5708,7 +5679,7 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start, pathIndex = subroutine->tableIndex; - RUNTIME_ARRAY(SubroutineTrace*, traces, p->subroutineTraceCount); + THREAD_RUNTIME_ARRAY(t, SubroutineTrace*, traces, p->subroutineTraceCount); unsigned i = 0; for (SubroutineTrace* trace = p->subroutineTrace; trace; trace = trace->next) @@ -5826,11 +5797,16 @@ finish(MyThread* t, Allocator* allocator, Context* context) (context->leaf ? 0 : stackOverflowThunk(t), difference(&(t->stackLimit), t)); - uintptr_t* code = static_cast - (allocator->allocate(pad(codeSize) + pad(c->poolSize()) + BytesPerWord)); + unsigned total = pad(codeSize) + pad(c->poolSize()) + BytesPerWord; + + uintptr_t* code = static_cast(allocator->allocate(total)); code[0] = codeSize; uint8_t* start = reinterpret_cast(code + 1); + context->executableAllocator = allocator; + context->executableStart = code; + context->executableSize = total; + if (context->objectPool) { object pool = allocate3 (t, allocator, Machine::ImmortalAllocation, @@ -5868,7 +5844,7 @@ finish(MyThread* t, Allocator* allocator, Context* context) object newExceptionHandlerTable = translateExceptionHandlerTable (t, c, context->method, reinterpret_cast(start)); - if (UNLIKELY(t->exception)) return; + PROTECT(t, newExceptionHandlerTable); object newLineNumberTable = translateLineNumberTable @@ -5885,7 +5861,7 @@ finish(MyThread* t, Allocator* allocator, Context* context) } if (context->traceLogCount) { - RUNTIME_ARRAY(TraceElement*, elements, context->traceLogCount); + THREAD_RUNTIME_ARRAY(t, TraceElement*, elements, context->traceLogCount); unsigned index = 0; unsigned pathFootprint = 0; unsigned mapCount = 0; @@ -5978,7 +5954,7 @@ compile(MyThread* t, Context* context) c->init(codeLength(t, methodCode(t, context->method)), footprint, locals, alignedFrameSize(t, context->method)); - RUNTIME_ARRAY(uint8_t, stackMap, + THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, codeMaxStack(t, methodCode(t, context->method))); Frame frame(context, RUNTIME_ARRAY_BODY(stackMap)); @@ -6029,7 +6005,6 @@ compile(MyThread* t, Context* context) Compiler::State* state = c->saveState(); compile(t, &frame, 0); - if (UNLIKELY(t->exception)) return; context->dirtyRoots = false; unsigned eventIndex = calculateFrameMaps(t, context, 0, 0); @@ -6040,7 +6015,7 @@ compile(MyThread* t, Context* context) unsigned visitCount = exceptionHandlerTableLength(t, eht); - RUNTIME_ARRAY(bool, visited, visitCount); + THREAD_RUNTIME_ARRAY(t, bool, visited, visitCount); memset(RUNTIME_ARRAY_BODY(visited), 0, visitCount * sizeof(bool)); while (visitCount) { @@ -6059,7 +6034,7 @@ compile(MyThread* t, Context* context) RUNTIME_ARRAY_BODY(visited)[i] = true; progress = true; - RUNTIME_ARRAY(uint8_t, stackMap, + THREAD_RUNTIME_ARRAY(t, uint8_t, stackMap, codeMaxStack(t, methodCode(t, context->method))); Frame frame2(&frame, RUNTIME_ARRAY_BODY(stackMap)); @@ -6082,7 +6057,6 @@ compile(MyThread* t, Context* context) } compile(t, &frame2, exceptionHandlerIp(eh), start); - if (UNLIKELY(t->exception)) return; context->eventLog.append(PopContextEvent); @@ -6112,47 +6086,41 @@ compileMethod2(MyThread* t, void* ip) object node = findCallNode(t, ip); object target = callNodeTarget(t, node); - if (LIKELY(t->exception == 0)) { - PROTECT(t, node); - PROTECT(t, target); + PROTECT(t, node); + PROTECT(t, target); - t->trace->targetMethod = target; + t->trace->targetMethod = target; - compile(t, codeAllocator(t), 0, target); + THREAD_RESOURCE0(t, static_cast(t)->trace->targetMethod = 0); - t->trace->targetMethod = 0; - } + compile(t, codeAllocator(t), 0, target); - if (UNLIKELY(t->exception)) { - return 0; + uintptr_t address; + if ((methodFlags(t, target) & ACC_NATIVE) + and useLongJump(t, reinterpret_cast(ip))) + { + address = bootNativeThunk(t); } else { - uintptr_t address; - if ((methodFlags(t, target) & ACC_NATIVE) - and useLongJump(t, reinterpret_cast(ip))) - { - address = bootNativeThunk(t); - } else { - address = methodAddress(t, target); - } - uint8_t* updateIp = static_cast(ip); - - UnaryOperation op; - if (callNodeFlags(t, node) & TraceElement::LongCall) { - if (callNodeFlags(t, node) & TraceElement::TailCall) { - op = AlignedLongJump; - } else { - op = AlignedLongCall; - } - } else if (callNodeFlags(t, node) & TraceElement::TailCall) { - op = AlignedJump; - } else { - op = AlignedCall; - } - - updateCall(t, op, updateIp, reinterpret_cast(address)); - - return reinterpret_cast(address); + address = methodAddress(t, target); } + uint8_t* updateIp = static_cast(ip); + + UnaryOperation op; + if (callNodeFlags(t, node) & TraceElement::LongCall) { + if (callNodeFlags(t, node) & TraceElement::TailCall) { + op = AlignedLongJump; + } else { + op = AlignedLongCall; + } + } else if (callNodeFlags(t, node) & TraceElement::TailCall) { + op = AlignedJump; + } else { + op = AlignedCall; + } + + updateCall(t, op, updateIp, reinterpret_cast(address)); + + return reinterpret_cast(address); } uint64_t @@ -6166,13 +6134,7 @@ compileMethod(MyThread* t) ip = t->arch->frameIp(t->stack); } - void* r = compileMethod2(t, ip); - - if (UNLIKELY(t->exception)) { - unwind(t); - } else { - return reinterpret_cast(r); - } + return reinterpret_cast(compileMethod2(t, ip)); } void* @@ -6190,28 +6152,22 @@ compileVirtualMethod2(MyThread* t, object class_, unsigned index) } t->trace->targetMethod = arrayBody(t, classVirtualTable(t, c), index); + THREAD_RESOURCE0(t, static_cast(t)->trace->targetMethod = 0;); + PROTECT(t, class_); object target = resolveTarget(t, class_, index); PROTECT(t, target); - if (LIKELY(t->exception == 0)) { - compile(t, codeAllocator(t), 0, target); - } + compile(t, codeAllocator(t), 0, target); - t->trace->targetMethod = 0; - - if (UNLIKELY(t->exception)) { - return 0; + void* address = reinterpret_cast(methodAddress(t, target)); + if (methodFlags(t, target) & ACC_NATIVE) { + t->trace->nativeMethod = target; } else { - void* address = reinterpret_cast(methodAddress(t, target)); - if (methodFlags(t, target) & ACC_NATIVE) { - t->trace->nativeMethod = target; - } else { - classVtable(t, class_, methodOffset(t, target)) = address; - } - return address; + classVtable(t, class_, methodOffset(t, target)) = address; } + return address; } uint64_t @@ -6223,13 +6179,7 @@ compileVirtualMethod(MyThread* t) unsigned index = t->virtualCallIndex; t->virtualCallIndex = 0; - void* r = compileVirtualMethod2(t, class_, index); - - if (UNLIKELY(t->exception)) { - unwind(t); - } else { - return reinterpret_cast(r); - } + return reinterpret_cast(compileVirtualMethod2(t, class_, index)); } uint64_t @@ -6253,9 +6203,9 @@ invokeNativeSlow(MyThread* t, object method, void* function) } unsigned count = methodParameterCount(t, method) + 2; - RUNTIME_ARRAY(uintptr_t, args, footprint); + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); unsigned argOffset = 0; - RUNTIME_ARRAY(uint8_t, types, count); + THREAD_RUNTIME_ARRAY(t, uint8_t, types, count); unsigned typeOffset = 0; RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(t); @@ -6337,6 +6287,10 @@ invokeNativeSlow(MyThread* t, object method, void* function) { ENTER(t, Thread::IdleState); + bool noThrow = t->checkpoint->noThrow; + t->checkpoint->noThrow = true; + THREAD_RESOURCE(t, bool, noThrow, t->checkpoint->noThrow = noThrow); + result = t->m->system->call (function, RUNTIME_ARRAY_BODY(args), @@ -6360,43 +6314,45 @@ invokeNativeSlow(MyThread* t, object method, void* function) &byteArrayBody(t, methodName(t, method), 0)); } - if (LIKELY(t->exception == 0)) { - switch (returnCode) { - case ByteField: - case BooleanField: - result = static_cast(result); - break; + if (UNLIKELY(t->exception)) { + object exception = t->exception; + t->exception = 0; + vm::throw_(t, exception); + } - case CharField: - result = static_cast(result); - break; + switch (returnCode) { + case ByteField: + case BooleanField: + result = static_cast(result); + break; - case ShortField: - result = static_cast(result); - break; + case CharField: + result = static_cast(result); + break; - case FloatField: - case IntField: - result = static_cast(result); - break; + case ShortField: + result = static_cast(result); + break; - case LongField: - case DoubleField: - break; + case FloatField: + case IntField: + result = static_cast(result); + break; - case ObjectField: - result = static_cast(result) ? *reinterpret_cast - (static_cast(result)) : 0; - break; + case LongField: + case DoubleField: + break; - case VoidField: - result = 0; - break; + case ObjectField: + result = static_cast(result) ? *reinterpret_cast + (static_cast(result)) : 0; + break; - default: abort(t); - } - } else { + case VoidField: result = 0; + break; + + default: abort(t); } while (t->reference != reference) { @@ -6442,41 +6398,35 @@ invokeNative(MyThread* t) uint64_t result = 0; t->trace->targetMethod = t->trace->nativeMethod; + + THREAD_RESOURCE0(t, { + static_cast(t)->trace->targetMethod = 0; + static_cast(t)->trace->nativeMethod = 0; + }); - if (LIKELY(t->exception == 0)) { - resolveNative(t, t->trace->nativeMethod); + resolveNative(t, t->trace->nativeMethod); - if (LIKELY(t->exception == 0)) { - result = invokeNative2(t, t->trace->nativeMethod); - } - } + result = invokeNative2(t, t->trace->nativeMethod); unsigned parameterFootprint = methodParameterFootprint (t, t->trace->targetMethod); - t->trace->targetMethod = 0; - t->trace->nativeMethod = 0; + uintptr_t* stack = static_cast(t->stack); - if (UNLIKELY(t->exception)) { - unwind(t); - } else { - uintptr_t* stack = static_cast(t->stack); - - if (TailCalls - and t->arch->argumentFootprint(parameterFootprint) - > t->arch->stackAlignmentInWords()) - { - stack += t->arch->argumentFootprint(parameterFootprint) - - t->arch->stackAlignmentInWords(); - } - - stack += t->arch->frameReturnAddressSize(); - - transition(t, t->arch->frameIp(t->stack), stack, t->base, t->continuation, - t->trace); - - return result; + if (TailCalls + and t->arch->argumentFootprint(parameterFootprint) + > t->arch->stackAlignmentInWords()) + { + stack += t->arch->argumentFootprint(parameterFootprint) + - t->arch->stackAlignmentInWords(); } + + stack += t->arch->frameReturnAddressSize(); + + transition(t, t->arch->frameIp(t->stack), stack, t->base, t->continuation, + t->trace); + + return result; } void @@ -6807,7 +6757,7 @@ jumpAndInvoke(MyThread* t, object method, void* base, void* stack, ...) } unsigned argumentCount = methodParameterFootprint(t, method); - RUNTIME_ARRAY(uintptr_t, arguments, argumentCount); + THREAD_RUNTIME_ARRAY(t, uintptr_t, arguments, argumentCount); va_list a; va_start(a, stack); for (unsigned i = 0; i < argumentCount; ++i) { RUNTIME_ARRAY_BODY(arguments)[i] = va_arg(a, uintptr_t); @@ -6832,8 +6782,7 @@ callContinuation(MyThread* t, object continuation, object result, enum { Call, Unwind, - Rewind, - Throw + Rewind } action; object nextContinuation = 0; @@ -6894,25 +6843,15 @@ callContinuation(MyThread* t, object continuation, object result, "(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;" "Ljava/lang/Throwable;)V"); - if (method) { - setRoot(t, RewindMethod, method); + setRoot(t, RewindMethod, method); - compile(t, local::codeAllocator(t), 0, method); - - if (UNLIKELY(t->exception)) { - action = Throw; - } - } else { - action = Throw; - } + compile(t, local::codeAllocator(t), 0, method); } } else { action = Call; } } else { - t->exception = makeThrowable - (t, Machine::IncompatibleContinuationExceptionType); - action = Throw; + throwNew(t, Machine::IncompatibleContinuationExceptionType); } } else { action = Call; @@ -6942,12 +6881,6 @@ callContinuation(MyThread* t, object continuation, object result, continuation, result, exception); } break; - case Throw: { - transition(t, ip, stack, base, threadContinuation, t->trace); - - vmJump(ip, base, stack, t, 0, 0); - } break; - default: abort(t); } @@ -6981,24 +6914,16 @@ callWithCurrentContinuation(MyThread* t, object receiver) } } - if (LIKELY(t->exception == 0)) { - method = findInterfaceMethod - (t, root(t, ReceiveMethod), objectClass(t, receiver)); - PROTECT(t, method); + method = findInterfaceMethod + (t, root(t, ReceiveMethod), objectClass(t, receiver)); + PROTECT(t, method); - compile(t, local::codeAllocator(t), 0, method); + compile(t, local::codeAllocator(t), 0, method); - if (LIKELY(t->exception == 0)) { - t->continuation = makeCurrentContinuation(t, &ip, &base, &stack); - } - } + t->continuation = makeCurrentContinuation(t, &ip, &base, &stack); } - if (LIKELY(t->exception == 0)) { - jumpAndInvoke(t, method, base, stack, receiver, t->continuation); - } else { - unwind(t); - } + jumpAndInvoke(t, method, base, stack, receiver, t->continuation); } void @@ -7024,22 +6949,16 @@ dynamicWind(MyThread* t, object before, object thunk, object after) } } - if (LIKELY(t->exception == 0)) { - t->continuation = makeCurrentContinuation(t, &ip, &base, &stack); + t->continuation = makeCurrentContinuation(t, &ip, &base, &stack); - object newContext = makeContinuationContext - (t, continuationContext(t, t->continuation), before, after, - t->continuation, t->trace->originalMethod); + object newContext = makeContinuationContext + (t, continuationContext(t, t->continuation), before, after, + t->continuation, t->trace->originalMethod); - set(t, t->continuation, ContinuationContext, newContext); - } + set(t, t->continuation, ContinuationContext, newContext); } - if (LIKELY(t->exception == 0)) { - jumpAndInvoke(t, root(t, WindMethod), base, stack, before, thunk, after); - } else { - unwind(t); - } + jumpAndInvoke(t, root(t, WindMethod), base, stack, before, thunk, after); } class ArgumentList { @@ -7176,10 +7095,12 @@ invoke(Thread* thread, object method, ArgumentList* arguments) if (stackLimit == 0) { t->stackLimit = stackPosition - StackSizeInBytes; } else if (stackPosition < stackLimit) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); - return 0; + throwNew(t, Machine::StackOverflowErrorType); } + THREAD_RESOURCE(t, uintptr_t, stackLimit, + static_cast(t)->stackLimit = stackLimit); + unsigned returnCode = methodReturnCode(t, method); unsigned returnType = fieldType(t, returnCode); @@ -7187,6 +7108,8 @@ invoke(Thread* thread, object method, ArgumentList* arguments) { MyThread::CallTrace trace(t, method); + MyCheckpoint checkpoint(t); + assert(t, arguments->position == arguments->size); result = vmInvoke @@ -7199,13 +7122,14 @@ invoke(Thread* thread, object method, ArgumentList* arguments) returnType); } - t->stackLimit = stackLimit; - if (t->exception) { if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { collect(t, Heap::MinorCollection); } - return 0; + + object exception = t->exception; + t->exception = 0; + vm::throw_(t, exception); } object r; @@ -7526,7 +7450,7 @@ class MyProcessor: public Processor { virtual object invokeArray(Thread* t, object method, object this_, object arguments) { - if (UNLIKELY(t->exception)) return 0; + assert(t, t->exception == 0); assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); @@ -7539,8 +7463,8 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); unsigned size = methodParameterFootprint(t, method); - RUNTIME_ARRAY(uintptr_t, array, size); - RUNTIME_ARRAY(bool, objectMask, size); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); ArgumentList list (t, RUNTIME_ARRAY_BODY(array), size, RUNTIME_ARRAY_BODY(objectMask), this_, spec, arguments); @@ -7550,18 +7474,14 @@ class MyProcessor: public Processor { compile(static_cast(t), local::codeAllocator(static_cast(t)), 0, method); - if (LIKELY(t->exception == 0)) { - return local::invoke(t, method, &list); - } - - return 0; + return local::invoke(t, method, &list); } virtual object invokeList(Thread* t, object method, object this_, bool indirectObjects, va_list arguments) { - if (UNLIKELY(t->exception)) return 0; + assert(t, t->exception == 0); assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); @@ -7574,8 +7494,8 @@ class MyProcessor: public Processor { (&byteArrayBody(t, methodSpec(t, method), 0)); unsigned size = methodParameterFootprint(t, method); - RUNTIME_ARRAY(uintptr_t, array, size); - RUNTIME_ARRAY(bool, objectMask, size); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); ArgumentList list (t, RUNTIME_ARRAY_BODY(array), size, RUNTIME_ARRAY_BODY(objectMask), this_, spec, indirectObjects, arguments); @@ -7585,11 +7505,7 @@ class MyProcessor: public Processor { compile(static_cast(t), local::codeAllocator(static_cast(t)), 0, method); - if (LIKELY(t->exception == 0)) { - return local::invoke(t, method, &list); - } - - return 0; + return local::invoke(t, method, &list); } virtual object @@ -7597,34 +7513,29 @@ class MyProcessor: public Processor { const char* methodName, const char* methodSpec, object this_, va_list arguments) { - if (UNLIKELY(t->exception)) return 0; + assert(t, t->exception == 0); assert(t, t->state == Thread::ActiveState or t->state == Thread::ExclusiveState); unsigned size = parameterFootprint(t, methodSpec, this_ == 0); - RUNTIME_ARRAY(uintptr_t, array, size); - RUNTIME_ARRAY(bool, objectMask, size); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); ArgumentList list (t, RUNTIME_ARRAY_BODY(array), size, RUNTIME_ARRAY_BODY(objectMask), this_, methodSpec, false, arguments); object method = resolveMethod (t, loader, className, methodName, methodSpec); - if (LIKELY(t->exception == 0)) { - assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); - PROTECT(t, method); + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + + PROTECT(t, method); - compile(static_cast(t), - local::codeAllocator(static_cast(t)), 0, method); + compile(static_cast(t), + local::codeAllocator(static_cast(t)), 0, method); - if (LIKELY(t->exception == 0)) { - return local::invoke(t, method, &list); - } - } - - return 0; + return local::invoke(t, method, &list); } virtual void dispose(Thread* vmt) { @@ -8762,7 +8673,6 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, if (bootContext == 0) { initClass(t, methodClass(t, method)); - if (UNLIKELY(t->exception)) return; } if (methodAddress(t, method) != defaultThunk(t)) { @@ -8790,7 +8700,6 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, Context context(t, bootContext, clone); compile(t, &context); - if (UNLIKELY(t->exception)) return; { object ehTable = codeExceptionHandlerTable(t, methodCode(t, clone)); @@ -8804,7 +8713,6 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, if (exceptionHandlerCatchType(handler)) { resolveClassInPool (t, clone, exceptionHandlerCatchType(handler) - 1); - if (UNLIKELY(t->exception)) return; } } } @@ -8817,7 +8725,6 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, } finish(t, allocator, &context); - if (UNLIKELY(t->exception)) return; if (DebugMethodTree) { fprintf(stderr, "insert method at %p\n", @@ -8849,6 +8756,11 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, = reinterpret_cast(methodCompiled(t, clone)); } + // we've compiled the method and inserted it into the tree without + // error, so we ensure that the executable area not be deallocated + // when we dispose of the context: + context.executableAllocator = 0; + treeUpdate(t, root(t, MethodTree), methodCompiled(t, clone), method, root(t, MethodTreeSentinal), compareIpToMethodBounds); } diff --git a/src/continuations-x86.S b/src/continuations-x86.S index f0688a9e51..de30be72ac 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2224 +#define THREAD_CONTINUATION 2240 #define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232 -#define THREAD_EXCEPTION_OFFSET 2240 -#define THREAD_EXCEPTION_HANDLER 2248 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2248 +#define THREAD_EXCEPTION_OFFSET 2256 +#define THREAD_EXCEPTION_HANDLER 2264 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 @@ -89,11 +89,11 @@ LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 2148 +#define THREAD_CONTINUATION 2156 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2152 -#define THREAD_EXCEPTION_OFFSET 2156 -#define THREAD_EXCEPTION_HANDLER 2160 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 +#define THREAD_EXCEPTION_OFFSET 2164 +#define THREAD_EXCEPTION_HANDLER 2168 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/heap.cpp b/src/heap.cpp index f8969caa98..7f923da02d 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -68,6 +68,7 @@ void assert(Context*, bool); System* system(Context*); void* tryAllocate(Context* c, unsigned size); +void* allocate(Context* c, unsigned size); void free(Context* c, const void* p, unsigned size); void outOfMemory(Context*); @@ -360,7 +361,9 @@ class Segment { break; } } else { - outOfMemory(context); + data = static_cast + (local::allocate + (context, (footprint(capacity_)) * BytesPerWord)); } } } @@ -1710,7 +1713,7 @@ collect(Context* c) } void* -tryAllocate(Context* c, unsigned size) +allocate(Context* c, unsigned size, bool limit) { ACQUIRE(c->lock); @@ -1718,7 +1721,7 @@ tryAllocate(Context* c, unsigned size) size = pad(size) + 2 * BytesPerWord; } - if (size + c->count < c->limit) { + if ((not limit) or size + c->count < c->limit) { void* p = c->system->tryAllocate(size); if (p) { c->count += size; @@ -1735,6 +1738,18 @@ tryAllocate(Context* c, unsigned size) return 0; } +void* +tryAllocate(Context* c, unsigned size) +{ + return allocate(c, size, true); +} + +void* +allocate(Context* c, unsigned size) +{ + return allocate(c, size, false); +} + void free(Context* c, const void* p, unsigned size) { @@ -1787,16 +1802,16 @@ class MyHeap: public Heap { c.immortalHeapEnd = start + sizeInWords; } + virtual bool limitExceeded() { + return c.count > c.limit; + } + virtual void* tryAllocate(unsigned size) { return local::tryAllocate(&c, size); } virtual void* allocate(unsigned size) { - void* p = local::tryAllocate(&c, size); - if (p == 0) { - c.client->outOfMemory(); - } - return p; + return local::allocate(&c, size); } virtual void free(const void* p, unsigned size) { diff --git a/src/heap.h b/src/heap.h index a045fd9526..3f454d6be0 100644 --- a/src/heap.h +++ b/src/heap.h @@ -54,6 +54,7 @@ class Heap: public Allocator { virtual void setClient(Client* client) = 0; virtual void setImmortalHeap(uintptr_t* start, unsigned sizeInWords) = 0; + virtual bool limitExceeded() = 0; virtual void collect(CollectionType type, unsigned footprint) = 0; virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, bool objectMask, unsigned* totalInBytes) = 0; diff --git a/src/interpret.cpp b/src/interpret.cpp index fd1bbcbcf3..7ca4fcb0a2 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -375,7 +375,7 @@ popFrame(Thread* t) if (UNLIKELY(methodVmFlags(t, method) & ClassInitFlag) and t->classInitList and t->classInitList->class_ == methodClass(t, method)) - { + { t->classInitList->pop(); postInitClass(t, methodClass(t, method)); @@ -435,7 +435,7 @@ checkStack(Thread* t, object method) + codeMaxStack(t, methodCode(t, method)) > StackSizeInWords / 2)) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); + throwNew(t, Machine::StackOverflowErrorType); } } @@ -570,9 +570,9 @@ invokeNativeSlow(Thread* t, object method, void* function) } unsigned count = methodParameterCount(t, method) + 2; - RUNTIME_ARRAY(uintptr_t, args, footprint); + THREAD_RUNTIME_ARRAY(t, uintptr_t, args, footprint); unsigned argOffset = 0; - RUNTIME_ARRAY(uint8_t, types, count); + THREAD_RUNTIME_ARRAY(t, uint8_t, types, count); unsigned typeOffset = 0; RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(t); @@ -613,6 +613,10 @@ invokeNativeSlow(Thread* t, object method, void* function) { ENTER(t, Thread::IdleState); + bool noThrow = t->checkpoint->noThrow; + t->checkpoint->noThrow = true; + THREAD_RESOURCE(t, bool, noThrow, t->checkpoint->noThrow = noThrow); + result = t->m->system->call (function, RUNTIME_ARRAY_BODY(args), @@ -633,7 +637,9 @@ invokeNativeSlow(Thread* t, object method, void* function) popFrame(t); if (UNLIKELY(t->exception)) { - return VoidField; + object exception = t->exception; + t->exception = 0; + throw_(t, exception); } pushResult(t, returnCode, result, true); @@ -648,10 +654,6 @@ invokeNative(Thread* t, object method) resolveNative(t, method); - if (UNLIKELY(t->exception)) { - return VoidField; - } - object native = methodRuntimeDataNative(t, getMethodRuntimeData(t, method)); if (nativeFast(t, native)) { pushFrame(t, method); @@ -673,10 +675,6 @@ invokeNative(Thread* t, object method) popFrame(t); - if (UNLIKELY(t->exception)) { - return VoidField; - } - pushResult(t, methodReturnCode(t, method), result, false); return methodReturnCode(t, method); @@ -802,10 +800,8 @@ pushField(Thread* t, object target, object field) } object -interpret(Thread* t) +interpret3(Thread* t, const int base) { - const int base = t->frame; - unsigned instruction = nop; unsigned& ip = t->ip; unsigned& sp = t->sp; @@ -858,10 +854,9 @@ interpret(Thread* t) { pushObject(t, objectArrayBody(t, array, index)); } else { - object message = makeString - (t, "%d not in [0,%d)", index, objectArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, objectArrayLength(t, array)); goto throw_; } } else { @@ -881,10 +876,9 @@ interpret(Thread* t) { set(t, array, ArrayBody + (index * BytesPerWord), value); } else { - object message = makeString - (t, "%d not in [0,%d)", index, objectArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, objectArrayLength(t, array)); goto throw_; } } else { @@ -924,13 +918,11 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; pushObject(t, makeObjectArray(t, class_, count)); } else { - object message = makeString(t, "%d", count); exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); + (t, Machine::NegativeArraySizeExceptionType, "%d", count); goto throw_; } } goto loop; @@ -995,10 +987,9 @@ interpret(Thread* t) { pushInt(t, booleanArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - booleanArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, + "%d not in [0,%d)", index, booleanArrayLength(t, array)); goto throw_; } } else { @@ -1008,11 +999,9 @@ interpret(Thread* t) { pushInt(t, byteArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - byteArrayLength(t, array)); - exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, + "%d not in [0,%d)", index, byteArrayLength(t, array)); goto throw_; } } @@ -1035,10 +1024,9 @@ interpret(Thread* t) { booleanArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - booleanArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, + "%d not in [0,%d)", index, booleanArrayLength(t, array)); goto throw_; } } else { @@ -1047,10 +1035,9 @@ interpret(Thread* t) { byteArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - byteArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, + "%d not in [0,%d)", index, byteArrayLength(t, array)); goto throw_; } } @@ -1074,10 +1061,9 @@ interpret(Thread* t) { pushInt(t, charArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - charArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, charArrayLength(t, array)); goto throw_; } } else { @@ -1097,10 +1083,9 @@ interpret(Thread* t) { charArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - charArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, charArrayLength(t, array)); goto throw_; } } else { @@ -1117,13 +1102,11 @@ interpret(Thread* t) if (UNLIKELY(exception)) goto throw_; if (not instanceOf(t, class_, peekObject(t, sp - 1))) { - object message = makeString - (t, "%s as %s", + exception = makeThrowable + (t, Machine::ClassCastExceptionType, "%s as %s", &byteArrayBody (t, className(t, objectClass(t, peekObject(t, sp - 1))), 0), &byteArrayBody(t, className(t, class_), 0)); - exception = makeThrowable - (t, Machine::ClassCastExceptionType, message); goto throw_; } } @@ -1158,10 +1141,9 @@ interpret(Thread* t) { pushLong(t, doubleArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - doubleArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, doubleArrayLength(t, array)); goto throw_; } } else { @@ -1181,10 +1163,9 @@ interpret(Thread* t) { memcpy(&doubleArrayBody(t, array, index), &value, sizeof(uint64_t)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - doubleArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, doubleArrayLength(t, array)); goto throw_; } } else { @@ -1360,10 +1341,9 @@ interpret(Thread* t) { pushInt(t, floatArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - floatArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, floatArrayLength(t, array)); goto throw_; } } else { @@ -1383,10 +1363,9 @@ interpret(Thread* t) { memcpy(&floatArrayBody(t, array, index), &value, sizeof(uint32_t)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - floatArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, floatArrayLength(t, array)); goto throw_; } } else { @@ -1476,7 +1455,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); @@ -1511,7 +1489,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; assert(t, fieldFlags(t, field) & ACC_STATIC); @@ -1592,10 +1569,9 @@ interpret(Thread* t) { pushInt(t, intArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - intArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, intArrayLength(t, array)); goto throw_; } } else { @@ -1622,10 +1598,9 @@ interpret(Thread* t) { intArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - intArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, intArrayLength(t, array)); goto throw_; } } else { @@ -1874,7 +1849,6 @@ interpret(Thread* t) if (peekObject(t, sp - 1)) { object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; if (instanceOf(t, class_, popObject(t))) { pushInt(t, 1); @@ -1893,7 +1867,6 @@ interpret(Thread* t) ip += 2; object method = resolveMethod(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; unsigned parameterFootprint = methodParameterFootprint(t, method); if (LIKELY(peekObject(t, sp - parameterFootprint))) { @@ -1910,7 +1883,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; unsigned parameterFootprint = methodParameterFootprint(t, method); if (LIKELY(peekObject(t, sp - parameterFootprint))) { @@ -1935,7 +1907,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; PROTECT(t, method); if (UNLIKELY(classInit(t, methodClass(t, method), 3))) goto invoke; @@ -1947,7 +1918,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object method = resolveMethod(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; unsigned parameterFootprint = methodParameterFootprint(t, method); if (LIKELY(peekObject(t, sp - parameterFootprint))) { @@ -2096,10 +2066,9 @@ interpret(Thread* t) { pushLong(t, longArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - longArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, longArrayLength(t, array)); goto throw_; } } else { @@ -2126,10 +2095,9 @@ interpret(Thread* t) { longArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - longArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, longArrayLength(t, array)); goto throw_; } } else { @@ -2170,7 +2138,6 @@ interpret(Thread* t) if (objectClass(t, v) == type(t, Machine::ReferenceType)) { object class_ = resolveClassInPool (t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; pushObject(t, getJClass(t, class_)); } else if (objectClass(t, v) == type(t, Machine::ClassType)) { @@ -2389,16 +2356,14 @@ interpret(Thread* t) uint8_t dimensions = codeBody(t, code, ip++); object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; PROTECT(t, class_); int32_t counts[dimensions]; for (int i = dimensions - 1; i >= 0; --i) { counts[i] = popInt(t); if (UNLIKELY(counts[i] < 0)) { - object message = makeString(t, "%d", counts[i]); exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); + (t, Machine::NegativeArraySizeExceptionType, "%d", counts[i]); goto throw_; } } @@ -2416,7 +2381,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; PROTECT(t, class_); if (UNLIKELY(classInit(t, class_, 3))) goto invoke; @@ -2470,9 +2434,8 @@ interpret(Thread* t) pushObject(t, array); } else { - object message = makeString(t, "%d", count); exception = makeThrowable - (t, Machine::NegativeArraySizeExceptionType, message); + (t, Machine::NegativeArraySizeExceptionType, "%d", count); goto throw_; } } goto loop; @@ -2491,7 +2454,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); PROTECT(t, field); @@ -2582,7 +2544,6 @@ interpret(Thread* t) uint16_t index = codeReadInt16(t, code, ip); object field = resolveField(t, frameMethod(t, frame), index - 1); - if (UNLIKELY(exception)) goto throw_; assert(t, fieldFlags(t, field) & ACC_STATIC); @@ -2683,10 +2644,9 @@ interpret(Thread* t) { pushInt(t, shortArrayBody(t, array, index)); } else { - object message = makeString(t, "%d not in [0,%d)", index, - shortArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, shortArrayLength(t, array)); goto throw_; } } else { @@ -2706,10 +2666,9 @@ interpret(Thread* t) { shortArrayBody(t, array, index) = value; } else { - object message = makeString(t, "%d not in [0,%d)", index, - shortArrayLength(t, array)); exception = makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType, message); + (t, Machine::ArrayIndexOutOfBoundsExceptionType, "%d not in [0,%d)", + index, shortArrayLength(t, array)); goto throw_; } } else { @@ -2771,7 +2730,6 @@ interpret(Thread* t) resolveClass(t, classLoader(t, methodClass(t, frameMethod(t, frame))), className(t, class_)); - if (UNLIKELY(exception)) goto throw_; ip -= 3; } goto loop; @@ -2822,11 +2780,8 @@ interpret(Thread* t) invoke: { if (methodFlags(t, code) & ACC_NATIVE) { invokeNative(t, code); - if (UNLIKELY(exception)) goto throw_; } else { checkStack(t, code); - if (UNLIKELY(exception)) goto throw_; - pushFrame(t, code); } } goto loop; @@ -2851,6 +2806,39 @@ interpret(Thread* t) return 0; } +uint64_t +interpret2(vm::Thread* t, uintptr_t* arguments) +{ + int base = arguments[0]; + bool* success = reinterpret_cast(arguments[1]); + + object r = interpret3(static_cast(t), base); + *success = true; + return reinterpret_cast(r); +} + +object +interpret(Thread* t) +{ + const int base = t->frame; + + while (true) { + bool success = false; + uintptr_t arguments[] = { base, reinterpret_cast(&success) }; + + uint64_t r = run(t, interpret2, arguments); + if (success) { + if (t->exception) { + object exception = t->exception; + t->exception = 0; + throw_(t, exception); + } else { + return reinterpret_cast(r); + } + } + } +} + void pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects, va_list a) @@ -2957,47 +2945,45 @@ invoke(Thread* t, object method) if (methodFlags(t, method) & ACC_NATIVE) { unsigned returnCode = invokeNative(t, method); - if (LIKELY(t->exception == 0)) { - switch (returnCode) { - case ByteField: - case BooleanField: - case CharField: - case ShortField: - case FloatField: - case IntField: - result = makeInt(t, popInt(t)); - break; + switch (returnCode) { + case ByteField: + case BooleanField: + case CharField: + case ShortField: + case FloatField: + case IntField: + result = makeInt(t, popInt(t)); + break; - case LongField: - case DoubleField: - result = makeLong(t, popLong(t)); - break; + case LongField: + case DoubleField: + result = makeLong(t, popLong(t)); + break; - case ObjectField: - result = popObject(t); - break; + case ObjectField: + result = popObject(t); + break; - case VoidField: - result = 0; - break; + case VoidField: + result = 0; + break; - default: - abort(t); - }; - } + default: + abort(t); + }; } else { checkStack(t, method); - if (LIKELY(t->exception == 0)) { - pushFrame(t, method); - result = interpret(t); - if (LIKELY(t->exception == 0)) { - popFrame(t); - } - } - } + pushFrame(t, method); - if (UNLIKELY(t->exception)) { - return 0; + result = interpret(t); + + if (LIKELY(t->exception == 0)) { + popFrame(t); + } else { + object exception = t->exception; + t->exception = 0; + throw_(t, exception); + } } return result; @@ -3155,8 +3141,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 > StackSizeInWords / 2)) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); - return 0; + throwNew(t, Machine::StackOverflowErrorType); } const char* spec = reinterpret_cast @@ -3180,8 +3165,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 > StackSizeInWords / 2)) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); - return 0; + throwNew(t, Machine::StackOverflowErrorType); } const char* spec = reinterpret_cast @@ -3204,8 +3188,7 @@ class MyProcessor: public Processor { if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) > StackSizeInWords / 2)) { - t->exception = makeThrowable(t, Machine::StackOverflowErrorType); - return 0; + throwNew(t, Machine::StackOverflowErrorType); } pushArguments(t, this_, methodSpec, false, arguments); @@ -3213,13 +3196,9 @@ class MyProcessor: public Processor { object method = resolveMethod (t, loader, className, methodName, methodSpec); - if (LIKELY(t->exception == 0)) { - assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); - return ::invoke(t, method); - } else { - return 0; - } + return ::invoke(t, method); } virtual object getStackTrace(vm::Thread*, vm::Thread*) { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 43baf82d92..5a80e8d216 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -71,11 +71,9 @@ DetachCurrentThread(Machine* m) } } -jint JNICALL -DestroyJavaVM(Machine* m) +uint64_t +destroyJavaVM(Thread* t, uintptr_t*) { - Thread* t; AttachCurrentThread(m, &t, 0); - // wait for other non-daemon threads to exit { ACQUIRE(t, t->m->stateLock); while (t->m->liveCount - t->m->daemonCount > 1) { @@ -83,16 +81,22 @@ DestroyJavaVM(Machine* m) } } - { ENTER(t, Thread::ActiveState); + shutDown(t); - shutDown(t); + return 1; +} + +jint JNICALL +DestroyJavaVM(Machine* m) +{ + Thread* t; AttachCurrentThread(m, &t, 0); + + if (run(t, destroyJavaVM, 0)) { + t->exit(); + return 0; + } else { + return -1; } - - int exitCode = (t->exception ? -1 : 0); - - t->exit(); - - return exitCode; } jint JNICALL @@ -233,12 +237,11 @@ GetArrayLength(Thread* t, jarray array) return cast(*array, BytesPerWord); } -jstring JNICALL -NewString(Thread* t, const jchar* chars, jsize size) +uint64_t +newString(Thread* t, uintptr_t* arguments) { - if (chars == 0) return 0; - - ENTER(t, Thread::ActiveState); + const jchar* chars = reinterpret_cast(arguments[0]); + jsize size = arguments[1]; object a = 0; if (size) { @@ -246,7 +249,31 @@ NewString(Thread* t, const jchar* chars, jsize size) memcpy(&charArrayBody(t, a, 0), chars, size * sizeof(jchar)); } - return makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size)); + return reinterpret_cast + (makeLocalReference(t, t->m->classpath->makeString(t, a, 0, size))); +} + +jstring JNICALL +NewString(Thread* t, const jchar* chars, jsize size) +{ + if (chars == 0) return 0; + + uintptr_t arguments[] = { reinterpret_cast(chars), size }; + + return reinterpret_cast(run(t, newString, arguments)); +} + +uint64_t +newStringUTF(Thread* t, uintptr_t* arguments) +{ + const char* chars = reinterpret_cast(arguments[0]); + + object array = parseUtf8(t, chars, strlen(chars)); + + return reinterpret_cast + (makeLocalReference + (t, t->m->classpath->makeString + (t, array, 0, cast(array, BytesPerWord) - 1))); } jstring JNICALL @@ -254,13 +281,9 @@ NewStringUTF(Thread* t, const char* chars) { if (chars == 0) return 0; - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(chars) }; - object array = parseUtf8(t, chars, strlen(chars)); - - return makeLocalReference - (t, t->m->classpath->makeString - (t, array, 0, cast(array, BytesPerWord) - 1)); + return reinterpret_cast(run(t, newStringUTF, arguments)); } void @@ -274,45 +297,63 @@ replace(int a, int b, const char* in, int8_t* out) *out = 0; } +uint64_t +defineClass(Thread* t, uintptr_t* arguments) +{ + jobject loader = reinterpret_cast(arguments[0]); + const uint8_t* buffer = reinterpret_cast(arguments[1]); + jsize length = arguments[2]; + + return reinterpret_cast + (makeLocalReference + (t, getJClass + (t, defineClass + (t, loader ? *loader : root(t, Machine::BootLoader), buffer, length)))); +} + jclass JNICALL DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(loader), + reinterpret_cast(buffer), + length }; - object c = defineClass - (t, loader ? *loader : root(t, Machine::BootLoader), - reinterpret_cast(buffer), length); - - return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c)); + return reinterpret_cast(run(t, defineClass, arguments)); } -jclass JNICALL -FindClass(Thread* t, const char* name) +uint64_t +findClass(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + const char* name = reinterpret_cast(arguments[0]); object n = makeByteArray(t, strlen(name) + 1); replace('.', '/', name, &byteArrayBody(t, n, 0)); object caller = getCaller(t, 0); - object c = resolveClass - (t, caller ? classLoader(t, methodClass(t, caller)) - : root(t, Machine::AppLoader), n); - - return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c)); + return reinterpret_cast + (makeLocalReference + (t, getJClass + (t, resolveClass + (t, caller ? classLoader(t, methodClass(t, caller)) + : root(t, Machine::AppLoader), n)))); } -jint JNICALL -ThrowNew(Thread* t, jclass c, const char* message) +jclass JNICALL +FindClass(Thread* t, const char* name) { - if (t->exception) { - return -1; - } + uintptr_t arguments[] = { reinterpret_cast(name) }; + + return reinterpret_cast(run(t, findClass, arguments)); +} + +uint64_t +throwNew(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* message = reinterpret_cast(arguments[1]); - ENTER(t, Thread::ActiveState); - object m = 0; PROTECT(t, m); @@ -327,7 +368,20 @@ ThrowNew(Thread* t, jclass c, const char* message) set(t, t->exception, ThrowableMessage, m); set(t, t->exception, ThrowableTrace, trace); - return 0; + return 1; +} + +jint JNICALL +ThrowNew(Thread* t, jclass c, const char* message) +{ + if (t->exception) { + return -1; + } + + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(message) }; + + return run(t, throwNew, arguments) ? 0 : -1; } jint JNICALL @@ -429,15 +483,40 @@ methodID(Thread* t, object method) return methodNativeID(t, method); } +uint64_t +getMethodID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); + + object method = findMethod(t, c, name, spec); + + assert(t, (methodFlags(t, method) & ACC_STATIC) == 0); + + return methodID(t, method); +} + jmethodID JNICALL GetMethodID(Thread* t, jclass c, const char* name, const char* spec) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec) }; + + return run(t, getMethodID, arguments); +} + +uint64_t +getStaticMethodID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); object method = findMethod(t, c, name, spec); - if (UNLIKELY(t->exception)) return 0; - assert(t, (methodFlags(t, method) & ACC_STATIC) == 0); + assert(t, methodFlags(t, method) & ACC_STATIC); return methodID(t, method); } @@ -445,14 +524,11 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec) jmethodID JNICALL GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec) }; - object method = findMethod(t, c, name, spec); - if (UNLIKELY(t->exception)) return 0; - - assert(t, methodFlags(t, method) & ACC_STATIC); - - return methodID(t, method); + return run(t, getStaticMethodID, arguments); } inline object @@ -465,17 +541,29 @@ getMethod(Thread* t, jmethodID m) return method; } -jobject JNICALL -NewObjectV(Thread* t, jclass c, jmethodID m, va_list a) +uint64_t +newObjectV(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jclass c = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); object o = make(t, jclassVmClass(t, *c)); PROTECT(t, o); - t->m->processor->invokeList(t, getMethod(t, m), o, true, a); + t->m->processor->invokeList(t, getMethod(t, m), o, true, *a); - return makeLocalReference(t, o); + return reinterpret_cast(makeLocalReference(t, o)); +} + +jobject JNICALL +NewObjectV(Thread* t, jclass c, jmethodID m, va_list a) +{ + uintptr_t arguments[] = { reinterpret_cast(c), + m, + reinterpret_cast(a) }; + + return reinterpret_cast(run(t, newObjectV, arguments)); } jobject JNICALL @@ -491,14 +579,27 @@ NewObject(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callObjectMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + object method = getMethod(t, m); + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeList(t, method, *o, true, *a))); +} + jobject JNICALL CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - return makeLocalReference - (t, t->m->processor->invokeList(t, method, *o, true, a)); + return reinterpret_cast(run(t, callObjectMethodV, arguments)); } jobject JNICALL @@ -514,14 +615,25 @@ CallObjectMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callIntMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + object method = getMethod(t, m); + return intValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); +} + jboolean JNICALL CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? (intValue(t, r) != 0) : false); + return run(t, callIntMethodV, arguments) != 0; } jboolean JNICALL @@ -540,11 +652,11 @@ CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...) jbyte JNICALL CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callIntMethodV, arguments); } jbyte JNICALL @@ -563,11 +675,11 @@ CallByteMethod(Thread* t, jobject o, jmethodID m, ...) jchar JNICALL CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callIntMethodV, arguments); } jchar JNICALL @@ -586,11 +698,11 @@ CallCharMethod(Thread* t, jobject o, jmethodID m, ...) jshort JNICALL CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callIntMethodV, arguments); } jshort JNICALL @@ -609,11 +721,11 @@ CallShortMethod(Thread* t, jobject o, jmethodID m, ...) jint JNICALL CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callIntMethodV, arguments); } jint JNICALL @@ -629,14 +741,25 @@ CallIntMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callLongMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + object method = getMethod(t, m); + return longValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); +} + jlong JNICALL CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? longValue(t, r) : 0); + return run(t, callLongMethodV, arguments); } jlong JNICALL @@ -655,11 +778,11 @@ CallLongMethod(Thread* t, jobject o, jmethodID m, ...) jfloat JNICALL CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? bitsToFloat(intValue(t, r)) : 0); + return bitsToFloat(run(t, callIntMethodV, arguments)); } jfloat JNICALL @@ -678,11 +801,11 @@ CallFloatMethod(Thread* t, jobject o, jmethodID m, ...) jdouble JNICALL CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - object r = t->m->processor->invokeList(t, method, *o, true, a); - return (r ? bitsToDouble(longValue(t, r)) : 0); + return bitsToDouble(run(t, callLongMethodV, arguments)); } jdouble JNICALL @@ -698,13 +821,27 @@ CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callVoidMethodV(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + va_list* a = reinterpret_cast(arguments[2]); + + object method = getMethod(t, m); + t->m->processor->invokeList(t, method, *o, true, *a); + + return 0; +} + void JNICALL CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; - object method = getMethod(t, m); - t->m->processor->invokeList(t, method, *o, true, a); + run(t, callVoidMethodV, arguments); } void JNICALL @@ -728,13 +865,23 @@ getStaticMethod(Thread* t, jmethodID m) return method; } +uint64_t +callStaticObjectMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a))); +} + jobject JNICALL CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - return makeLocalReference(t, t->m->processor->invokeList - (t, getStaticMethod(t, m), 0, true, a)); + return reinterpret_cast(run(t, callStaticObjectMethodV, arguments)); } jobject JNICALL @@ -750,13 +897,22 @@ CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticIntMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return intValue + (t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a)); +} + jboolean JNICALL CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? (intValue(t, r) != 0) : false); + return run(t, callStaticIntMethodV, arguments) != 0; } jboolean JNICALL @@ -775,10 +931,9 @@ CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...) jbyte JNICALL CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callStaticIntMethodV, arguments); } jbyte JNICALL @@ -797,10 +952,9 @@ CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...) jchar JNICALL CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callStaticIntMethodV, arguments); } jchar JNICALL @@ -819,10 +973,9 @@ CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...) jshort JNICALL CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callStaticIntMethodV, arguments); } jshort JNICALL @@ -841,10 +994,9 @@ CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...) jint JNICALL CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? intValue(t, r) : 0); + return run(t, callStaticIntMethodV, arguments); } jint JNICALL @@ -860,13 +1012,22 @@ CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticLongMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + return longValue + (t, t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a)); +} + jlong JNICALL CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? longValue(t, r) : 0); + return run(t, callStaticLongMethodV, arguments); } jlong JNICALL @@ -885,10 +1046,9 @@ CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...) jfloat JNICALL CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? bitsToFloat(intValue(t, r)) : 0); + return bitsToFloat(run(t, callStaticIntMethodV, arguments)); } jfloat JNICALL @@ -907,10 +1067,9 @@ CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...) jdouble JNICALL CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); - return (r ? bitsToDouble(longValue(t, r)) : 0); + return bitsToDouble(run(t, callStaticLongMethodV, arguments)); } jdouble JNICALL @@ -926,12 +1085,23 @@ CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticVoidMethodV(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + va_list* a = reinterpret_cast(arguments[1]); + + t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, *a); + + return 0; +} + void JNICALL CallStaticVoidMethodV(Thread* t, jclass, jmethodID m, va_list a) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { m, reinterpret_cast(a) }; - t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a); + run(t, callStaticVoidMethodV, arguments); } void JNICALL @@ -945,26 +1115,34 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) va_end(a); } +uint64_t +getFieldID(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + const char* name = reinterpret_cast(arguments[1]); + const char* spec = reinterpret_cast(arguments[2]); + + return fieldOffset(t, resolveField(t, jclassVmClass(t, *c), name, spec)); +} + jfieldID JNICALL GetFieldID(Thread* t, jclass c, const char* name, const char* spec) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec) }; - object field = resolveField(t, jclassVmClass(t, *c), name, spec); - if (UNLIKELY(t->exception)) return 0; - - return fieldOffset(t, field); + return run(t, getFieldID, arguments); } jfieldID JNICALL GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(name), + reinterpret_cast(spec) }; - object field = resolveField(t, jclassVmClass(t, *c), name, spec); - if (UNLIKELY(t->exception)) return 0; - - return fieldOffset(t, field); + return run(t, getFieldID, arguments); } jobject JNICALL @@ -1325,17 +1503,29 @@ ExceptionClear(Thread* t) t->exception = 0; } -jobjectArray JNICALL -NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) +uint64_t +newObjectArray(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jsize length = arguments[0]; + jclass class_ = reinterpret_cast(arguments[1]); + jobject init = reinterpret_cast(arguments[2]); object a = makeObjectArray(t, jclassVmClass(t, *class_), length); object value = (init ? *init : 0); for (jsize i = 0; i < length; ++i) { set(t, a, ArrayBody + (i * BytesPerWord), value); } - return makeLocalReference(t, a); + return reinterpret_cast(makeLocalReference(t, a)); +} + +jobjectArray JNICALL +NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) +{ + uintptr_t arguments[] = { length, + reinterpret_cast(class_), + reinterpret_cast(init) }; + + return reinterpret_cast(run(t, newObjectArray, arguments)); } jobject JNICALL @@ -1355,68 +1545,102 @@ SetObjectArrayElement(Thread* t, jobjectArray array, jsize index, set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0)); } +uint64_t +newArray(Thread* t, uintptr_t* arguments) +{ + object (*constructor)(Thread*, unsigned) + = reinterpret_cast(arguments[0]); + + jsize length = arguments[1]; + + return reinterpret_cast + (makeLocalReference(t, constructor(t, length))); +} + jbooleanArray JNICALL NewBooleanArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeBooleanArray)), + length }; - return makeLocalReference(t, makeBooleanArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); +} + +object +makeByteArray0(Thread* t, unsigned length) +{ + return makeByteArray(t, length); } jbyteArray JNICALL NewByteArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeByteArray0)), + length }; - return makeLocalReference(t, makeByteArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jcharArray JNICALL NewCharArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeCharArray)), + length }; - return makeLocalReference(t, makeCharArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jshortArray JNICALL NewShortArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeShortArray)), + length }; - return makeLocalReference(t, makeShortArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jintArray JNICALL NewIntArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeIntArray)), + length }; - return makeLocalReference(t, makeIntArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jlongArray JNICALL NewLongArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeLongArray)), + length }; - return makeLocalReference(t, makeLongArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jfloatArray JNICALL NewFloatArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeFloatArray)), + length }; - return makeLocalReference(t, makeFloatArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jdoubleArray JNICALL NewDoubleArray(Thread* t, jsize length) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(makeDoubleArray)), + length }; - return makeLocalReference(t, makeDoubleArray(t, length)); + return reinterpret_cast(run(t, newArray, arguments)); } jboolean* JNICALL @@ -1909,11 +2133,13 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint) } } -jint JNICALL -RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, - jint methodCount) +uint64_t +registerNatives(Thread* t, uintptr_t* arguments) { - ENTER(t, Thread::ActiveState); + jclass c = reinterpret_cast(arguments[0]); + const JNINativeMethod* methods + = reinterpret_cast(arguments[1]); + jint methodCount = arguments[2]; for (int i = 0; i < methodCount; ++i) { if (methods[i].function) { @@ -1930,7 +2156,18 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, } } - return 0; + return 1; +} + +jint JNICALL +RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, + jint methodCount) +{ + uintptr_t arguments[] = { reinterpret_cast(c), + reinterpret_cast(methods), + methodCount }; + + return run(t, registerNatives, arguments) ? 0 : -1; } jint JNICALL @@ -1943,24 +2180,49 @@ UnregisterNatives(Thread* t, jclass c) return 0; } +uint64_t +monitorOp(Thread* t, uintptr_t* arguments) +{ + void (*op)(Thread*, object) + = reinterpret_cast(arguments[0]); + + jobject o = reinterpret_cast(arguments[1]); + + op(t, *o); + + return 1; +} + +void +acquire0(Thread* t, object o) +{ + return acquire(t, o); +} + jint JNICALL MonitorEnter(Thread* t, jobject o) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(acquire0)), + reinterpret_cast(o) }; - acquire(t, *o); + return run(t, monitorOp, arguments) ? 0 : -1; +} - return 0; +void +release0(Thread* t, object o) +{ + return acquire(t, o); } jint JNICALL MonitorExit(Thread* t, jobject o) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] + = { reinterpret_cast(voidPointer(release0)), + reinterpret_cast(o) }; - release(t, *o); - - return 0; + return run(t, monitorOp, arguments) ? 0 : -1; } jint JNICALL @@ -2030,20 +2292,23 @@ boot(Thread* t) { enter(t, Thread::ActiveState); - if (t->exception == 0) { - setRoot(t, Machine::NullPointerException, makeThrowable - (t, Machine::NullPointerExceptionType)); - - if (t->exception == 0) { - setRoot(t, Machine::ArithmeticException, - makeThrowable(t, Machine::ArithmeticExceptionType)); + t->javaThread = t->m->classpath->makeThread(t, 0); - if (t->exception == 0) { - setRoot(t, Machine::ArrayIndexOutOfBoundsException, - makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType)); - } - } - } + setRoot(t, Machine::NullPointerException, makeThrowable + (t, Machine::NullPointerExceptionType)); + + setRoot(t, Machine::ArithmeticException, + makeThrowable(t, Machine::ArithmeticExceptionType)); + + setRoot(t, Machine::ArrayIndexOutOfBoundsException, + makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType)); + + setRoot(t, Machine::OutOfMemoryError, + makeThrowable(t, Machine::OutOfMemoryErrorType)); + + setRoot(t, Machine::FinalizerThread, t->m->classpath->makeThread(t, t)); + + threadDaemon(t, root(t, Machine::FinalizerThread)) = true; t->m->classpath->boot(t); diff --git a/src/machine.cpp b/src/machine.cpp index 1fade5edbe..6a93f39fb2 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -83,7 +83,7 @@ dispose(Thread* t, Thread* o, bool remove) expect(t, find(t->m->rootThread, o)); unsigned c = count(t->m->rootThread, o); - RUNTIME_ARRAY(Thread*, threads, c); + THREAD_RUNTIME_ARRAY(t, Thread*, threads, c); fill(t->m->rootThread, o, RUNTIME_ARRAY_BODY(threads)); #endif @@ -578,7 +578,14 @@ postCollect(Thread* t) } t->heapOffset = 0; - t->heapIndex = 0; + + if (t->m->heap->limitExceeded()) { + // if we're out of memory, pretend the thread-local heap is + // already full so we don't make things worse: + t->heapIndex = ThreadHeapSizeInWords; + } else { + t->heapIndex = 0; + } if (t->flags & Thread::UseBackupHeapFlag) { memset(t->backupHeap, 0, ThreadBackupHeapSizeInBytes); @@ -592,6 +599,17 @@ postCollect(Thread* t) } } +uint64_t +invoke(Thread* t, uintptr_t* arguments) +{ + object m = reinterpret_cast(arguments[0]); + object o = reinterpret_cast(arguments[1]); + + t->m->processor->invoke(t, m, o); + + return 1; +} + void finalizeObject(Thread* t, object o) { @@ -604,7 +622,11 @@ finalizeObject(Thread* t, object o) and vm::strcmp(reinterpret_cast("()V"), &byteArrayBody(t, methodSpec(t, m), 0)) == 0) { - t->m->processor->invoke(t, m, o); + uintptr_t arguments[] = { reinterpret_cast(m), + reinterpret_cast(o) }; + + run(t, invoke, arguments); + t->exception = 0; return; } @@ -613,21 +635,6 @@ finalizeObject(Thread* t, object o) abort(t); } -object -makeByteArray(Thread* t, const char* format, va_list a) -{ - const int Size = 256; - char buffer[Size]; - - int r = vm::vsnprintf(buffer, Size - 1, format, a); - expect(t, r >= 0 and r < Size - 1); - - object s = makeByteArray(t, strlen(buffer) + 1); - memcpy(&byteArrayBody(t, s, 0), buffer, byteArrayLength(t, s)); - - return s; -} - unsigned readByte(Stream& s, unsigned* value) { @@ -858,6 +865,9 @@ parsePool(Thread* t, Stream& s) if (count) { uint32_t* index = static_cast(t->m->heap->allocate(count * 4)); + THREAD_RESOURCE2(t, uint32_t*, index, unsigned, count, + t->m->heap->free(index, count * 4)); + for (unsigned i = 0; i < count; ++i) { index[i] = s.position(); @@ -889,6 +899,7 @@ parsePool(Thread* t, Stream& s) s.skip(8); ++ i; break; + case CONSTANT_Double: singletonSetBit(t, pool, count, i); singletonSetBit(t, pool, count, i + 1); @@ -911,8 +922,6 @@ parsePool(Thread* t, Stream& s) i += parsePoolEntry(t, s, index, pool, i); } - t->m->heap->free(index, count * 4); - s.setPosition(end); } @@ -960,7 +969,6 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, name); object interface = resolveClass(t, classLoader(t, class_), name); - if (UNLIKELY(t->exception)) return; PROTECT(t, interface); @@ -981,7 +989,6 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool) unsigned i = 0; for (HashMapIterator it(t, map); it.hasMore();) { object interface = tripleSecond(t, it.next()); - if (UNLIKELY(t->exception)) return; set(t, interfaceTable, ArrayBody + (i * BytesPerWord), interface); ++ i; @@ -1028,7 +1035,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) object addendum = 0; PROTECT(t, addendum); - RUNTIME_ARRAY(uint8_t, staticTypes, count); + THREAD_RUNTIME_ARRAY(t, uint8_t, staticTypes, count); for (unsigned i = 0; i < count; ++i) { unsigned flags = s.read2(); @@ -2046,6 +2053,7 @@ boot(Thread* t) setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0)); setRoot(t, Machine::StringMap, makeWeakHashMap(t, 0, 0)); + m->processor->boot(t, 0); { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1); @@ -2162,6 +2170,67 @@ class HeapClient: public Heap::Client { Machine* m; }; +void +doCollect(Thread* t, Heap::CollectionType type) +{ +#ifdef VM_STRESS + bool stress = (t->flags |= Thread::StressFlag); + if (not stress) atomicOr(&(t->flags), Thread::StressFlag); +#endif + + Machine* m = t->m; + + m->unsafe = true; + m->heap->collect(type, footprint(m->rootThread)); + m->unsafe = false; + + postCollect(m->rootThread); + + killZombies(t, m->rootThread); + + for (unsigned i = 0; i < m->heapPoolIndex; ++i) { + m->heap->free(m->heapPool[i], ThreadHeapSizeInBytes); + } + m->heapPoolIndex = 0; + + if (m->heap->limitExceeded()) { + // if we're out of memory, disallow further allocations of fixed + // objects: + m->fixedFootprint = FixedFootprintThresholdInBytes; + } else { + m->fixedFootprint = 0; + } + +#ifdef VM_STRESS + if (not stress) atomicAnd(&(t->flags), ~Thread::StressFlag); +#endif + + object f = t->m->finalizeQueue; + t->m->finalizeQueue = 0; + for (; f; f = finalizerNext(t, f)) { + void (*function)(Thread*, object); + memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); + if (function) { + function(t, finalizerTarget(t, f)); + } else { + setRoot(t, Machine::ObjectsToFinalize, makePair + (t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize))); + } + } + + if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) { + m->finalizeThread = m->processor->makeThread + (m, root(t, Machine::FinalizerThread), m->rootThread); + + addThread(t, m->finalizeThread); + + if (not startThread(t, m->finalizeThread)) { + removeThread(t, m->finalizeThread); + m->finalizeThread = 0; + } + } +} + } // namespace namespace vm { @@ -2663,7 +2732,9 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, > ThreadHeapSizeInWords) { t->heap = 0; - if (t->m->heapPoolIndex < ThreadHeapPoolSize) { + if ((not t->m->heap->limitExceeded()) + and t->m->heapPoolIndex < ThreadHeapPoolSize) + { t->heap = static_cast (t->m->heap->tryAllocate(ThreadHeapSizeInBytes)); @@ -2694,6 +2765,10 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, // vmPrintTrace(t); collect(t, Heap::MinorCollection); } + + if (t->m->heap->limitExceeded()) { + throw_(t, root(t, Machine::OutOfMemoryError)); + } } while (type == Machine::MovableAllocation and t->heapIndex + ceiling(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords); @@ -2759,12 +2834,51 @@ makeNewGeneral(Thread* t, object class_) return instance; } +void NO_RETURN +throw_(Thread* t, object e) +{ + assert(t, t->exception == 0); + + Thread::Checkpoint* checkpoint = t->checkpoint; + + expect(t, not checkpoint->noThrow); + + t->exception = e; + + while (t->resource != checkpoint->resource) { + Thread::Resource* r = t->resource; + t->resource = r->next; + r->release(); + } + + t->protector = checkpoint->protector; + + checkpoint->unwind(); + + abort(t); +} + +object +makeByteArray(Thread* t, const char* format, va_list a) +{ + const int Size = 256; + char buffer[Size]; + + int r = vm::vsnprintf(buffer, Size - 1, format, a); + expect(t, r >= 0 and r < Size - 1); + + object s = makeByteArray(t, strlen(buffer) + 1); + memcpy(&byteArrayBody(t, s, 0), buffer, byteArrayLength(t, s)); + + return s; +} + object makeByteArray(Thread* t, const char* format, ...) { va_list a; va_start(a, format); - object s = ::makeByteArray(t, format, a); + object s = makeByteArray(t, format, a); va_end(a); return s; @@ -2775,7 +2889,7 @@ makeString(Thread* t, const char* format, ...) { va_list a; va_start(a, format); - object s = ::makeByteArray(t, format, a); + object s = makeByteArray(t, format, a); va_end(a); return t->m->classpath->makeString(t, s, 0, byteArrayLength(t, s) - 1); @@ -2880,6 +2994,16 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length, } } +uint64_t +resolveBootstrap(Thread* t, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + + resolveSystemClass(t, root(t, Machine::BootLoader), name); + + return 1; +} + bool isAssignableFrom(Thread* t, object a, object b) { @@ -2890,8 +3014,9 @@ isAssignableFrom(Thread* t, object a, object b) if (classFlags(t, a) & ACC_INTERFACE) { if (classVmFlags(t, b) & BootstrapFlag) { - resolveSystemClass(t, root(t, Machine::BootLoader), className(t, b)); - if (UNLIKELY(t->exception)) { + uintptr_t arguments[] = { reinterpret_cast(className(t, b)) }; + + if (run(t, resolveBootstrap, arguments) == 0) { t->exception = 0; return false; } @@ -3084,7 +3209,6 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size) if (super) { object sc = resolveClass (t, loader, referenceName(t, singletonObject(t, pool, super - 1))); - if (UNLIKELY(t->exception)) return 0; set(t, class_, ClassSuper, sc); @@ -3094,16 +3218,12 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size) } parseInterfaceTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; parseFieldTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; parseMethodTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; parseAttributeTable(t, s, class_, pool); - if (UNLIKELY(t->exception)) return 0; object vtable = classVirtualTable(t, class_); unsigned vtableLength = (vtable ? arrayLength(t, vtable) : 0); @@ -3160,7 +3280,7 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_) if (byteArrayBody(t, spec, 0) == '[') { class_ = resolveArrayClass(t, loader, spec, throw_); } else { - RUNTIME_ARRAY(char, file, byteArrayLength(t, spec) + 6); + THREAD_RUNTIME_ARRAY(t, char, file, byteArrayLength(t, spec) + 6); memcpy(RUNTIME_ARRAY_BODY(file), &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1); @@ -3177,27 +3297,27 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_) fprintf(stderr, "parsing %s\n", &byteArrayBody(t, spec, 0)); } - // parse class file - class_ = parseClass(t, loader, region->start(), region->length()); - region->dispose(); + { THREAD_RESOURCE(t, System::Region*, region, region->dispose()); - if (LIKELY(t->exception == 0)) { - if (Verbose) { - fprintf(stderr, "done parsing %s: %p\n", - &byteArrayBody(t, spec, 0), - class_); - } + // parse class file + class_ = parseClass(t, loader, region->start(), region->length()); + } - object bootstrapClass = hashMapFind - (t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash, - byteArrayEqual); + if (Verbose) { + fprintf(stderr, "done parsing %s: %p\n", + &byteArrayBody(t, spec, 0), + class_); + } - if (bootstrapClass) { - PROTECT(t, bootstrapClass); - - updateBootstrapClass(t, bootstrapClass, class_); - class_ = bootstrapClass; - } + object bootstrapClass = hashMapFind + (t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash, + byteArrayEqual); + + if (bootstrapClass) { + PROTECT(t, bootstrapClass); + + updateBootstrapClass(t, bootstrapClass, class_); + class_ = bootstrapClass; } } } @@ -3206,10 +3326,9 @@ resolveSystemClass(Thread* t, object loader, object spec, bool throw_) PROTECT(t, class_); hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash); - } else if (throw_ and t->exception == 0) { - object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); - t->exception = makeThrowable - (t, Machine::ClassNotFoundExceptionType, message); + } else if (throw_) { + throwNew(t, Machine::ClassNotFoundExceptionType, "%s", + &byteArrayBody(t, spec, 0)); } } @@ -3265,28 +3384,24 @@ resolveClass(Thread* t, object loader, object spec, bool throw_) } } - if (LIKELY(t->exception == 0)) { - object method = findVirtualMethod - (t, root(t, Machine::LoadClassMethod), objectClass(t, loader)); + object method = findVirtualMethod + (t, root(t, Machine::LoadClassMethod), objectClass(t, loader)); - if (LIKELY(t->exception == 0)) { - PROTECT(t, method); + PROTECT(t, method); + + THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, spec)); + replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast + (&byteArrayBody(t, spec, 0))); - RUNTIME_ARRAY(char, s, byteArrayLength(t, spec)); - replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast - (&byteArrayBody(t, spec, 0))); + object specString = makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); - object specString = makeString(t, "%s", RUNTIME_ARRAY_BODY(s)); - - object jc = t->m->processor->invoke(t, method, loader, specString); - if (LIKELY(jc and t->exception == 0)) { - c = jclassVmClass(t, jc); - } - } + object jc = t->m->processor->invoke(t, method, loader, specString); + if (LIKELY(jc)) { + c = jclassVmClass(t, jc); } } - if (LIKELY(c and t->exception == 0)) { + if (LIKELY(c)) { PROTECT(t, c); ACQUIRE(t, t->m->classLock); @@ -3301,13 +3416,8 @@ resolveClass(Thread* t, object loader, object spec, bool throw_) return c; } else { - if (t->exception == 0) { - object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); - t->exception = makeThrowable - (t, Machine::ClassNotFoundExceptionType, message); - } - - return 0; + throwNew(t, Machine::ClassNotFoundExceptionType, "%s", + &byteArrayBody(t, spec, 0)); } } } @@ -3325,13 +3435,10 @@ resolveMethod(Thread* t, object class_, const char* methodName, object method = findMethodInClass(t, class_, name, spec); - if (t->exception == 0 and method == 0) { - object message = makeString - (t, "%s %s not found in %s", methodName, methodSpec, - &byteArrayBody(t, className(t, class_), 0)); - - t->exception = makeThrowable(t, Machine::NoSuchMethodErrorType, message); - return 0; + if (method == 0) { + throwNew(t, Machine::NoSuchMethodErrorType, "%s %s not found in %s", + methodName, methodSpec, &byteArrayBody + (t, className(t, class_), 0)); } else { return method; } @@ -3358,13 +3465,9 @@ resolveField(Thread* t, object class_, const char* fieldName, field = findFieldInClass(t, c, name, spec); } - if (t->exception == 0 and field == 0) { - object message = makeString - (t, "%s %s not found in %s", fieldName, fieldSpec, - &byteArrayBody(t, className(t, class_), 0)); - - t->exception = makeThrowable(t, Machine::NoSuchFieldErrorType, message); - return 0; + if (field == 0) { + throwNew(t, Machine::NoSuchFieldErrorType, "%s %s not found in %s", + fieldName, fieldSpec, &byteArrayBody(t, className(t, class_), 0)); } else { return field; } @@ -3413,11 +3516,8 @@ preInitClass(Thread* t, object c) t->m->classLock->wait(t->systemThread, 0); } } else if (classVmFlags(t, c) & InitErrorFlag) { - object message = makeString - (t, "%s", &byteArrayBody(t, className(t, c), 0)); - - t->exception = makeThrowable - (t, Machine::NoClassDefFoundErrorType, message); + throwNew(t, Machine::NoClassDefFoundErrorType, "%s", + &byteArrayBody(t, className(t, c), 0)); } else { classVmFlags(t, c) |= InitFlag; return true; @@ -3434,13 +3534,13 @@ postInitClass(Thread* t, object c) ACQUIRE(t, t->m->classLock); if (t->exception) { - object exception = t->exception; - t->exception = 0; - t->exception = makeThrowable - (t, Machine::ExceptionInInitializerErrorType, 0, 0, exception); - classVmFlags(t, c) |= NeedInitFlag | InitErrorFlag; classVmFlags(t, c) &= ~InitFlag; + + object exception = t->exception; + t->exception = 0; + + throwNew(t, Machine::ExceptionInInitializerErrorType, 0, 0, exception); } else { classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag); } @@ -3453,11 +3553,11 @@ initClass(Thread* t, object c) PROTECT(t, c); if (preInitClass(t, c)) { + OBJECT_RESOURCE(t, c, postInitClass(t, c)); + Thread::ClassInitStack stack(t, c); t->m->processor->invoke(t, classInitializer(t, c), 0); - - postInitClass(t, c); } } @@ -3496,7 +3596,6 @@ resolveObjectArrayClass(Thread* t, object loader, object elementClass) } object arrayClass = resolveClass(t, loader, spec); - if (UNLIKELY(t->exception)) return 0; set(t, getClassRuntimeData(t, elementClass), ClassRuntimeDataArrayClass, arrayClass); @@ -3509,7 +3608,6 @@ makeObjectArray(Thread* t, object elementClass, unsigned count) { object arrayClass = resolveObjectArrayClass (t, classLoader(t, elementClass), elementClass); - if (UNLIKELY(t->exception)) return 0; PROTECT(t, arrayClass); @@ -3692,57 +3790,16 @@ collect(Thread* t, Heap::CollectionType type) { ENTER(t, Thread::ExclusiveState); -#ifdef VM_STRESS - bool stress = (t->flags |= Thread::StressFlag); - if (not stress) atomicOr(&(t->flags), Thread::StressFlag); -#endif - - Machine* m = t->m; - - m->unsafe = true; - m->heap->collect(type, footprint(m->rootThread)); - m->unsafe = false; - - postCollect(m->rootThread); - - killZombies(t, m->rootThread); - - for (unsigned i = 0; i < m->heapPoolIndex; ++i) { - m->heap->free(m->heapPool[i], ThreadHeapSizeInBytes); - } - m->heapPoolIndex = 0; - - m->fixedFootprint = 0; - -#ifdef VM_STRESS - if (not stress) atomicAnd(&(t->flags), ~Thread::StressFlag); -#endif - - object f = t->m->finalizeQueue; - t->m->finalizeQueue = 0; - for (; f; f = finalizerNext(t, f)) { - void (*function)(Thread*, object); - memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); - if (function) { - function(t, finalizerTarget(t, f)); - } else { - setRoot(t, Machine::ObjectsToFinalize, makePair - (t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize))); - } + if (t->m->heap->limitExceeded()) { + type = Heap::MajorCollection; } - if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) { - object javaThread = t->m->classpath->makeThread(t, m->rootThread); - threadDaemon(t, javaThread) = true; + doCollect(t, type); - m->finalizeThread = m->processor->makeThread(m, javaThread, m->rootThread); - - addThread(t, m->finalizeThread); - - if (not startThread(t, m->finalizeThread)) { - removeThread(t, m->finalizeThread); - m->finalizeThread = 0; - } + if (t->m->heap->limitExceeded()) { + // try once more, giving the heap a chance to squeeze everything + // into the smallest possible space: + doCollect(t, Heap::MajorCollection); } } @@ -3762,7 +3819,7 @@ walk(Thread* t, Heap::Walker* w, object o, unsigned start) = (arrayElementSize ? cast(o, fixedSize - BytesPerWord) : 0); - RUNTIME_ARRAY(uint32_t, mask, intArrayLength(t, objectMask)); + THREAD_RUNTIME_ARRAY(t, uint32_t, mask, intArrayLength(t, objectMask)); memcpy(RUNTIME_ARRAY_BODY(mask), &intArrayBody(t, objectMask, 0), intArrayLength(t, objectMask) * 4); @@ -3836,7 +3893,7 @@ printTrace(Thread* t, object exception) if (throwableMessage(t, e)) { object m = throwableMessage(t, e); - RUNTIME_ARRAY(char, message, stringLength(t, m) + 1); + THREAD_RUNTIME_ARRAY(t, char, message, stringLength(t, m) + 1); stringChars(t, m, RUNTIME_ARRAY_BODY(message)); fprintf(stderr, ": %s\n", RUNTIME_ARRAY_BODY(message)); } else { diff --git a/src/machine.h b/src/machine.h index 789d3214ef..187dc46e21 100644 --- a/src/machine.h +++ b/src/machine.h @@ -37,6 +37,56 @@ #define ENTER(t, state) StateResource MAKE_NAME(stateResource_) (t, state) +#define THREAD_RESOURCE0(t, releaseBody) \ + class MAKE_NAME(Resource_): public Thread::Resource { \ + public: \ + MAKE_NAME(Resource_)(Thread* t): Resource(t) { } \ + ~MAKE_NAME(Resource_)() { releaseBody; } \ + virtual void release() \ + { this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); } \ + } MAKE_NAME(resource_)(t); + +#define OBJECT_RESOURCE(t, name, releaseBody) \ + class MAKE_NAME(Resource_): public Thread::Resource { \ + public: \ + MAKE_NAME(Resource_)(Thread* t, object name): \ + Resource(t), name(name), protector(t, &(this->name)) { } \ + ~MAKE_NAME(Resource_)() { releaseBody; } \ + virtual void release() \ + { this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); } \ + \ + private: \ + object name; \ + Thread::SingleProtector protector; \ + } MAKE_NAME(resource_)(t, name); + +#define THREAD_RESOURCE(t, type, name, releaseBody) \ + class MAKE_NAME(Resource_): public Thread::Resource { \ + public: \ + MAKE_NAME(Resource_)(Thread* t, type name): \ + Resource(t), name(name) { } \ + ~MAKE_NAME(Resource_)() { releaseBody; } \ + virtual void release() \ + { this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); } \ + \ + private: \ + type name; \ + } MAKE_NAME(resource_)(t, name); + +#define THREAD_RESOURCE2(t, type1, name1, type2, name2, releaseBody) \ + class MAKE_NAME(Resource_): public Thread::Resource { \ + public: \ + MAKE_NAME(Resource_)(Thread* t, type1 name1, type2 name2): \ + Resource(t), name1(name1), name2(name2) { } \ + ~MAKE_NAME(Resource_)() { releaseBody; } \ + virtual void release() \ + { this->MAKE_NAME(Resource_)::~MAKE_NAME(Resource_)(); } \ + \ + private: \ + type1 name1; \ + type2 name2; \ + } MAKE_NAME(resource_)(t, name1, name2); + namespace vm { const bool Verbose = false; @@ -1201,10 +1251,12 @@ class Machine { MethodRuntimeDataTable, JNIMethodTable, ShutdownHooks, + FinalizerThread, ObjectsToFinalize, NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException, + OutOfMemoryError, VirtualFileFinders, VirtualFiles }; @@ -1280,15 +1332,23 @@ inline void stress(Thread* t); #endif // not VM_STRESS -void -runJavaThread(Thread* t); +uint64_t +runThread(Thread*, uintptr_t*); -void -runFinalizeThread(Thread* t); +uint64_t +run(Thread* t, uint64_t (*function)(Thread*, uintptr_t*), + uintptr_t* arguments); void checkDaemon(Thread* t); +extern "C" uint64_t +vmRun(uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments, + void* checkpoint); + +extern "C" void +vmRun_returnAddress(); + class Thread { public: enum State { @@ -1336,9 +1396,26 @@ class Thread { object* p; }; - class ClassInitStack { + class Resource { + public: + Resource(Thread* t): t(t), next(t->resource) { + t->resource = this; + } + + ~Resource() { + t->resource = next; + } + + virtual void release() = 0; + + Thread* t; + Resource* next; + }; + + class ClassInitStack: public Resource { public: ClassInitStack(Thread* t, object class_): + Resource(t), next(t->classInitStack), class_(class_), protector(t, &(this->class_)) @@ -1347,7 +1424,11 @@ class Thread { } ~ClassInitStack() { - protector.t->classInitStack = next; + t->classInitStack = next; + } + + virtual void release() { + this->ClassInitStack::~ClassInitStack(); } ClassInitStack* next; @@ -1355,6 +1436,50 @@ class Thread { SingleProtector protector; }; + class Checkpoint { + public: + Checkpoint(Thread* t): + t(t), + next(t->checkpoint), + resource(t->resource), + protector(t->protector), + noThrow(false) + { + t->checkpoint = this; + } + + ~Checkpoint() { + t->checkpoint = next; + } + + virtual void NO_RETURN unwind() = 0; + + Thread* t; + Checkpoint* next; + Resource* resource; + Protector* protector; + bool noThrow; + }; + + class RunCheckpoint: public Checkpoint { + public: + RunCheckpoint(Thread* t): + Checkpoint(t), + stack(0), + base(0) + { } + + virtual void unwind() { + void* stack = this->stack; + this->stack = 0; + expect(t->m->system, stack); + vmJump(voidPointer(vmRun_returnAddress), base, stack, t, 0, 0); + } + + void* stack; + void* base; + }; + class Runnable: public System::Runnable { public: Runnable(Thread* t): t(t) { } @@ -1366,18 +1491,10 @@ class Thread { virtual void run() { enterActiveState(t); - t->m->localThread->set(t); + vm::run(t, runThread, 0); - checkDaemon(t); - - if (t == t->m->finalizeThread) { - runFinalizeThread(t); - } else if (t->javaThread) { - runJavaThread(t); - - if (t->exception) { - printTrace(t, t->exception); - } + if (t->exception) { + printTrace(t, t->exception); } t->exit(); @@ -1416,6 +1533,8 @@ class Thread { unsigned heapOffset; Protector* protector; ClassInitStack* classInitStack; + Resource* resource; + Checkpoint* checkpoint; Runnable runnable; uintptr_t* defaultHeap; uintptr_t* heap; @@ -1448,6 +1567,38 @@ class Classpath { dispose() = 0; }; +#ifdef _MSC_VER + +template +class RuntimeArray: public Thread::Resource { + public: + RuntimeArray(Thread* t, unsigned size): + Resource(t), + body(static_cast(t->m->heap->allocate(size * sizeof(T)))), + size(size) + { } + + ~RuntimeArray() { + t->m->heap->free(body, size * sizeof(T)); + } + + virtual void release() { + RuntimeArray::~RuntimeArray(); + } + + T* body; + unsigned size; +}; + +# define THREAD_RUNTIME_ARRAY(thread, type, name, size) \ + RuntimeArray name(thread, size); + +#else // not _MSC_VER + +# define THREAD_RUNTIME_ARRAY(thread, type, name, size) type name[size]; + +#endif // not _MSC_VER + Classpath* makeClasspath(System* system, Allocator* allocator, const char* javaHome, const char* embedPrefix); @@ -1469,16 +1620,21 @@ enterActiveState(Thread* t) enter(t, Thread::ActiveState); } -class StateResource { +class StateResource: public Thread::Resource { public: - StateResource(Thread* t, Thread::State state): t(t), oldState(t->state) { + StateResource(Thread* t, Thread::State state): + Resource(t), oldState(t->state) + { enter(t, state); } ~StateResource() { enter(t, oldState); } + virtual void release() { + this->StateResource::~StateResource(); + } + private: - Thread* t; Thread::State oldState; }; @@ -1553,33 +1709,43 @@ release(Thread* t, System::Monitor* m) m->release(t->systemThread); } -class MonitorResource { +class MonitorResource: public Thread::Resource { public: - MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { + MonitorResource(Thread* t, System::Monitor* m): + Resource(t), m(m) + { acquire(t, m); } ~MonitorResource() { - release(t, m); + vm::release(t, m); + } + + virtual void release() { + this->MonitorResource::~MonitorResource(); } private: - Thread* t; System::Monitor* m; }; -class RawMonitorResource { +class RawMonitorResource: public Thread::Resource { public: - RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) { + RawMonitorResource(Thread* t, System::Monitor* m): + Resource(t), m(m) + { m->acquire(t->systemThread); } ~RawMonitorResource() { - release(t, m); + vm::release(t, m); + } + + virtual void release() { + this->RawMonitorResource::~RawMonitorResource(); } private: - Thread* t; System::Monitor* m; }; @@ -1622,8 +1788,12 @@ class FixedAllocator: public Allocator { return p; } - virtual void free(const void*, unsigned) { - abort(s); + virtual void free(const void* p, unsigned size) { + if (p >= base and static_cast(p) + size == base + offset) { + offset -= size; + } else { + abort(s); + } } System* s; @@ -1667,7 +1837,6 @@ allocateSmall(Thread* t, unsigned sizeInBytes) object o = reinterpret_cast(t->heap + t->heapIndex); t->heapIndex += ceiling(sizeInBytes, BytesPerWord); - cast(o, 0) = 0; return o; } @@ -1745,12 +1914,39 @@ instanceOf(Thread* t, object class_, object o); #include "type-declarations.cpp" +inline uint64_t +run(Thread* t, uint64_t (*function)(Thread*, uintptr_t*), uintptr_t* arguments) +{ + ENTER(t, Thread::ActiveState); + Thread::RunCheckpoint checkpoint(t); + return vmRun(function, arguments, &checkpoint); +} + inline void runJavaThread(Thread* t) { t->m->classpath->runThread(t); } +void +runFinalizeThread(Thread* t); + +inline uint64_t +runThread(Thread* t, uintptr_t*) +{ + t->m->localThread->set(t); + + checkDaemon(t); + + if (t == t->m->finalizeThread) { + runFinalizeThread(t); + } else if (t->javaThread) { + runJavaThread(t); + } + + return 1; +} + inline bool startThread(Thread* t, Thread* p) { @@ -1820,17 +2016,12 @@ checkDaemon(Thread* t) } } -inline Thread* -attachThread(Machine* m, bool daemon) +inline uint64_t +initAttachedThread(Thread* t, uintptr_t* arguments) { - Thread* t = m->processor->makeThread(m, 0, m->rootThread); - m->system->attach(&(t->runnable)); + bool daemon = arguments[0]; - addThread(t, t); - - enter(t, Thread::ActiveState); - - t->javaThread = m->classpath->makeThread(t, m->rootThread); + t->javaThread = t->m->classpath->makeThread(t, t->m->rootThread); threadPeer(t, t->javaThread) = reinterpret_cast(t); @@ -1840,11 +2031,30 @@ attachThread(Machine* m, bool daemon) registerDaemon(t); } - enter(t, Thread::IdleState); + t->m->localThread->set(t); - m->localThread->set(t); + return 1; +} - return t; +inline Thread* +attachThread(Machine* m, bool daemon) +{ + Thread* t = m->processor->makeThread(m, 0, m->rootThread); + m->system->attach(&(t->runnable)); + + addThread(t, t); + + uintptr_t arguments[] = { daemon }; + + enter(t, Thread::ActiveState); + + if (run(t, initAttachedThread, arguments)) { + enter(t, Thread::IdleState); + return t; + } else { + t->exit(); + return 0; + } } inline object& @@ -1939,6 +2149,9 @@ make(Thread* t, object class_) } } +object +makeByteArray(Thread* t, const char* format, va_list a); + object makeByteArray(Thread* t, const char* format, ...); @@ -2248,12 +2461,8 @@ inline object resolveMethod(Thread* t, object loader, const char* className, const char* methodName, const char* methodSpec) { - object class_ = resolveClass(t, loader, className); - if (LIKELY(t->exception == 0)) { - return resolveMethod(t, class_, methodName, methodSpec); - } else { - return 0; - } + return resolveMethod + (t, resolveClass(t, loader, className), methodName, methodSpec); } object @@ -2264,12 +2473,8 @@ inline object resolveField(Thread* t, object loader, const char* className, const char* fieldName, const char* fieldSpec) { - object class_ = resolveClass(t, loader, className); - if (LIKELY(t->exception == 0)) { - return resolveField(t, class_, fieldName, fieldSpec); - } else { - return 0; - } + return resolveField + (t, resolveClass(t, loader, className), fieldName, fieldSpec); } bool @@ -2347,6 +2552,48 @@ makeThrowable return result; } +inline object +makeThrowable(Thread* t, Machine::Type type, const char* format, va_list a) +{ + object s = makeByteArray(t, format, a); + + object message = t->m->classpath->makeString + (t, s, 0, byteArrayLength(t, s) - 1); + + return makeThrowable(t, type, message); +} + +inline object +makeThrowable(Thread* t, Machine::Type type, const char* format, ...) +{ + va_list a; + va_start(a, format); + object r = makeThrowable(t, type, format, a); + va_end(a); + + return r; +} + +void NO_RETURN +throw_(Thread* t, object e); + +inline void NO_RETURN +throwNew(Thread* t, Machine::Type type) +{ + throw_(t, makeThrowable(t, type)); +} + +inline void NO_RETURN +throwNew(Thread* t, Machine::Type type, const char* format, ...) +{ + va_list a; + va_start(a, format); + object r = makeThrowable(t, type, format, a); + va_end(a); + + throw_(t, r); +} + object findInHierarchyOrNull(Thread* t, object class_, object name, object spec, object (*find)(Thread*, object, object, object)); @@ -2359,12 +2606,10 @@ findInHierarchy(Thread* t, object class_, object name, object spec, object o = findInHierarchyOrNull(t, class_, name, spec, find); if (o == 0) { - object message = makeString - (t, "%s %s not found in %s", - &byteArrayBody(t, name, 0), - &byteArrayBody(t, spec, 0), - &byteArrayBody(t, className(t, class_), 0)); - t->exception = makeThrowable(t, errorType, message); + throwNew(t, errorType, "%s %s not found in %s", + &byteArrayBody(t, name, 0), + &byteArrayBody(t, spec, 0), + &byteArrayBody(t, className(t, class_), 0)); } return o; @@ -2390,8 +2635,7 @@ findMethodOrNull(Thread* t, object class_, const char* name, const char* spec) inline object findVirtualMethod(Thread* t, object method, object class_) { - return arrayBody(t, classVirtualTable(t, class_), - methodOffset(t, method)); + return arrayBody(t, classVirtualTable(t, class_), methodOffset(t, method)); } inline object @@ -2403,8 +2647,8 @@ findInterfaceMethod(Thread* t, object method, object class_) object itable = classInterfaceTable(t, class_); for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { if (arrayBody(t, itable, i) == interface) { - return arrayBody(t, arrayBody(t, itable, i + 1), - methodOffset(t, method)); + return arrayBody + (t, arrayBody(t, itable, i + 1), methodOffset(t, method)); } } abort(t); @@ -2849,10 +3093,10 @@ wait(Thread* t, object o, int64_t milliseconds) bool interrupted = monitorWait(t, m, milliseconds); if (interrupted) { - t->exception = makeThrowable(t, Machine::InterruptedExceptionType); + throwNew(t, Machine::InterruptedExceptionType); } } else { - t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); + throwNew(t, Machine::IllegalMonitorStateExceptionType); } if (DebugMonitors) { @@ -2881,7 +3125,7 @@ notify(Thread* t, object o) if (m and monitorOwner(t, m) == t) { monitorNotify(t, m); } else { - t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); + throwNew(t, Machine::IllegalMonitorStateExceptionType); } } @@ -2898,7 +3142,7 @@ notifyAll(Thread* t, object o) if (m and monitorOwner(t, m) == t) { monitorNotifyAll(t, m); } else { - t->exception = makeThrowable(t, Machine::IllegalMonitorStateExceptionType); + throwNew(t, Machine::IllegalMonitorStateExceptionType); } } @@ -3057,7 +3301,6 @@ resolveClassInObject(Thread* t, object loader, object container, PROTECT(t, container); o = resolveClass(t, loader, o); - if (UNLIKELY(t->exception)) return 0; set(t, container, classOffset, o); } @@ -3072,7 +3315,6 @@ resolveClassInPool(Thread* t, object loader, object method, unsigned index) PROTECT(t, method); o = resolveClass(t, loader, referenceName(t, o)); - if (UNLIKELY(t->exception)) return 0; set(t, codePool(t, methodCode(t, method)), SingletonBody + (index * BytesPerWord), o); @@ -3101,12 +3343,10 @@ resolve(Thread* t, object loader, object method, unsigned index, PROTECT(t, reference); object class_ = resolveClassInObject(t, loader, o, ReferenceClass); - if (UNLIKELY(t->exception)) return 0; o = findInHierarchy (t, class_, referenceName(t, reference), referenceSpec(t, reference), find, errorType); - if (UNLIKELY(t->exception)) return 0; set(t, codePool(t, methodCode(t, method)), SingletonBody + (index * BytesPerWord), o); @@ -3236,9 +3476,7 @@ primitiveClass(Thread* t, char name) case 'S': return type(t, Machine::JshortType); case 'V': return type(t, Machine::JvoidType); case 'Z': return type(t, Machine::JbooleanType); - default: - t->exception = makeThrowable(t, Machine::IllegalArgumentExceptionType); - return 0; + default: throwNew(t, Machine::IllegalArgumentExceptionType); } } diff --git a/src/process.cpp b/src/process.cpp index 00edbe66b7..b364598eb5 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -153,13 +153,13 @@ resolveNativeMethod(Thread* t, object method, const char* prefix, { unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false); // extra 6 is for code below: - RUNTIME_ARRAY(char, undecorated, undecoratedSize + 1 + 6); + THREAD_RUNTIME_ARRAY(t, char, undecorated, undecoratedSize + 1 + 6); makeJNIName(t, prefix, prefixLength, RUNTIME_ARRAY_BODY(undecorated) + 1, method, false); unsigned decoratedSize = prefixLength + jniNameLength(t, method, true); // extra 6 is for code below: - RUNTIME_ARRAY(char, decorated, decoratedSize + 1 + 6); + THREAD_RUNTIME_ARRAY(t, char, decorated, decoratedSize + 1 + 6); makeJNIName(t, prefix, prefixLength, RUNTIME_ARRAY_BODY(decorated) + 1, method, true); @@ -232,20 +232,13 @@ resolveNative(Thread* t, object method) initClass(t, methodClass(t, method)); - if (LIKELY(t->exception == 0) - and methodRuntimeDataNative(t, getMethodRuntimeData(t, method)) == 0) - { + if (methodRuntimeDataNative(t, getMethodRuntimeData(t, method)) == 0) { object native = resolveNativeMethod(t, method); if (UNLIKELY(native == 0)) { - object message = makeString - (t, "%s.%s%s", - &byteArrayBody(t, className(t, methodClass(t, method)), 0), - &byteArrayBody(t, methodName(t, method), 0), - &byteArrayBody(t, methodSpec(t, method), 0)); - - t->exception = makeThrowable - (t, Machine::UnsatisfiedLinkErrorType, message); - return; + throwNew(t, Machine::UnsatisfiedLinkErrorType, "%s.%s%s", + &byteArrayBody(t, className(t, methodClass(t, method)), 0), + &byteArrayBody(t, methodName(t, method), 0), + &byteArrayBody(t, methodSpec(t, method), 0)); } PROTECT(t, native); diff --git a/src/x86.S b/src/x86.S index 552e093bdc..c7c6e5c504 100644 --- a/src/x86.S +++ b/src/x86.S @@ -23,6 +23,10 @@ #ifdef __x86_64__ +#define CHECKPOINT_THREAD 8 +#define CHECKPOINT_STACK 48 +#define CHECKPOINT_BASE 56 + #ifdef __MINGW32__ .globl GLOBAL(detectFeature) GLOBAL(detectFeature): @@ -173,6 +177,48 @@ GLOBAL(vmJump): movq %r8,%rsp movq %r9,%rbx jmp *%rcx + +#define VMRUN_FRAME_SIZE 80 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // %rcx: function + // %rdx: arguments + // %r8 : checkpoint + pushq %rbp + movq %rsp,%rbp + subq $VMRUN_FRAME_SIZE,%rsp + + movq %rbx,16(%rsp) + movq %r12,24(%rsp) + movq %r13,32(%rsp) + movq %r14,40(%rsp) + movq %r15,48(%rsp) + movq %rsi,56(%rsp) + movq %rdi,64(%rsp) + + movq %rsp,CHECKPOINT_STACK(%rcx) + movq %rbp,CHECKPOINT_BASE(%rcx) + + movq %rcx,%r11 + movq CHECKPOINT_THREAD(%rdx),%rcx + + call *%r11 + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movq 16(%rsp),%rbx + movq 24(%rsp),%r12 + movq 32(%rsp),%r13 + movq 40(%rsp),%r14 + movq 48(%rsp),%r15 + movq 56(%rsp),%rsi + movq 64(%rsp),%rdi + + addq $VMRUN_FRAME_SIZE,%rsp + popq %rbp + ret #else // not __MINGW32__ .globl GLOBAL(detectFeature) @@ -314,10 +360,52 @@ GLOBAL(vmJump): movq %r9,%rdx jmp *%rdi +#define VMRUN_FRAME_SIZE 64 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // %rdi: function + // %rsi: arguments + // %rdx: checkpoint + pushq %rbp + movq %rsp,%rbp + subq $VMRUN_FRAME_SIZE,%rsp + + movq %rbx,16(%rsp) + movq %r12,24(%rsp) + movq %r13,32(%rsp) + movq %r14,40(%rsp) + movq %r15,48(%rsp) + + movq %rsp,CHECKPOINT_STACK(%rdx) + movq %rbp,CHECKPOINT_BASE(%rdx) + + movq %rdi,%r11 + movq CHECKPOINT_THREAD(%rdx),%rdi + + call *%r11 + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movq 16(%rsp),%rbx + movq 24(%rsp),%r12 + movq 32(%rsp),%r13 + movq 40(%rsp),%r14 + movq 48(%rsp),%r15 + + addq $VMRUN_FRAME_SIZE,%rsp + popq %rbp + ret + #endif // not __MINGW32__ #elif defined __i386__ +#define CHECKPOINT_THREAD 4 +#define CHECKPOINT_STACK 24 +#define CHECKPOINT_BASE 28 + .globl GLOBAL(detectFeature) GLOBAL(detectFeature): pushl %ebp @@ -432,4 +520,42 @@ GLOBAL(vmJump): movl 12(%esp),%esp jmp *%esi -#endif //def __x86_64__ +#define VMRUN_FRAME_SIZE 32 + +.globl GLOBAL(vmRun) +GLOBAL(vmRun): + // 8(%ebp): function + // 12(%ebp): arguments + // 16(%ebp): checkpoint + pushl %ebp + movl %esp,%ebp + subl $VMRUN_FRAME_SIZE,%esp + + movl %ebx,8(%esp) + movl %esi,12(%esp) + movl %edi,16(%esp) + + movl 12(%ebp),%eax + movl %eax,4(%esp) + + movl 16(%ebp),%ecx + movl CHECKPOINT_THREAD(%ecx),%eax + movl %eax,0(%esp) + + movl %esp,CHECKPOINT_STACK(%ecx) + movl %ebp,CHECKPOINT_BASE(%ecx) + + call *8(%ebp) + +.globl GLOBAL(vmRun_returnAddress) +GLOBAL(vmRun_returnAddress): + + movl 8(%esp),%ebx + movl 12(%esp),%esi + movl 16(%esp),%edi + + addl $VMRUN_FRAME_SIZE,%esp + popl %ebp + ret + +#endif // __i386__ diff --git a/test/OutOfMemory.java b/test/OutOfMemory.java new file mode 100644 index 0000000000..fbcb614fdf --- /dev/null +++ b/test/OutOfMemory.java @@ -0,0 +1,62 @@ +public class OutOfMemory { + // assume a 128MB heap size: + private static final int Padding = 120 * 1024 * 1024; + + private static class Node { + Object value; + Node next; + } + + private static void bigObjects() { + Object[] root = null; + while (true) { + Object[] x = new Object[1024 * 1024]; + x[0] = root; + root = x; + } + } + + private static void littleObjects() { + byte[] padding = new byte[Padding]; + Node root = null; + while (true) { + Node x = new Node(); + x.next = root; + root = x; + } + } + + private static void bigAndLittleObjects() { + byte[] padding = new byte[Padding]; + Node root = null; + while (true) { + Node x = new Node(); + x.value = new Object[1024 * 1024]; + x.next = root; + root = x; + } + } + + public static void main(String[] args) { + try { + bigObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + try { + littleObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + + try { + bigAndLittleObjects(); + throw new RuntimeException(); + } catch (OutOfMemoryError e) { + e.printStackTrace(); + } + } +}