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(); + } + } +}