diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index f312690606..c73c00931d 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -104,14 +104,15 @@ public class Classes { byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); return Enum.valueOf - (getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)), + (SystemClassLoader.getClass + (loadVMClass(loader, typeName, 1, typeName.length - 3)), new String(name, 0, name.length - 1, false)); } case 'c':{ byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); - return getClass(loadVMClass(loader, name, 1, name.length - 3)); + return SystemClassLoader.getClass(loadVMClass(loader, name, 1, name.length - 3)); } case '@': @@ -136,7 +137,7 @@ public class Classes { { byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1); Object[] annotation = new Object[(read2(in) + 1) * 2]; - annotation[1] = getClass + annotation[1] = SystemClassLoader.getClass (loadVMClass(loader, typeName, 1, typeName.length - 3)); for (int i = 2; i < annotation.length; i += 2) { diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index d93be28114..3054afe15a 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -14,7 +14,7 @@ import java.net.URL; import java.net.MalformedURLException; public class SystemClassLoader extends ClassLoader { - private static native VMClass findVMClass(String name) + private native VMClass findVMClass(String name) throws ClassNotFoundException; protected Class findClass(String name) throws ClassNotFoundException { @@ -23,14 +23,14 @@ public class SystemClassLoader extends ClassLoader { public static native Class getClass(VMClass vmClass); - private static native VMClass findLoadedVMClass(String name); + private native VMClass findLoadedVMClass(String name); protected Class reallyFindLoadedClass(String name){ VMClass c = findLoadedVMClass(name); return c == null ? null : getClass(c); } - private static native boolean resourceExists(String name); + private native boolean resourceExists(String name); protected URL findResource(String name) { if (resourceExists(name)) { diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 6d234f3765..65021739fb 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -14,6 +14,7 @@ import avian.VMClass; import avian.ClassAddendum; import avian.AnnotationInvocationHandler; import avian.SystemClassLoader; +import avian.Classes; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -69,23 +70,23 @@ public final class Class public static String getName(VMClass c) { if (c.name == null) { if ((c.vmFlags & PrimitiveFlag) != 0) { - if (c == SystemClassLoader.primitiveClass('V')) { + if (c == Classes.primitiveClass('V')) { c.name = "void\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('Z')) { + } else if (c == Classes.primitiveClass('Z')) { c.name = "boolean\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('B')) { + } else if (c == Classes.primitiveClass('B')) { c.name = "byte\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('C')) { + } else if (c == Classes.primitiveClass('C')) { c.name = "char\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('S')) { + } else if (c == Classes.primitiveClass('S')) { c.name = "short\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('I')) { + } else if (c == Classes.primitiveClass('I')) { c.name = "int\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('F')) { + } else if (c == Classes.primitiveClass('F')) { c.name = "float\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('J')) { + } else if (c == Classes.primitiveClass('J')) { c.name = "long\0".getBytes(); - } else if (c == SystemClassLoader.primitiveClass('D')) { + } else if (c == Classes.primitiveClass('D')) { c.name = "double\0".getBytes(); } else { throw new AssertionError(); @@ -150,9 +151,9 @@ public final class Class loader = Class.class.vmClass.loader; } Class c = loader.loadClass(name); - SystemClassLoader.link(c.vmClass, loader); + Classes.link(c.vmClass, loader); if (initialize) { - SystemClassLoader.initialize(c.vmClass); + Classes.initialize(c.vmClass); } return c; } @@ -170,7 +171,7 @@ public final class Class } else { if (name.length() == 1) { return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass(name.charAt(0))); + (Classes.primitiveClass(name.charAt(0))); } else { throw new ClassNotFoundException(name); } @@ -184,29 +185,21 @@ public final class Class if (isArray()) { String n = getName(); if ("[Z".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('Z')); + return SystemClassLoader.getClass(Classes.primitiveClass('Z')); } else if ("[B".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('B')); + return SystemClassLoader.getClass(Classes.primitiveClass('B')); } else if ("[S".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('S')); + return SystemClassLoader.getClass(Classes.primitiveClass('S')); } else if ("[C".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('C')); + return SystemClassLoader.getClass(Classes.primitiveClass('C')); } else if ("[I".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('I')); + return SystemClassLoader.getClass(Classes.primitiveClass('I')); } else if ("[F".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('F')); + return SystemClassLoader.getClass(Classes.primitiveClass('F')); } else if ("[J".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('J')); + return SystemClassLoader.getClass(Classes.primitiveClass('J')); } else if ("[D".equals(n)) { - return SystemClassLoader.getClass - (SystemClassLoader.primitiveClass('D')); + return SystemClassLoader.getClass(Classes.primitiveClass('D')); } if (vmClass.staticTable == null) throw new AssertionError(); @@ -217,12 +210,12 @@ public final class Class } public boolean isAssignableFrom(Class c) { - return SystemClassLoader.isAssignableFrom(vmClass, c.vmClass); + return Classes.isAssignableFrom(vmClass, c.vmClass); } private static Field findField(VMClass vmClass, String name) { if (vmClass.fieldTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); for (int i = 0; i < vmClass.fieldTable.length; ++i) { if (Field.getName(vmClass.fieldTable[i]).equals(name)) { @@ -269,7 +262,7 @@ public final class Class Class[] parameterTypes) { if (vmClass.methodTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); if (parameterTypes == null) { parameterTypes = new Class[0]; @@ -365,7 +358,7 @@ public final class Class public Constructor[] getDeclaredConstructors() { Constructor[] array = new Constructor[countConstructors(false)]; if (vmClass.methodTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int index = 0; for (int i = 0; i < vmClass.methodTable.length; ++i) { @@ -381,7 +374,7 @@ public final class Class public Constructor[] getConstructors() { Constructor[] array = new Constructor[countConstructors(true)]; if (vmClass.methodTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int index = 0; for (int i = 0; i < vmClass.methodTable.length; ++i) { @@ -423,7 +416,7 @@ public final class Class public Field[] getFields() { Field[] array = new Field[countPublicFields()]; if (vmClass.fieldTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int ai = 0; for (int i = 0; i < vmClass.fieldTable.length; ++i) { @@ -454,7 +447,7 @@ public final class Class public Method[] getDeclaredMethods() { Method[] array = new Method[countMethods(false)]; if (vmClass.methodTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int ai = 0; for (int i = 0; i < vmClass.methodTable.length; ++i) { @@ -470,7 +463,7 @@ public final class Class public Method[] getMethods() { Method[] array = new Method[countMethods(true)]; if (vmClass.methodTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int index = 0; for (int i = 0; i < vmClass.methodTable.length; ++i) { @@ -487,7 +480,7 @@ public final class Class public Class[] getInterfaces() { if (vmClass.interfaceTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); int stride = (isInterface() ? 1 : 2); Class[] array = new Class[vmClass.interfaceTable.length / stride]; @@ -534,8 +527,8 @@ public final class Class } public static boolean isInstance(VMClass c, Object o) { - return o != null && SystemClassLoader.isAssignableFrom - (c, SystemClassLoader.getVMClass(o)); + return o != null && Classes.isAssignableFrom + (c, Classes.getVMClass(o)); } public boolean isInstance(Object o) { @@ -620,7 +613,7 @@ public final class Class public T getAnnotation(Class class_) { for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { - SystemClassLoader.link(c, c.loader); + Classes.link(c, c.loader); Object[] table = (Object[]) c.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { @@ -636,7 +629,7 @@ public final class Class public Annotation[] getDeclaredAnnotations() { if (vmClass.addendum.annotationTable != null) { - SystemClassLoader.link(vmClass); + Classes.link(vmClass); Object[] table = (Object[]) vmClass.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index c63d971440..dbd376b62f 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -47,7 +47,7 @@ public abstract class ClassLoader { } return avian.SystemClassLoader.getClass - (avian.SystemClassLoader.defineVMClass(this, b, offset, length)); + (avian.Classes.defineVMClass(this, b, offset, length)); } protected Class findClass(String name) throws ClassNotFoundException { @@ -88,7 +88,7 @@ public abstract class ClassLoader { } protected void resolveClass(Class c) { - avian.SystemClassLoader.link(c.vmClass, this); + avian.Classes.link(c.vmClass, this); } private ClassLoader getParent() { diff --git a/classpath/java/lang/OutOfMemoryError.java b/classpath/java/lang/OutOfMemoryError.java index 29cae34d73..977da303e3 100644 --- a/classpath/java/lang/OutOfMemoryError.java +++ b/classpath/java/lang/OutOfMemoryError.java @@ -12,7 +12,7 @@ package java.lang; public class OutOfMemoryError extends VirtualMachineError { public OutOfMemoryError(String message) { - super(message, null); + super(message); } public OutOfMemoryError() { diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index b8f9ac0cf3..23fe3bf40f 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -13,6 +13,7 @@ package java.lang.reflect; import avian.VMField; import avian.AnnotationInvocationHandler; import avian.SystemClassLoader; +import avian.Classes; import java.lang.annotation.Annotation; @@ -204,7 +205,7 @@ public class Field extends AccessibleObject { } else { throw new IllegalArgumentException ("needed " + getType() + ", got " - + Class.getName(SystemClassLoader.vmClass(target)) + + + Class.getName(Classes.vmClass(target)) + " when setting " + Class.getName(vmField.class_) + "." + getName()); } break; diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index 15119c8d30..804450f123 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -515,8 +515,7 @@ public class Proxy { byte[] classData = out.toByteArray(); return avian.SystemClassLoader.getClass - (avian.SystemClassLoader.defineVMClass - (loader, classData, 0, classData.length)); + (avian.Classes.defineVMClass(loader, classData, 0, classData.length)); } public static Object newProxyInstance(ClassLoader loader, diff --git a/classpath/sun/reflect/ConstantPool.java b/classpath/sun/reflect/ConstantPool.java new file mode 100644 index 0000000000..582ce67607 --- /dev/null +++ b/classpath/sun/reflect/ConstantPool.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2010, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package sun.reflect; + +public class ConstantPool { } diff --git a/makefile b/makefile index 87567a58ab..e1af555cb4 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.3 diff --git a/src/bootimage.h b/src/bootimage.h index b76a77b7fa..ada3ce41d9 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -55,11 +55,13 @@ class BootImage { unsigned heapSize; unsigned codeSize; - unsigned classCount; + unsigned bootClassCount; + unsigned appClassCount; unsigned stringCount; unsigned callCount; - unsigned loader; + unsigned bootLoader; + unsigned appLoader; unsigned types; unsigned methodTree; unsigned methodTreeSentinal; diff --git a/src/builtin.cpp b/src/builtin.cpp index 2d0d115a3c..c1dc0f5c29 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -18,10 +18,11 @@ using namespace vm; namespace { int64_t -search(Thread* t, object name, object (*op)(Thread*, object), - bool replaceDots) +search(Thread* t, object loader, object name, + object (*op)(Thread*, object, object), bool replaceDots) { if (LIKELY(name)) { + PROTECT(t, loader); PROTECT(t, name); object n = makeByteArray(t, stringLength(t, name) + 1); @@ -32,7 +33,7 @@ search(Thread* t, object name, object (*op)(Thread*, object), replace('.', '/', s); } - object r = op(t, n); + object r = op(t, loader, n); if (t->exception) { return 0; } @@ -45,86 +46,45 @@ search(Thread* t, object name, object (*op)(Thread*, object), } } +object +resolveSystemClassThrow(Thread* t, object loader, object spec) +{ + return resolveSystemClass(t, loader, spec, true); +} + } // namespace -extern "C" JNIEXPORT void JNICALL -Avian_avian_SystemClassLoader_acquireClassLock -(Thread* t, object, uintptr_t*) -{ - acquire(t, t->m->classLock); -} - -extern "C" JNIEXPORT void JNICALL -Avian_avian_SystemClassLoader_releaseClassLock -(Thread* t, object, uintptr_t*) -{ - release(t, t->m->classLock); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_getVMClass -(Thread* t, object, uintptr_t* arguments) -{ - return reinterpret_cast - (objectClass(t, reinterpret_cast(arguments[0]))); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_defineVMClass -(Thread* t, object, uintptr_t* arguments) -{ - object loader = reinterpret_cast(arguments[0]); - object b = reinterpret_cast(arguments[1]); - int offset = arguments[2]; - int length = arguments[3]; - - 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); - - return reinterpret_cast(c); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findLoadedVMClass (Thread* t, object, uintptr_t* arguments) { - object name = reinterpret_cast(arguments[0]); + object loader = reinterpret_cast(arguments[0]); + object name = reinterpret_cast(arguments[1]); - return search(t, name, findLoadedSystemClass, true); + return search(t, loader, name, findLoadedClass, true); } extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_findVMClass (Thread* t, object, uintptr_t* arguments) -{ - object name = reinterpret_cast(arguments[0]); - - return search(t, name, resolveSystemClass, true); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_resolveVMClass -(Thread* t, object, uintptr_t* arguments) { object loader = reinterpret_cast(arguments[0]); - object spec = reinterpret_cast(arguments[1]); + object name = reinterpret_cast(arguments[1]); - return reinterpret_cast(resolveClass(t, loader, spec)); + return search(t, loader, name, resolveSystemClassThrow, true); } extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_resourceExists (Thread* t, object, uintptr_t* arguments) { - object name = reinterpret_cast(arguments[0]); + object loader = reinterpret_cast(arguments[0]); + object name = reinterpret_cast(arguments[1]); if (LIKELY(name)) { RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); - return t->m->finder->exists(RUNTIME_ARRAY_BODY(n)); + return getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n)); } else { t->exception = t->m->classpath->makeThrowable (t, Machine::NullPointerExceptionType); @@ -133,35 +93,11 @@ Avian_avian_SystemClassLoader_resourceExists } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_primitiveClass +Avian_avian_SystemClassLoader_getClass (Thread* t, object, uintptr_t* arguments) { - return reinterpret_cast(primitiveClass(t, arguments[0])); -} - -extern "C" JNIEXPORT void JNICALL -Avian_avian_SystemClassLoader_initialize -(Thread* t, object, uintptr_t* arguments) -{ - object this_ = reinterpret_cast(arguments[0]); - - initClass(t, this_); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_isAssignableFrom -(Thread* t, object, uintptr_t* arguments) -{ - object this_ = reinterpret_cast(arguments[0]); - object that = reinterpret_cast(arguments[1]); - - if (LIKELY(that)) { - return vm::isAssignableFrom(t, this_, that); - } else { - t->exception = t->m->classpath->makeThrowable - (t, Machine::NullPointerExceptionType); - return 0; - } + return reinterpret_cast + (getJClass(t, reinterpret_cast(arguments[0]))); } #ifdef AVIAN_HEAPDUMP @@ -208,7 +144,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength RUNTIME_ARRAY(char, p, stringLength(t, path) + 1); stringChars(t, path, RUNTIME_ARRAY_BODY(p)); - System::Region* r = t->m->finder->find(RUNTIME_ARRAY_BODY(p)); + System::Region* r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)); if (r) { jint rSize = r->length(); r->dispose(); @@ -229,7 +165,7 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open stringChars(t, path, RUNTIME_ARRAY_BODY(p)); return reinterpret_cast - (t->m->finder->find(RUNTIME_ARRAY_BODY(p))); + (t->m->appFinder->find(RUNTIME_ARRAY_BODY(p))); } else { t->exception = t->m->classpath->makeThrowable (t, Machine::NullPointerExceptionType); diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index b9b5570eda..6d64767ed7 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -49,15 +49,16 @@ class MyClasspath : public Classpath { const unsigned NormalPriority = 5; return vm::makeThread - (t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, t->m->loader, 0, 0, - group); + (t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, + root(t, Machine::BootLoader), 0, 0, group); } virtual void runThread(Thread* t) { object method = resolveMethod - (t, t->m->loader, "java/lang/Thread", "run", "(Ljava/lang/Thread;)V"); + (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); @@ -75,7 +76,7 @@ class MyClasspath : public Classpath { trace = makeTrace(t); } - object result = make(t, arrayBody(t, t->m->types, type)); + object result = make(t, vm::type(t, type)); set(t, result, ThrowableMessage, message); set(t, result, ThrowableTrace, trace); @@ -84,6 +85,12 @@ class MyClasspath : public Classpath { return result; } + virtual void + boot(Thread*) + { + // ignore + } + virtual void dispose() { @@ -352,7 +359,7 @@ Avian_java_lang_reflect_Array_makeObjectArray int length = arguments[1]; return reinterpret_cast - (makeObjectArray(t, classLoader(t, elementType), elementType, length)); + (makeObjectArray(t, elementType, length)); } extern "C" JNIEXPORT int64_t JNICALL @@ -408,7 +415,8 @@ Avian_java_lang_System_getVMProperty int64_t r = 0; if (::strcmp(RUNTIME_ARRAY_BODY(n), "java.lang.classpath") == 0) { - r = reinterpret_cast(makeString(t, "%s", t->m->finder->path())); + r = reinterpret_cast + (makeString(t, "%s", t->m->appFinder->path())); } else if (::strcmp(RUNTIME_ARRAY_BODY(n), "avian.version") == 0) { r = reinterpret_cast(makeString(t, AVIAN_VERSION)); } else if (::strcmp(RUNTIME_ARRAY_BODY(n), "file.encoding") == 0) { @@ -499,7 +507,8 @@ Avian_java_lang_Runtime_addShutdownHook ACQUIRE(t, t->m->shutdownLock); - t->m->shutdownHooks = makePair(t, hook, t->m->shutdownHooks); + setRoot(t, Machine::ShutdownHooks, + makePair(t, hook, root(t, Machine::ShutdownHooks))); } extern "C" JNIEXPORT int64_t JNICALL @@ -516,15 +525,13 @@ Avian_java_lang_Throwable_resolveTrace object trace = reinterpret_cast(*arguments); PROTECT(t, trace); - unsigned length = arrayLength(t, trace); - object elementType = arrayBody - (t, t->m->types, Machine::StackTraceElementType); - object array = makeObjectArray - (t, classLoader(t, elementType), elementType, length); + unsigned length = objectArrayLength(t, trace); + object elementType = type(t, Machine::StackTraceElementType); + object array = makeObjectArray(t, elementType, length); PROTECT(t, array); for (unsigned i = 0; i < length; ++i) { - object ste = makeStackTraceElement(t, arrayBody(t, trace, i)); + object ste = makeStackTraceElement(t, objectArrayBody(t, trace, i)); set(t, array, ArrayBody + (i * BytesPerWord), ste); } @@ -599,3 +606,85 @@ Avian_java_lang_Thread_setDaemon setDaemon(t, thread, daemon); } + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Classes_acquireClassLock +(Thread* t, object, uintptr_t*) +{ + acquire(t, t->m->classLock); +} + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Classes_releaseClassLock +(Thread* t, object, uintptr_t*) +{ + release(t, t->m->classLock); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_resolveVMClass +(Thread* t, object, uintptr_t* arguments) +{ + object loader = reinterpret_cast(arguments[0]); + object spec = reinterpret_cast(arguments[1]); + + return reinterpret_cast(resolveClass(t, loader, spec)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_primitiveClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast(primitiveClass(t, arguments[0])); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_defineVMClass +(Thread* t, object, uintptr_t* arguments) +{ + object loader = reinterpret_cast(arguments[0]); + object b = reinterpret_cast(arguments[1]); + int offset = arguments[2]; + int length = arguments[3]; + + 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); + + return reinterpret_cast(c); +} + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Classes_initialize +(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + + initClass(t, this_); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_isAssignableFrom +(Thread* t, object, uintptr_t* arguments) +{ + object this_ = reinterpret_cast(arguments[0]); + object that = reinterpret_cast(arguments[1]); + + if (LIKELY(that)) { + return vm::isAssignableFrom(t, this_, that); + } else { + t->exception = t->m->classpath->makeThrowable + (t, Machine::NullPointerExceptionType); + return 0; + } +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_getVMClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (objectClass(t, reinterpret_cast(arguments[0]))); +} diff --git a/src/classpath-common.h b/src/classpath-common.h index 23cccb8684..b9f1ef69b0 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -56,8 +56,7 @@ getTrace(Thread* t, unsigned skipCount) if (skipCount == 0) { object method = walker->method(); if (isAssignableFrom - (t, arrayBody(t, t->m->types, Machine::ThrowableType), - methodClass(t, method)) + (t, type(t, Machine::ThrowableType), methodClass(t, method)) and vm::strcmp(reinterpret_cast(""), &byteArrayBody(t, methodName(t, method), 0)) == 0) @@ -80,7 +79,7 @@ getTrace(Thread* t, unsigned skipCount) t->m->processor->walkStack(t, &v); - if (v.trace == 0) v.trace = makeArray(t, 0); + if (v.trace == 0) v.trace = makeObjectArray(t, 0); return v.trace; } diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 29c8866250..6871a3a9e6 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -40,6 +40,7 @@ # include # include # include +# include # include # include @@ -77,10 +78,10 @@ CREAT(string_t path, int mode) namespace local { const unsigned InterfaceVersion = 4; +const unsigned PageSize = 4 * 1024; Machine* globalMachine; - const char* primitiveName(Thread* t, object c) { @@ -144,6 +145,8 @@ class MyClasspath : public Classpath { virtual object makeJclass(Thread* t, object class_) { + PROTECT(t, class_); + object name = makeClassNameString(t, getClassName(t, class_)); return vm::makeJclass @@ -153,9 +156,7 @@ class MyClasspath : public Classpath { virtual object makeString(Thread* t, object array, int32_t offset, int32_t length) { - if (objectClass(t, array) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, array) == type(t, Machine::ByteArrayType)) { PROTECT(t, array); object charArray = makeCharArray(t, length); @@ -183,19 +184,25 @@ class MyClasspath : public Classpath { } return vm::makeThread - (t, 0, NormalPriority, 0, 0, false, false, false, 0, group, t->m->loader, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false); + (t, 0, NormalPriority, 0, 0, false, false, false, 0, group, + root(t, Machine::BootLoader), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, + 0, false); } virtual void runThread(Thread* t) { object method = resolveMethod - (t, t->m->loader, "java/lang/Thread", "run", "()V"); + (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); if (LIKELY(t->exception == 0)) { t->m->processor->invoke(t, method, t->javaThread); } + + acquire(t, t->javaThread); + t->flags &= ~Thread::ActiveFlag; + notifyAll(t, t->javaThread); + release(t, t->javaThread); } virtual object @@ -209,7 +216,7 @@ class MyClasspath : public Classpath { trace = makeTrace(t); } - object result = make(t, arrayBody(t, t->m->types, type)); + object result = make(t, vm::type(t, type)); set(t, result, ThrowableMessage, message); set(t, result, ThrowableTrace, trace); @@ -228,7 +235,22 @@ class MyClasspath : public Classpath { } t->m->processor->invoke - (t, t->m->loader, "java/lang/System", "initializeSystemClass", "()V", 0); + (t, root(t, Machine::BootLoader), "java/lang/System", + "initializeSystemClass", "()V", 0); + if (UNLIKELY(t->exception)) return; + + 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)); } virtual void @@ -281,16 +303,16 @@ countFields(Thread* t, object c, bool publicOnly) { object table = classFieldTable(t, c); if (publicOnly) { - return objectArrayLength(t, table); - } else { unsigned count = 0; for (unsigned i = 0; i < arrayLength(t, table); ++i) { object vmField = arrayBody(t, table, i); - if ((not publicOnly) or (fieldFlags(t, vmField) & ACC_PUBLIC)) { + if (fieldFlags(t, vmField) & ACC_PUBLIC) { ++ count; } } return count; + } else { + return objectArrayLength(t, table); } } @@ -430,8 +452,7 @@ resolveParameterJTypes(Thread* t, object loader, object spec, PROTECT(t, list); object array = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), - *parameterCount); + (t, type(t, Machine::JclassType), *parameterCount); PROTECT(t, array); for (int i = *parameterCount - 1; i >= 0; --i) { @@ -447,15 +468,14 @@ object resolveExceptionJTypes(Thread* t, object loader, object addendum) { if (addendum == 0) { - return makeObjectArray - (t, loader, arrayBody(t, t->m->types, Machine::JclassType), 0); + return makeObjectArray(t, type(t, Machine::JclassType), 0); } PROTECT(t, loader); PROTECT(t, addendum); object array = makeObjectArray - (t, loader, arrayBody(t, t->m->types, Machine::JclassType), + (t, type(t, Machine::JclassType), shortArrayLength(t, methodAddendumExceptionTable(t, addendum))); PROTECT(t, array); @@ -467,9 +487,7 @@ resolveExceptionJTypes(Thread* t, object loader, object addendum) object o = singletonObject(t, addendumPool(t, addendum), index); - if (objectClass(t, o) - == arrayBody(t, t->m->types, Machine::ReferenceType)) - { + if (objectClass(t, o) == type(t, Machine::ReferenceType)) { o = resolveClass(t, loader, referenceName(t, o)); if (UNLIKELY(t->exception)) return 0; @@ -532,6 +550,38 @@ Avian_sun_misc_Unsafe_registerNatives // ignore } +extern "C" JNIEXPORT int64_t +Avian_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2 +(Thread* t, object, uintptr_t* arguments) +{ + //object name = reinterpret_cast(arguments[1]); + object data = reinterpret_cast(arguments[2]); + int32_t offset = arguments[3]; + int32_t length = arguments[4]; + 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); + + return c ? reinterpret_cast(getJClass(t, c)) : 0; +} + +extern "C" JNIEXPORT int64_t +Avian_sun_misc_Unsafe_allocateInstance +(Thread* t, object, uintptr_t* arguments) +{ + object c = jclassVmClass(t, reinterpret_cast(arguments[1])); + PROTECT(t, c); + + initClass(t, c); + if (UNLIKELY(t->exception)) return 0; + + return reinterpret_cast(make(t, c)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_staticFieldOffset (Thread* t, object, uintptr_t* arguments) @@ -564,15 +614,90 @@ Avian_sun_misc_Unsafe_objectFieldOffset (t, jclassVmClass(t, jfieldClazz(t, jfield))), jfieldSlot(t, jfield))); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getObject +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + return cast(o, offset); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putObject +(Thread* t, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uintptr_t value = arguments[4]; + + set(t, o, offset, reinterpret_cast(value)); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + return cast(o, offset); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int32_t value = arguments[4]; + + cast(o, offset) = value; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getBoolean +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + return cast(o, offset); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putBoolean +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + uint8_t value = arguments[4]; + + cast(o, offset) = value; +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ +(Thread*, object, uintptr_t* arguments) +{ + object o = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int64_t value; memcpy(&value, arguments + 4, 8); + + cast(o, offset) = value; +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getObjectVolatile (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); - unsigned offset = arguments[2]; - object value = cast(o, offset); + int64_t offset; memcpy(&offset, arguments + 2, 8); + + uintptr_t value = cast(o, offset); loadMemoryBarrier(); - return reinterpret_cast(value); + return value; } extern "C" JNIEXPORT int64_t JNICALL @@ -588,6 +713,25 @@ Avian_sun_misc_Unsafe_compareAndSwapInt (&cast(target, offset), expect, update); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_compareAndSwapObject +(Thread* t, object, uintptr_t* arguments) +{ + object target = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + intptr_t expect = arguments[4]; + intptr_t update = arguments[5]; + + bool success = __sync_bool_compare_and_swap + (&cast(target, offset), expect, update); + + if (success) { + mark(t, target, offset); + } + + return success; +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapLong (Thread*, object, uintptr_t* arguments) @@ -625,6 +769,17 @@ Avian_sun_misc_Unsafe_freeMemory } } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_setMemory +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int64_t count; memcpy(&count, arguments + 3, 8); + int8_t v = arguments[5]; + + memset(reinterpret_cast(p), v, count); +} + extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_putLong__JJ (Thread*, object, uintptr_t* arguments) @@ -635,6 +790,16 @@ Avian_sun_misc_Unsafe_putLong__JJ *reinterpret_cast(p) = v; } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putInt__JI +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int32_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_getByte__J (Thread*, object, uintptr_t* arguments) @@ -644,6 +809,22 @@ Avian_sun_misc_Unsafe_getByte__J return *reinterpret_cast(p); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getInt__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_pageSize +(Thread*, object, uintptr_t*) +{ + return local::PageSize; +} + extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_ensureClassInitialized (Thread* t, object, uintptr_t* arguments) @@ -732,7 +913,7 @@ JVM_InitProperties(Thread* t, jobject properties) ENTER(t, Thread::ActiveState); object method = resolveMethod - (t, t->m->loader, "java/util/Properties", "setProperty", + (t, root(t, Machine::BootLoader), "java/util/Properties", "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); if (UNLIKELY(t->exception)) { @@ -776,6 +957,9 @@ JVM_InitProperties(Thread* t, jobject properties) local::setProperty(t, method, *properties, "sun.boot.library.path", getenv("LD_LIBRARY_PATH")); + local::setProperty(t, method, *properties, "java.protocol.handler.pkgs", + "avian"); + #endif local::setProperty(t, method, *properties, "file.encoding", "ASCII"); #ifdef ARCH_x86_32 @@ -811,10 +995,16 @@ extern "C" JNIEXPORT void JNICALL JVM_OnExit(void (*)(void)) { abort(); } extern "C" JNIEXPORT void JNICALL -JVM_Exit(jint) { abort(); } +JVM_Exit(jint code) +{ + exit(code); +} extern "C" JNIEXPORT void JNICALL -JVM_Halt(jint) { abort(); } +JVM_Halt(jint code) +{ + exit(code); +} extern "C" JNIEXPORT void JNICALL JVM_GC() @@ -896,7 +1086,7 @@ JVM_GetStackTraceDepth(Thread* t, jobject throwable) { ENTER(t, Thread::ActiveState); - return arrayLength(t, throwableTrace(t, *throwable)); + return objectArrayLength(t, throwableTrace(t, *throwable)); } extern "C" JNIEXPORT jobject JNICALL @@ -906,7 +1096,7 @@ JVM_GetStackTraceElement(Thread* t, jobject throwable, jint index) return makeLocalReference (t, makeStackTraceElement - (t, arrayBody(t, throwableTrace(t, *throwable), index))); + (t, objectArrayBody(t, throwableTrace(t, *throwable), index))); } extern "C" JNIEXPORT void JNICALL @@ -947,25 +1137,7 @@ JVM_IsThreadAlive(Thread* t, jobject thread) ENTER(t, Thread::ActiveState); Thread* p = reinterpret_cast(threadPeer(t, *thread)); - if (p) { - switch (p->state) { - case Thread::ActiveState: - case Thread::IdleState: - case Thread::ExclusiveState: - return true; - - case Thread::NoState: - case Thread::ZombieState: - case Thread::JoinedState: - case Thread::ExitState: - return false; - - default: - abort(t); - } - } else { - return false; - } + return p and (p->flags & Thread::ActiveFlag) != 0; } extern "C" JNIEXPORT void JNICALL @@ -1013,7 +1185,19 @@ extern "C" JNIEXPORT void JNICALL JVM_Interrupt(Thread*, jobject) { abort(); } extern "C" JNIEXPORT jboolean JNICALL -JVM_IsInterrupted(Thread*, jobject, jboolean) { abort(); } +JVM_IsInterrupted(Thread* t, jobject thread, jboolean clear) +{ + ENTER(t, Thread::ActiveState); + + acquire(t, *thread); + bool v = threadInterrupted(t, *thread); + if (clear) { + threadInterrupted(t, *thread) = false; + } + release(t, *thread); + + return v; +} extern "C" JNIEXPORT jboolean JNICALL JVM_HoldsLock(Thread*, jclass, jobject) { abort(); } @@ -1042,13 +1226,12 @@ JVM_GetClassContext(Thread* t) PROTECT(t, trace); object context = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), - arrayLength(t, trace)); + (t, type(t, Machine::JclassType), objectArrayLength(t, trace)); PROTECT(t, context); - for (unsigned i = 0; i < arrayLength(t, trace); ++i) { + for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) { object c = getJClass - (t, methodClass(t, traceElementMethod(t, arrayBody(t, trace, i)))); + (t, methodClass(t, traceElementMethod(t, objectArrayBody(t, trace, i)))); set(t, context, ArrayBody + (i * BytesPerWord), c); } @@ -1084,16 +1267,31 @@ JVM_LoadClass0(Thread*, jobject, jclass, jstring) { abort(); } extern "C" JNIEXPORT jint JNICALL -JVM_GetArrayLength(Thread*, jobject) { abort(); } +JVM_GetArrayLength(Thread* t, jobject array) +{ + ENTER(t, Thread::ActiveState); + + return cast(*array, BytesPerWord); +} extern "C" JNIEXPORT jobject JNICALL -JVM_GetArrayElement(Thread*, jobject, jint) { abort(); } +JVM_GetArrayElement(Thread* t, jobject array, jint index) +{ + ENTER(t, Thread::ActiveState); + + return makeLocalReference(t, objectArrayBody(t, *array, index)); +} extern "C" JNIEXPORT jvalue JNICALL JVM_GetPrimitiveArrayElement(Thread*, jobject, jint, jint) { abort(); } extern "C" JNIEXPORT void JNICALL -JVM_SetArrayElement(Thread*, jobject, jint, jobject) { abort(); } +JVM_SetArrayElement(Thread* t, jobject array, jint index, jobject value) +{ + ENTER(t, Thread::ActiveState); + + set(t, *array, ArrayBody + (index * BytesPerWord), (value ? *value : 0)); +} extern "C" JNIEXPORT void JNICALL JVM_SetPrimitiveArrayElement(Thread*, jobject, jint, jvalue, @@ -1126,8 +1324,7 @@ JVM_NewArray(Thread* t, jclass elementClass, jint length) default: abort(t); } } else { - return makeLocalReference - (t, makeObjectArray(t, t->m->loader, c, length)); + return makeLocalReference(t, makeObjectArray(t, c, length)); } } @@ -1152,32 +1349,32 @@ JVM_FindPrimitiveClass(Thread* t, const char* name) case 'b': if (name[1] == 'o') { return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JbooleanType))); + (t, getJClass(t, type(t, Machine::JbooleanType))); } else { return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JbyteType))); + (t, getJClass(t, type(t, Machine::JbyteType))); } case 'c': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JcharType))); + (t, getJClass(t, type(t, Machine::JcharType))); case 'd': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JdoubleType))); + (t, getJClass(t, type(t, Machine::JdoubleType))); case 'f': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JfloatType))); + (t, getJClass(t, type(t, Machine::JfloatType))); case 'i': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JintType))); + (t, getJClass(t, type(t, Machine::JintType))); case 'l': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JlongType))); + (t, getJClass(t, type(t, Machine::JlongType))); case 's': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JshortType))); + (t, getJClass(t, type(t, Machine::JshortType))); case 'v': return makeLocalReference - (t, getJClass(t, arrayBody(t, t->m->types, Machine::JvoidType))); + (t, getJClass(t, type(t, Machine::JvoidType))); default: t->exception = t->m->classpath->makeThrowable (t, Machine::IllegalArgumentExceptionType); @@ -1194,7 +1391,8 @@ JVM_FindClassFromClassLoader(Thread* t, const char* name, jboolean init, { ENTER(t, Thread::ActiveState); - object c = resolveClass(t, loader ? *loader : t->m->loader, name); + object c = resolveClass + (t, loader ? *loader : root(t, Machine::BootLoader), name); if (t->exception) { if (throwError) { t->exception = t->m->classpath->makeThrowable @@ -1224,25 +1422,13 @@ JVM_FindLoadedClass(Thread* t, jobject loader, jstring name) { ENTER(t, Thread::ActiveState); - ACQUIRE(t, t->m->classLock); - object spec = makeByteArray(t, stringLength(t, *name) + 1); { char* s = reinterpret_cast(&byteArrayBody(t, spec, 0)); stringChars(t, *name, s); replace('.', '/', s); } - object c; - if (loader == 0 or *loader == t->m->loader) { - c = findLoadedSystemClass(t, spec); - } else { - object map = classLoaderMap(t, *loader); - if (map) { - c = hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual); - } else { - c = 0; - } - } + object c = findLoadedClass(t, *loader, spec); return c ? makeLocalReference(t, getJClass(t, c)) : 0; } @@ -1275,8 +1461,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c) (classFlags(t, jclassVmClass(t, *c)) & ACC_INTERFACE) == 0 ? 2 : 1; object array = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), - arrayLength(t, table) / stride); + (t, type(t, Machine::JclassType), arrayLength(t, table) / stride); PROTECT(t, array); for (unsigned i = 0; i < objectArrayLength(t, array); ++i) { @@ -1287,9 +1472,7 @@ JVM_GetClassInterfaces(Thread* t, jclass c) return makeLocalReference(t, array); } else { return makeLocalReference - (t, makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JclassType), - 0)); + (t, makeObjectArray(t, type(t, Machine::JclassType), 0)); } } @@ -1299,7 +1482,8 @@ JVM_GetClassLoader(Thread* t, jclass c) ENTER(t, Thread::ActiveState); object loader = classLoader(t, jclassVmClass(t, *c)); - return loader == t->m->loader ? 0 : makeLocalReference(t, loader); + return loader == root(t, Machine::BootLoader) + ? 0 : makeLocalReference(t, loader); } extern "C" JNIEXPORT jboolean JNICALL @@ -1385,8 +1569,10 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly) object table = classMethodTable(t, jclassVmClass(t, *c)); if (table) { + PROTECT(t, table); + object array = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType), + (t, type(t, Machine::JmethodType), local::countMethods(t, jclassVmClass(t, *c), publicOnly)); PROTECT(t, array); @@ -1461,9 +1647,7 @@ JVM_GetClassDeclaredMethods(Thread* t, jclass c, jboolean publicOnly) return makeLocalReference(t, array); } else { return makeLocalReference - (t, makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JmethodType), - 0)); + (t, makeObjectArray(t, type(t, Machine::JmethodType), 0)); } } @@ -1474,8 +1658,10 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly) object table = classFieldTable(t, jclassVmClass(t, *c)); if (table) { + PROTECT(t, table); + object array = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType), + (t, type(t, Machine::JfieldType), local::countFields(t, jclassVmClass(t, *c), publicOnly)); PROTECT(t, array); @@ -1501,6 +1687,8 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly) return 0; } + PROTECT(t, type); + type = getJClass(t, type); object signature = t->m->classpath->makeString @@ -1524,12 +1712,12 @@ JVM_GetClassDeclaredFields(Thread* t, jclass c, jboolean publicOnly) set(t, array, ArrayBody + ((ai++) * BytesPerWord), field); } } + assert(t, ai == objectArrayLength(t, array)); return makeLocalReference(t, array); } else { return makeLocalReference - (t, makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JfieldType), 0)); + (t, makeObjectArray(t, type(t, Machine::JfieldType), 0)); } } @@ -1540,8 +1728,10 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly) object table = classMethodTable(t, jclassVmClass(t, *c)); if (table) { + PROTECT(t, table); + object array = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType), + (t, type(t, Machine::JconstructorType), local::countConstructors(t, jclassVmClass(t, *c), publicOnly)); PROTECT(t, array); @@ -1598,9 +1788,7 @@ JVM_GetClassDeclaredConstructors(Thread* t, jclass c, jboolean publicOnly) return makeLocalReference(t, array); } else { return makeLocalReference - (t, makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JconstructorType), - 0)); + (t, makeObjectArray(t, type(t, Machine::JconstructorType), 0)); } } @@ -1739,8 +1927,11 @@ JVM_DoPrivileged { ENTER(t, Thread::ActiveState); + // todo: cache these class and method lookups in the t->m->classpath + // object: + object privilegedAction = resolveClass - (t, t->m->loader, "java/security/PrivilegedAction"); + (t, root(t, Machine::BootLoader), "java/security/PrivilegedAction"); if (UNLIKELY(t->exception)) { return 0; @@ -1752,7 +1943,8 @@ JVM_DoPrivileged (t, privilegedAction, "run", "()Ljava/lang/Object;"); } else { object privilegedExceptionAction = resolveClass - (t, t->m->loader, "java/security/PrivilegedExceptionAction"); + (t, root(t, Machine::BootLoader), + "java/security/PrivilegedExceptionAction"); if (UNLIKELY(t->exception)) { return 0; @@ -1769,10 +1961,8 @@ JVM_DoPrivileged return makeLocalReference(t, result); } else { if (wrapException and not - (instanceOf - (t, arrayBody(t, t->m->types, Machine::ErrorType), t->exception) - or instanceOf - (t, arrayBody(t, t->m->types, Machine::RuntimeExceptionType), + (instanceOf(t, type(t, Machine::ErrorType), t->exception) + or instanceOf(t, type(t, Machine::RuntimeExceptionType), t->exception))) { object cause = t->exception; @@ -1781,7 +1971,8 @@ JVM_DoPrivileged t->exception = 0; object paeClass = resolveClass - (t, t->m->loader, "java/security/PrivilegedActionException"); + (t, root(t, Machine::BootLoader), + "java/security/PrivilegedActionException"); if (LIKELY(t->exception == 0)) { PROTECT(t, paeClass); @@ -2003,37 +2194,83 @@ extern "C" JNIEXPORT jint JNICALL JVM_Sync(jint) { abort(); } extern "C" JNIEXPORT jint JNICALL -JVM_InitializeSocketLibrary(void) { abort(); } +JVM_InitializeSocketLibrary() +{ +#ifdef PLATFORM_WINDOWS + static bool wsaInitialized = false; + if (not wsaInitialized) { + WSADATA data; + int r = WSAStartup(MAKEWORD(2, 2), &data); + if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { + return -1; + } else { + wsaInitialized = true; + } + } +#endif + return 0; +} extern "C" JNIEXPORT jint JNICALL -JVM_Socket(jint, jint, jint) { abort(); } +JVM_Socket(jint domain, jint type, jint protocol) +{ + return socket(domain, type, protocol); +} extern "C" JNIEXPORT jint JNICALL -JVM_SocketClose(jint) { abort(); } +JVM_SocketClose(jint socket) +{ +#ifdef PLATFORM_WINDOWS + return closesocket(socket); +#else + return close(socket); +#endif +} extern "C" JNIEXPORT jint JNICALL -JVM_SocketShutdown(jint, jint) { abort(); } +JVM_SocketShutdown(jint socket, jint how) +{ + return shutdown(socket, how); +} extern "C" JNIEXPORT jint JNICALL -JVM_Recv(jint, char*, jint, jint) { abort(); } +JVM_Recv(jint socket, char* dst, jint count, jint flags) +{ + return recv(socket, dst, count, flags); +} extern "C" JNIEXPORT jint JNICALL -JVM_Send(jint, char*, jint, jint) { abort(); } +JVM_Send(jint socket, char* src, jint count, jint flags) +{ + return send(socket, src, count, flags); +} extern "C" JNIEXPORT jint JNICALL JVM_Timeout(int, long) { abort(); } extern "C" JNIEXPORT jint JNICALL -JVM_Listen(jint, jint) { abort(); } +JVM_Listen(jint socket, jint count) +{ + return listen(socket, count); +} extern "C" JNIEXPORT jint JNICALL -JVM_Connect(jint, struct sockaddr*, jint) { abort(); } +JVM_Connect(jint socket, sockaddr* address, jint addressLength) +{ + return connect(socket, address, addressLength); +} extern "C" JNIEXPORT jint JNICALL JVM_Bind(jint, struct sockaddr*, jint) { abort(); } extern "C" JNIEXPORT jint JNICALL -JVM_Accept(jint, struct sockaddr*, jint*) { abort(); } +JVM_Accept(jint socket, struct sockaddr* address, jint* addressLength) +{ + socklen_t length = *addressLength; + int r = accept(socket, address, &length); + *addressLength = length; + return r; +} extern "C" JNIEXPORT jint JNICALL JVM_RecvFrom(jint, char*, int, @@ -2047,7 +2284,13 @@ extern "C" JNIEXPORT jint JNICALL JVM_SocketAvailable(jint, jint*) { abort(); } extern "C" JNIEXPORT jint JNICALL -JVM_GetSockName(jint, struct sockaddr*, int*) { abort(); } +JVM_GetSockName(jint socket, struct sockaddr* address, int* addressLength) +{ + socklen_t length = *addressLength; + int r = getsockname(socket, address, &length); + *addressLength = length; + return r; +} extern "C" JNIEXPORT jint JNICALL JVM_GetSockOpt(jint, int, int, char*, int*) { abort(); } diff --git a/src/compile-x86.S b/src/compile-x86.S index 9e86527444..7dd9349f40 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -22,7 +22,7 @@ #ifdef __x86_64__ -#define THREAD_STACK 2224 +#define THREAD_STACK 2216 #if defined __MINGW32__ || defined __CYGWIN32__ diff --git a/src/compile.cpp b/src/compile.cpp index 5619dd0769..ced35ebf15 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -40,7 +40,7 @@ namespace { namespace local { -const bool DebugCompile = true; +const bool DebugCompile = false; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -61,6 +61,20 @@ const unsigned InitialZoneCapacityInBytes = 64 * 1024; const unsigned ExecutableAreaSizeInBytes = 16 * 1024 * 1024; +enum Root { + CallTable, + MethodTree, + MethodTreeSentinal, + ObjectPools, + StaticTableArray, + VirtualThunks, + ReceiveMethod, + WindMethod, + RewindMethod +}; + +const unsigned RootCount = RewindMethod + 1; + inline bool isVmInvokeUnsafeStack(void* ip) { @@ -169,7 +183,7 @@ class MyThread: public Thread { // in this function, we "atomically" update the thread context // fields in such a way to ensure that another thread may // interrupt us at any time and still get a consistent, accurate - // stack trace. See MyProcess::getStackTrace for details. + // stack trace. See MyProcessor::getStackTrace for details. assert(t, t->transition == 0); @@ -277,7 +291,7 @@ resolveTarget(MyThread* t, void* stack, object method) PROTECT(t, method); PROTECT(t, class_); - resolveSystemClass(t, className(t, class_)); + resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_)); if (UNLIKELY(t->exception)) return 0; } @@ -294,7 +308,7 @@ resolveTarget(MyThread* t, object class_, unsigned index) if (classVmFlags(t, class_) & BootstrapFlag) { PROTECT(t, class_); - resolveSystemClass(t, className(t, class_)); + resolveSystemClass(t, root(t, Machine::BootLoader), className(t, class_)); if (UNLIKELY(t->exception)) return 0; } @@ -302,10 +316,10 @@ resolveTarget(MyThread* t, object class_, unsigned index) } object& -methodTree(MyThread* t); +root(Thread* t, Root root); -object -methodTreeSentinal(MyThread* t); +void +setRoot(Thread* t, Root root, object value); unsigned compiledSize(intptr_t address) @@ -348,8 +362,8 @@ methodForIp(MyThread* t, void* ip) // compile(MyThread*, Allocator*, BootContext*, object)): loadMemoryBarrier(); - return treeQuery(t, methodTree(t), reinterpret_cast(ip), - methodTreeSentinal(t), compareIpToMethodBounds); + return treeQuery(t, root(t, MethodTree), reinterpret_cast(ip), + root(t, MethodTreeSentinal), compareIpToMethodBounds); } class MyStackWalker: public Processor::StackWalker { @@ -2067,18 +2081,6 @@ unwind(MyThread* t) vmJump(ip, base, stack, t, 0, 0); } -object& -objectPools(MyThread* t); - -object& -windMethod(MyThread* t); - -object& -rewindMethod(MyThread* t); - -object& -receiveMethod(MyThread* t); - uintptr_t defaultThunk(MyThread* t); @@ -2408,11 +2410,10 @@ longToFloat(int64_t a) } uint64_t -makeBlankObjectArray(MyThread* t, object loader, object class_, int32_t length) +makeBlankObjectArray(MyThread* t, object class_, int32_t length) { if (length >= 0) { - return reinterpret_cast - (makeObjectArray(t, loader, class_, length)); + return reinterpret_cast(makeObjectArray(t, class_, length)); } else { object message = makeString(t, "%d", length); t->exception = t->m->classpath->makeThrowable @@ -2595,14 +2596,14 @@ void NO_RETURN throwArrayIndexOutOfBounds(MyThread* t) { if (ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t))) { - t->tracing = true; + atomicOr(&(t->flags), Thread::TracingFlag); t->exception = t->m->classpath->makeThrowable - (t, Machine::ArrayIndexOutOfBoundsExceptionType); - t->tracing = false; + (t, Machine::ArrayIndexOutOfBoundsExceptionType); + atomicAnd(&(t->flags), ~Thread::TracingFlag); } else { // not enough memory available for a new exception and stack trace // -- use a preallocated instance instead - t->exception = t->m->arrayIndexOutOfBoundsException; + t->exception = root(t, Machine::ArrayIndexOutOfBoundsException); } unwind(t); @@ -2658,7 +2659,7 @@ makeNew64(Thread* t, object class_) void gcIfNecessary(MyThread* t) { - if (UNLIKELY(t->useBackupHeap)) { + if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { collect(t, Heap::MinorCollection); } } @@ -3411,9 +3412,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, frame->trace(0, 0), BytesPerWord, Compiler::ObjectType, - 4, c->register_(t->arch->thread()), - frame->append(classLoader(t, methodClass(t, context->method))), - frame->append(class_), length)); + 3, c->register_(t->arch->thread()), frame->append(class_), length)); } break; case areturn: { @@ -4374,16 +4373,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (singletonIsObject(t, pool, index - 1)) { object v = singletonObject(t, pool, index - 1); - if (objectClass(t, v) - == arrayBody(t, t->m->types, Machine::ReferenceType)) - { + if (objectClass(t, v) == type(t, Machine::ReferenceType)) { object class_ = resolveClassInPool(t, context->method, index - 1); if (UNLIKELY(t->exception)) return; frame->pushObject(frame->append(getJClass(t, class_))); - } else if (objectClass(t, v) - == arrayBody(t, t->m->types, Machine::ClassType)) - { + } else if (objectClass(t, v) == type(t, Machine::ClassType)) { frame->pushObject(frame->append(getJClass(t, v))); } else { frame->pushObject(frame->append(v)); @@ -5723,8 +5718,8 @@ finish(MyThread* t, Allocator* allocator, Context* context) initArray(t, pool, context->objectPoolCount + 1); mark(t, pool, 0); - set(t, pool, ArrayBody, objectPools(t)); - objectPools(t) = pool; + set(t, pool, ArrayBody, root(t, ObjectPools)); + setRoot(t, ObjectPools, pool); unsigned i = 1; for (PoolElement* p = context->objectPool; p; p = p->next) { @@ -6009,14 +6004,6 @@ compileMethod2(MyThread* t, void* ip) t->trace->targetMethod = 0; } - if (false) { - compile(t, codeAllocator(t), 0, resolveMethod - (t, t->m->loader, - "org/eclipse/swt/widgets/TableItem", - "getBounds", - "(IIZZZZJ)Lorg/eclipse/swt/internal/win32/RECT;")); - } - if (UNLIKELY(t->exception)) { return 0; } else { @@ -6494,9 +6481,7 @@ findFrameMap(MyThread* t, void* stack, object method, int32_t offset, int32_t** map, unsigned* start) { object table = codePool(t, methodCode(t, method)); - if (objectClass(t, table) - == arrayBody(t, t->m->types, Machine::IntArrayType)) - { + if (objectClass(t, table) == type(t, Machine::IntArrayType)) { findFrameMapInSimpleTable(t, method, table, offset, map, start); } else { findFrameMapInGeneralTable(t, stack, method, table, offset, map, start); @@ -6813,16 +6798,16 @@ callContinuation(MyThread* t, object continuation, object result, nextContinuation = continuationContextContinuation(t, rewindContext); action = Rewind; - if (rewindMethod(t) == 0) { + if (root(t, RewindMethod) == 0) { PROTECT(t, nextContinuation); object method = resolveMethod - (t, t->m->loader, "avian/Continuations", "rewind", + (t, root(t, Machine::BootLoader), "avian/Continuations", "rewind", "(Ljava/lang/Runnable;Lavian/Callback;Ljava/lang/Object;" "Ljava/lang/Throwable;)V"); if (method) { - rewindMethod(t) = method; + setRoot(t, RewindMethod, method); compile(t, local::codeAllocator(t), 0, method); @@ -6864,7 +6849,7 @@ callContinuation(MyThread* t, object continuation, object result, transition(t, 0, 0, 0, nextContinuation, t->trace); jumpAndInvoke - (t, rewindMethod(t), base, stack, + (t, root(t, RewindMethod), base, stack, continuationContextBefore(t, continuationContext(t, nextContinuation)), continuation, result, exception); } break; @@ -6890,26 +6875,27 @@ callWithCurrentContinuation(MyThread* t, object receiver) { PROTECT(t, receiver); - if (receiveMethod(t) == 0) { + if (root(t, ReceiveMethod) == 0) { object m = resolveMethod - (t, t->m->loader, "avian/CallbackReceiver", "receive", + (t, root(t, Machine::BootLoader), "avian/CallbackReceiver", "receive", "(Lavian/Callback;)Ljava/lang/Object;"); if (m) { - receiveMethod(t) = m; + setRoot(t, ReceiveMethod, m); - object continuationClass = arrayBody - (t, t->m->types, Machine::ContinuationType); + object continuationClass = type(t, Machine::ContinuationType); if (classVmFlags(t, continuationClass) & BootstrapFlag) { - resolveSystemClass(t, vm::className(t, continuationClass)); + resolveSystemClass + (t, root(t, Machine::BootLoader), + vm::className(t, continuationClass)); } } } if (LIKELY(t->exception == 0)) { method = findInterfaceMethod - (t, receiveMethod(t), objectClass(t, receiver)); + (t, root(t, ReceiveMethod), objectClass(t, receiver)); PROTECT(t, method); compile(t, local::codeAllocator(t), 0, method); @@ -6938,14 +6924,14 @@ dynamicWind(MyThread* t, object before, object thunk, object after) PROTECT(t, thunk); PROTECT(t, after); - if (windMethod(t) == 0) { + if (root(t, WindMethod) == 0) { object method = resolveMethod - (t, t->m->loader, "avian/Continuations", "wind", + (t, root(t, Machine::BootLoader), "avian/Continuations", "wind", "(Ljava/lang/Runnable;Ljava/util/concurrent/Callable;" "Ljava/lang/Runnable;)Lavian/Continuations$UnwindResult;"); if (method) { - windMethod(t) = method; + setRoot(t, WindMethod, method); compile(t, local::codeAllocator(t), 0, method); } } @@ -6962,7 +6948,7 @@ dynamicWind(MyThread* t, object before, object thunk, object after) } if (LIKELY(t->exception == 0)) { - jumpAndInvoke(t, windMethod(t), base, stack, before, thunk, after); + jumpAndInvoke(t, root(t, WindMethod), base, stack, before, thunk, after); } else { unwind(t); } @@ -7117,7 +7103,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments) } if (t->exception) { - if (UNLIKELY(t->useBackupHeap)) { + if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { collect(t, Heap::MinorCollection); } return 0; @@ -7173,14 +7159,14 @@ class SegFaultHandler: public System::SignalHandler { *base, t->continuation, t->trace); if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) { - t->tracing = true; + atomicOr(&(t->flags), Thread::TracingFlag); t->exception = t->m->classpath->makeThrowable (t, Machine::NullPointerExceptionType); - t->tracing = false; + atomicAnd(&(t->flags), ~Thread::TracingFlag); } else { // not enough memory available for a new NPE and stack trace // -- use a preallocated instance instead - t->exception = t->m->nullPointerException; + t->exception = root(t, Machine::NullPointerException); } // printTrace(t, t->exception); @@ -7220,12 +7206,12 @@ boot(MyThread* t, BootImage* image); class MyProcessor; -void -compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p); - MyProcessor* processor(MyThread* t); +void +compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p); + class MyProcessor: public Processor { public: class Thunk { @@ -7255,15 +7241,7 @@ class MyProcessor: public Processor { MyProcessor(System* s, Allocator* allocator, bool useNativeFeatures): s(s), allocator(allocator), - callTable(0), - methodTree(0), - methodTreeSentinal(0), - objectPools(0), - staticTableArray(0), - virtualThunks(0), - receiveMethod(0), - windMethod(0), - rewindMethod(0), + roots(0), bootImage(0), codeAllocator(s, 0, 0), callTableSize(0), @@ -7365,15 +7343,7 @@ class MyProcessor: public Processor { MyThread* t = static_cast(vmt); if (t == t->m->rootThread) { - v->visit(&callTable); - v->visit(&methodTree); - v->visit(&methodTreeSentinal); - v->visit(&objectPools); - v->visit(&staticTableArray); - v->visit(&virtualThunks); - v->visit(&receiveMethod); - v->visit(&windMethod); - v->visit(&rewindMethod); + v->visit(&roots); } for (MyThread::CallTrace* trace = t->trace; trace; trace = trace->next) { @@ -7499,16 +7469,6 @@ class MyProcessor: public Processor { PROTECT(t, method); - if (false) { - compile(static_cast(t), - local::codeAllocator(static_cast(t)), 0, - resolveMethod(t, t->m->loader, - "com/ecovate/nat/logic/Cache", - "findInCache", - "(Ljava/lang/String;Ljava/lang/String;JZ)Lcom/ecovate/shared/xmlrpc/Resource;")); - trap(); - } - compile(static_cast(t), local::codeAllocator(static_cast(t)), 0, method); @@ -7636,9 +7596,9 @@ class MyProcessor: public Processor { } if (ensure(t, traceSize(target))) { - t->tracing = true; + atomicOr(&(t->flags), Thread::TracingFlag); trace = makeTrace(t, target); - t->tracing = false; + atomicAnd(&(t->flags), ~Thread::TracingFlag); } } @@ -7650,7 +7610,7 @@ class MyProcessor: public Processor { t->m->system->visit(t->systemThread, target->systemThread, &visitor); - if (UNLIKELY(t->useBackupHeap)) { + if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { PROTECT(t, visitor.trace); collect(t, Heap::MinorCollection); @@ -7679,10 +7639,10 @@ class MyProcessor: public Processor { *addresses = bootContext.addresses; } - virtual void visitRoots(HeapWalker* w) { - bootImage->methodTree = w->visitRoot(methodTree); - bootImage->methodTreeSentinal = w->visitRoot(methodTreeSentinal); - bootImage->virtualThunks = w->visitRoot(virtualThunks); + virtual void visitRoots(Thread* t, HeapWalker* w) { + bootImage->methodTree = w->visitRoot(root(t, MethodTree)); + bootImage->methodTreeSentinal = w->visitRoot(root(t, MethodTreeSentinal)); + bootImage->virtualThunks = w->visitRoot(root(t, VirtualThunks)); } virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) { @@ -7693,8 +7653,10 @@ class MyProcessor: public Processor { (t->m->heap->allocate(callTableSize * sizeof(unsigned) * 2)); unsigned index = 0; - for (unsigned i = 0; i < arrayLength(t, callTable); ++i) { - for (object p = arrayBody(t, callTable, i); p; p = callNodeNext(t, p)) { + for (unsigned i = 0; i < arrayLength(t, root(t, CallTable)); ++i) { + for (object p = arrayBody(t, root(t, CallTable), i); + p; p = callNodeNext(t, p)) + { table[index++] = callNodeAddress(t, p) - reinterpret_cast(codeAllocator.base); table[index++] = w->map()->find(callNodeTarget(t, p)) @@ -7712,14 +7674,19 @@ class MyProcessor: public Processor { codeAllocator.capacity = ExecutableAreaSizeInBytes; } + roots = makeArray(t, RootCount); + if (image) { local::boot(static_cast(t), image); } else { - callTable = makeArray(t, 128); - - methodTree = methodTreeSentinal = makeTreeNode(t, 0, 0, 0); - set(t, methodTree, TreeNodeLeft, methodTreeSentinal); - set(t, methodTree, TreeNodeRight, methodTreeSentinal); + setRoot(t, CallTable, makeArray(t, 128)); + + setRoot(t, MethodTreeSentinal, makeTreeNode(t, 0, 0, 0)); + setRoot(t, MethodTree, root(t, MethodTreeSentinal)); + set(t, root(t, MethodTree), TreeNodeLeft, + root(t, MethodTreeSentinal)); + set(t, root(t, MethodTree), TreeNodeRight, + root(t, MethodTreeSentinal)); } local::compileThunks(static_cast(t), &codeAllocator, this); @@ -7776,43 +7743,10 @@ class MyProcessor: public Processor { abort(t); } } - - virtual void registerNative(Thread* t, object method, void* function) { - PROTECT(t, method); - - expect(t, methodFlags(t, method) & ACC_NATIVE); - - object native = makeNative(t, function, false); - - // ensure other threads only see the methodCode field populated - // once the object it points do has been populated: - storeStoreMemoryBarrier(); - - set(t, method, MethodCode, native); - } - - virtual void unregisterNatives(Thread* t, object c) { - if (classMethodTable(t, c)) { - for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { - object method = arrayBody(t, classMethodTable(t, c), i); - if (methodFlags(t, method) & ACC_NATIVE) { - set(t, method, MethodCode, 0); - } - } - } - } System* s; Allocator* allocator; - object callTable; - object methodTree; - object methodTreeSentinal; - object objectPools; - object staticTableArray; - object virtualThunks; - object receiveMethod; - object windMethod; - object rewindMethod; + object roots; BootImage* bootImage; SegFaultHandler segFaultHandler; FixedAllocator codeAllocator; @@ -7883,11 +7817,10 @@ isThunkUnsafeStack(MyProcessor::ThunkCollection* thunks, void* ip) bool isVirtualThunk(MyThread* t, void* ip) { - MyProcessor* p = processor(t); - - for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) { - uintptr_t start = wordArrayBody(t, p->virtualThunks, i); - uintptr_t end = start + wordArrayBody(t, p->virtualThunks, i + 1); + for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2) + { + uintptr_t start = wordArrayBody(t, root(t, VirtualThunks), i); + uintptr_t end = start + wordArrayBody(t, root(t, VirtualThunks), i + 1); if (reinterpret_cast(ip) >= start and reinterpret_cast(ip) < end) @@ -7921,8 +7854,7 @@ findCallNode(MyThread* t, void* address) // compile(MyThread*, Allocator*, BootContext*, object)): loadMemoryBarrier(); - MyProcessor* p = processor(t); - object table = p->callTable; + object table = root(t, CallTable); intptr_t key = reinterpret_cast(address); unsigned index = static_cast(key) & (arrayLength(t, table) - 1); @@ -8002,8 +7934,8 @@ insertCallNode(MyThread* t, object table, unsigned* size, object node) void insertCallNode(MyThread* t, object node) { - MyProcessor* p = processor(t); - p->callTable = insertCallNode(t, p->callTable, &(p->callTableSize), node); + setRoot(t, CallTable, insertCallNode + (t, root(t, CallTable), &(processor(t)->callTableSize), node)); } object @@ -8022,14 +7954,19 @@ makeClassMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap) } object -makeStaticTableArray(Thread* t, unsigned* table, unsigned count, - uintptr_t* heap) +makeStaticTableArray(Thread* t, unsigned* bootTable, unsigned bootCount, + unsigned* appTable, unsigned appCount, uintptr_t* heap) { - object array = makeArray(t, count); + object array = makeArray(t, bootCount + appCount); - for (unsigned i = 0; i < count; ++i) { + for (unsigned i = 0; i < bootCount; ++i) { set(t, array, ArrayBody + (i * BytesPerWord), - classStaticTable(t, bootObject(heap, table[i]))); + classStaticTable(t, bootObject(heap, bootTable[i]))); + } + + for (unsigned i = 0; i < appCount; ++i) { + set(t, array, ArrayBody + ((bootCount + i) * BytesPerWord), + classStaticTable(t, bootObject(heap, appTable[i]))); } return array; @@ -8134,9 +8071,9 @@ fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code, } void -fixupMethods(Thread* t, BootImage* image, uint8_t* code) +fixupMethods(Thread* t, object map, BootImage* image, uint8_t* code) { - for (HashMapIterator it(t, t->m->classMap); it.hasMore();) { + for (HashMapIterator it(t, map); it.hasMore();) { object c = tripleSecond(t, it.next()); if (classMethodTable(t, c)) { @@ -8213,12 +8150,10 @@ fixupThunks(MyThread* t, BootImage* image, uint8_t* code) void fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code) { - MyProcessor* p = processor(t); - - for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); i += 2) { - if (wordArrayBody(t, p->virtualThunks, i)) { - wordArrayBody(t, p->virtualThunks, i) - = (wordArrayBody(t, p->virtualThunks, i) - image->codeBase) + for (unsigned i = 0; i < wordArrayLength(t, root(t, VirtualThunks)); i += 2) { + if (wordArrayBody(t, root(t, VirtualThunks), i)) { + wordArrayBody(t, root(t, VirtualThunks), i) + = (wordArrayBody(t, root(t, VirtualThunks), i) - image->codeBase) + reinterpret_cast(code); } } @@ -8229,8 +8164,9 @@ boot(MyThread* t, BootImage* image) { assert(t, image->magic == BootImage::Magic); - unsigned* classTable = reinterpret_cast(image + 1); - unsigned* stringTable = classTable + image->classCount; + unsigned* bootClassTable = reinterpret_cast(image + 1); + unsigned* appClassTable = bootClassTable + image->bootClassCount; + unsigned* stringTable = appClassTable + image->appClassCount; unsigned* callTable = stringTable + image->stringCount; uintptr_t* heapMap = reinterpret_cast @@ -8254,39 +8190,48 @@ boot(MyThread* t, BootImage* image) t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord); - t->m->loader = bootObject(heap, image->loader); + setRoot(t, Machine::BootLoader, bootObject(heap, image->bootLoader)); + setRoot(t, Machine::AppLoader, bootObject(heap, image->appLoader)); t->m->types = bootObject(heap, image->types); MyProcessor* p = static_cast(t->m->processor); - p->methodTree = bootObject(heap, image->methodTree); - p->methodTreeSentinal = bootObject(heap, image->methodTreeSentinal); + setRoot(t, MethodTree, bootObject(heap, image->methodTree)); + setRoot(t, MethodTreeSentinal, bootObject(heap, image->methodTreeSentinal)); - p->virtualThunks = bootObject(heap, image->virtualThunks); + setRoot(t, VirtualThunks, bootObject(heap, image->virtualThunks)); fixupCode(t, codeMap, codeMapSizeInWords, code, heap); syncInstructionCache(code, image->codeSize); - t->m->classMap = makeClassMap(t, classTable, image->classCount, heap); + setRoot(t, Machine::ClassMap, makeClassMap + (t, bootClassTable, image->bootClassCount, heap)); - t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap); + set(t, root(t, Machine::AppLoader), ClassLoaderMap, makeClassMap + (t, appClassTable, image->appClassCount, heap)); + + setRoot(t, Machine::StringMap, makeStringMap + (t, stringTable, image->stringCount, heap)); p->callTableSize = image->callCount; - p->callTable = makeCallTable - (t, heap, callTable, image->callCount, - reinterpret_cast(code)); - p->staticTableArray = makeStaticTableArray - (t, classTable, image->classCount, heap); + setRoot(t, CallTable, makeCallTable + (t, heap, callTable, image->callCount, + reinterpret_cast(code))); + setRoot(t, StaticTableArray, makeStaticTableArray + (t, bootClassTable, image->bootClassCount, + appClassTable, image->appClassCount, heap)); + fixupThunks(t, image, code); fixupVirtualThunks(t, image, code); - fixupMethods(t, image, code); + fixupMethods(t, root(t, Machine::ClassMap), image, code); + fixupMethods(t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code); - t->m->bootstrapClassMap = makeHashMap(t, 0, 0); + setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0)); } intptr_t @@ -8539,30 +8484,6 @@ processor(MyThread* t) return static_cast(t->m->processor); } -object& -objectPools(MyThread* t) -{ - return processor(t)->objectPools; -} - -object& -windMethod(MyThread* t) -{ - return processor(t)->windMethod; -} - -object& -rewindMethod(MyThread* t) -{ - return processor(t)->rewindMethod; -} - -object& -receiveMethod(MyThread* t) -{ - return processor(t)->receiveMethod; -} - uintptr_t defaultThunk(MyThread* t) { @@ -8639,32 +8560,30 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) uintptr_t virtualThunk(MyThread* t, unsigned index) { - MyProcessor* p = processor(t); - - if (p->virtualThunks == 0 - or wordArrayLength(t, p->virtualThunks) <= index * 2) + if (root(t, VirtualThunks) == 0 + or wordArrayLength(t, root(t, VirtualThunks)) <= index * 2) { object newArray = makeWordArray(t, nextPowerOfTwo((index + 1) * 2)); - if (p->virtualThunks) { + if (root(t, VirtualThunks)) { memcpy(&wordArrayBody(t, newArray, 0), - &wordArrayBody(t, p->virtualThunks, 0), - wordArrayLength(t, p->virtualThunks) * BytesPerWord); + &wordArrayBody(t, root(t, VirtualThunks), 0), + wordArrayLength(t, root(t, VirtualThunks)) * BytesPerWord); } - p->virtualThunks = newArray; + setRoot(t, VirtualThunks, newArray); } - if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) { + if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) { ACQUIRE(t, t->m->classLock); - if (wordArrayBody(t, p->virtualThunks, index * 2) == 0) { + if (wordArrayBody(t, root(t, VirtualThunks), index * 2) == 0) { unsigned size; uintptr_t thunk = compileVirtualThunk(t, index, &size); - wordArrayBody(t, p->virtualThunks, index * 2) = thunk; - wordArrayBody(t, p->virtualThunks, (index * 2) + 1) = size; + wordArrayBody(t, root(t, VirtualThunks), index * 2) = thunk; + wordArrayBody(t, root(t, VirtualThunks), (index * 2) + 1) = size; } } - return wordArrayBody(t, p->virtualThunks, index * 2); + return wordArrayBody(t, root(t, VirtualThunks), index * 2); } void @@ -8717,10 +8636,12 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, methodCode(t, method), reinterpret_cast(compiled)); - methodTree(t) = treeInsert - (t, &(context.zone), methodTree(t), - reinterpret_cast(compiled), clone, methodTreeSentinal(t), - compareIpToMethodBounds); + setRoot + (t, MethodTree, treeInsert + (t, &(context.zone), root(t, MethodTree), + reinterpret_cast(compiled), clone, + root(t, MethodTreeSentinal), + compareIpToMethodBounds)); storeStoreMemoryBarrier(); @@ -8731,22 +8652,23 @@ compile(MyThread* t, Allocator* allocator, BootContext* bootContext, = compiled; } - treeUpdate(t, methodTree(t), reinterpret_cast(compiled), - method, methodTreeSentinal(t), compareIpToMethodBounds); + treeUpdate(t, root(t, MethodTree), reinterpret_cast(compiled), + method, root(t, MethodTreeSentinal), compareIpToMethodBounds); } } } object& -methodTree(MyThread* t) +root(Thread* t, Root root) { - return processor(t)->methodTree; + return arrayBody(t, processor(static_cast(t))->roots, root); } -object -methodTreeSentinal(MyThread* t) +void +setRoot(Thread* t, Root root, object value) { - return processor(t)->methodTreeSentinal; + set(t, processor(static_cast(t))->roots, + ArrayBody + (root * BytesPerWord), value); } FixedAllocator* diff --git a/src/continuations-x86.S b/src/continuations-x86.S index 5dc0ba9e10..c55679d0ba 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2232 +#define THREAD_CONTINUATION 2224 #define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2240 -#define THREAD_EXCEPTION_OFFSET 2248 -#define THREAD_EXCEPTION_HANDLER 2256 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2232 +#define THREAD_EXCEPTION_OFFSET 2240 +#define THREAD_EXCEPTION_HANDLER 2248 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 diff --git a/src/gnu.cpp b/src/gnu.cpp deleted file mode 100644 index 84e7193ee6..0000000000 --- a/src/gnu.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* Copyright (c) 2009, Avian Contributors - - Permission to use, copy, modify, and/or distribute this software - for any purpose with or without fee is hereby granted, provided - that the above copyright notice and this permission notice appear - in all copies. - - There is NO WARRANTY for this software. See license.txt for - details. */ - -#include "machine.h" -#include "constants.h" -#include "processor.h" -#include "util.h" - -using namespace vm; - -namespace { - -void -setProperty(Thread* t, object method, object properties, - const char* name, const void* value, const char* format = "%s") -{ - PROTECT(t, method); - PROTECT(t, properties); - - object n = makeString(t, "%s", name); - PROTECT(t, n); - - object v = makeString(t, format, value); - - t->m->processor->invoke(t, method, properties, n, v); -} - -} // namespace - -namespace vm { - -jobject JNICALL -NewDirectByteBuffer(Thread* t, void* address, jlong capacity) -{ - const char* pointerClassName; - const char* initSpec; - if (BytesPerWord == 8) { - pointerClassName = "gnu/classpath/Pointer64"; - initSpec = "(J)V"; - } else { - pointerClassName = "gnu/classpath/Pointer32"; - initSpec = "(I)V"; - } - - object pointerClass = resolveClass(t, t->m->loader, pointerClassName); - if (UNLIKELY(pointerClass == 0)) return 0; - PROTECT(t, pointerClass); - - object pointerConstructor = resolveMethod - (t, pointerClass, "", initSpec); - if (UNLIKELY(pointerConstructor == 0)) return 0; - - object pointer = make(t, pointerClass); - PROTECT(t, pointer); - - t->m->processor->invoke(t, pointerConstructor, pointer, address); - if (UNLIKELY(t->exception)) return 0; - - object bufferClass = resolveClass - (t, t->m->loader, "java/nio/DirectByteBufferImpl$ReadWrite"); - if (UNLIKELY(bufferClass == 0)) return 0; - PROTECT(t, bufferClass); - - object bufferConstructor = resolveMethod - (t, bufferClass, "", "(Lgnu/classpath/Pointer;int)V"); - if (UNLIKELY(bufferConstructor == 0)) return 0; - - object buffer = make(t, bufferClass); - PROTECT(t, buffer); - - t->m->processor->invoke - (t, bufferConstructor, buffer, &pointer, static_cast(capacity)); - if (UNLIKELY(t->exception)) return 0; - - return makeLocalReference(t, buffer); -} - -void* JNICALL -GetDirectBufferAddress(Thread* t, jobject buffer) -{ - object addressField = resolveField - (t, objectClass(t, *buffer), "address", "Lgnu/classpath/Pointer;"); - if (UNLIKELY(addressField == 0)) return 0; - - object address = cast(*buffer, fieldOffset(t, addressField)); - if (address == 0) return 0; - - const char* dataSpec; - if (BytesPerWord == 8) { - dataSpec = "J"; - } else { - dataSpec = "I"; - } - - object dataField = resolveField - (t, objectClass(t, address), "data", dataSpec); - if (UNLIKELY(dataField == 0)) return 0; - - return cast(address, fieldOffset(t, dataField)); -} - -jlong JNICALL -GetDirectBufferCapacity(Thread* t, jobject buffer) -{ - object capField = resolveField(t, objectClass(t, *buffer), "cap", "I"); - if (UNLIKELY(capField == 0)) return 0; - - return cast(*buffer, fieldOffset(t, capField)); -} - -} // namespace vm - -extern "C" JNIEXPORT void JNICALL -Avian_gnu_classpath_VMSystemProperties_preInit -(Thread* t, object, uintptr_t* arguments) -{ - object properties = reinterpret_cast(arguments[0]); - PROTECT(t, properties); - - object method = resolveMethod - (t, t->m->loader, "java/util/Properties", "setProperty", - "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); - - if (UNLIKELY(t->exception)) { - return; - } - - PROTECT(t, method); - - setProperty(t, method, properties, "java.version", "1.5"); - setProperty(t, method, properties, "java.specification.version", "1.5"); - - setProperty(t, method, properties, "java.vm.name", "Avian"); - - setProperty(t, method, properties, "java.protocol.handler.pkgs", "avian"); - - setProperty(t, method, properties, "file.encoding", "ASCII"); - - // specify a bogus library path so we can do our own search in - // VMRuntime.nativeLoad: -#define LIBRARY_PATH_SENTINAL "*" - setProperty(t, method, properties, "java.library.path", - LIBRARY_PATH_SENTINAL); - -#ifdef PLATFORM_WINDOWS -# define FILE_SEPARATOR "\\" - - setProperty(t, method, properties, "line.separator", "\r\n"); - setProperty(t, method, properties, "file.separator", FILE_SEPARATOR); - setProperty(t, method, properties, "path.separator", ";"); - setProperty(t, method, properties, "os.name", "Windows"); - - TCHAR buffer[MAX_PATH]; - GetTempPath(MAX_PATH, buffer); - setProperty(t, method, properties, "java.io.tmpdir", buffer); - setProperty(t, method, properties, "java.home", buffer); - - setProperty(t, method, properties, "user.home", - _wgetenv(L"USERPROFILE"), "%ls"); - - GetCurrentDirectory(MAX_PATH, buffer); - setProperty(t, method, properties, "user.dir", buffer); -#else -# define FILE_SEPARATOR "/" - - setProperty(t, method, properties, "line.separator", "\n"); - setProperty(t, method, properties, "file.separator", FILE_SEPARATOR); - setProperty(t, method, properties, "path.separator", ":"); -# ifdef __APPLE__ - setProperty(t, method, properties, "os.name", "Mac OS X"); -# else - setProperty(t, method, properties, "os.name", "Linux"); -# endif - setProperty(t, method, properties, "java.io.tmpdir", "/tmp"); - setProperty(t, method, properties, "java.home", "/tmp"); - setProperty(t, method, properties, "user.home", getenv("HOME")); - setProperty(t, method, properties, "user.dir", getenv("PWD")); -#endif - -#ifdef ARCH_x86_32 - setProperty(t, method, properties, "gnu.cpu.endian", "little"); - setProperty(t, method, properties, "os.arch", "x86"); -#elif defined ARCH_x86_64 - setProperty(t, method, properties, "gnu.cpu.endian", "little"); - setProperty(t, method, properties, "os.arch", "x86_64"); -#elif defined ARCH_powerpc - setProperty(t, method, properties, "gnu.cpu.endian", "big"); - setProperty(t, method, properties, "os.arch", "ppc"); -#elif defined ARCH_arm - setProperty(t, method, properties, "os.arch", "arm"); -#else - setProperty(t, method, properties, "os.arch", "unknown"); -#endif -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_gnu_classpath_VMStackWalker_getClassContext -(Thread* t, object, uintptr_t*) -{ - class Visitor: public Processor::StackVisitor { - public: - Visitor(Thread* t): - t(t), skipCount(1), trace(0), index(0), protector(t, &trace) - { } - - virtual bool visit(Processor::StackWalker* walker) { - if (skipCount == 0) { - if (trace == 0) { - trace = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType), - walker->count()); - } - - assert(t, index < objectArrayLength(t, trace)); - - set(t, trace, ArrayBody + (index * BytesPerWord), - methodClass(t, walker->method())); - - ++ index; - return true; - } else { - -- skipCount; - return true; - } - } - - Thread* t; - unsigned skipCount; - object trace; - unsigned index; - Thread::SingleProtector protector; - } v(t); - - t->m->processor->walkStack(t, &v); - - if (v.trace == 0) { - v.trace = makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::ClassType), 0); - } - - return reinterpret_cast(v.trace); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_gnu_classpath_VMStackWalker_getClassLoader -(Thread* t, object, uintptr_t* arguments) -{ - return reinterpret_cast - (classLoader(t, reinterpret_cast(arguments[0]))); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMRuntime_mapLibraryName -(Thread* t, object, uintptr_t* arguments) -{ - object name = reinterpret_cast(arguments[0]); - PROTECT(t, name); - - const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1; - const unsigned nameLength = stringLength(t, name); - const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1; - const unsigned total = soPrefixLength + nameLength + soSuffixLength; - - object s = makeByteArray(t, total + 1); - char* p = reinterpret_cast(&byteArrayBody(t, s, 0)); - - memcpy(p, SO_PREFIX, soPrefixLength); - stringChars(t, name, p + soPrefixLength); - memcpy(p + soPrefixLength + nameLength, SO_SUFFIX, soSuffixLength); - p[total] = 0; - - return reinterpret_cast(makeString(t, s, 0, total, 0)); -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_System_arraycopy -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_VMSystem_arraycopy -(Thread* t, object, uintptr_t* arguments) -{ - Avian_java_lang_System_arraycopy(t, 0, arguments); -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_Runtime_load -(Thread* t, object, uintptr_t*); - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMRuntime_nativeLoad -(Thread* t, object, uintptr_t* arguments) -{ - object name = reinterpret_cast(arguments[0]); - - // given that we set java.library.path to LIBRARY_PATH_SENTINAL, we - // can determine which names are filenames and which are library - // names by looking for the prefix LIBRARY_PATH_SENTINAL - // FILE_SEPARATOR - - unsigned length = stringLength(t, name); - char n[length + 1]; - stringChars(t, name, n); - - const unsigned pathPrefixLength - = sizeof(LIBRARY_PATH_SENTINAL) - 1 - + sizeof(FILE_SEPARATOR) - 1; - - bool mapName = (strncmp(n, LIBRARY_PATH_SENTINAL FILE_SEPARATOR, - pathPrefixLength) == 0); - if (mapName) { - // strip the path prefix, SO prefix, and SO suffix before passing - // the name to Runtime.load - - const unsigned soPrefixLength = sizeof(SO_PREFIX) - 1; - const unsigned soSuffixLength = sizeof(SO_SUFFIX) - 1; - const unsigned newOffset - = stringOffset(t, name) + pathPrefixLength + soPrefixLength; - const unsigned newLength - = length - pathPrefixLength - soPrefixLength - soSuffixLength; - - name = makeString(t, stringData(t, name), newOffset, newLength, 0); - } - - uintptr_t args[] = { reinterpret_cast(name), mapName }; - - Avian_java_lang_Runtime_load(t, 0, args); - - if (t->exception) { - t->exception = 0; - return 0; - } else { - return 1; - } -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Class_primitiveClass -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMClassLoader_getPrimitiveClass -(Thread* t, object, uintptr_t* arguments) -{ - return Avian_java_lang_Class_primitiveClass(t, 0, arguments); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_defineClass -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMClassLoader_defineClass -(Thread* t, object, uintptr_t* arguments) -{ - uintptr_t args[] - = { arguments[0], arguments[2], arguments[3], arguments[4] }; - -// object name = reinterpret_cast(arguments[1]); -// char n[stringLength(t, name) + 1]; -// stringChars(t, name, n); -// fprintf(stderr, "define class %s in %p\n", n, -// reinterpret_cast(arguments[0])); - - return Avian_avian_SystemClassLoader_defineClass(t, 0, args); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_System_identityHashCode -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMSystem_identityHashCode -(Thread* t, object, uintptr_t* arguments) -{ - return Avian_java_lang_System_identityHashCode(t, 0, arguments); -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_Runtime_gc -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_VMRuntime_gc -(Thread* t, object, uintptr_t*) -{ - Avian_java_lang_Runtime_gc(t, 0, 0); -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_VMRuntime_runFinalizationForExit -(Thread*, object, uintptr_t*) -{ - // ignore -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_VMRuntime_exit -(Thread*, object, uintptr_t* arguments) -{ - exit(arguments[0]); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_findClass -(Thread*, object, uintptr_t*); - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMClassLoader_loadClass -(Thread* t, object, uintptr_t* arguments) -{ - uintptr_t args[] = { 0, arguments[0] }; - - // object name = reinterpret_cast(arguments[0]); - // char n[stringLength(t, name) + 1]; - // stringChars(t, name, n); - // fprintf(stderr, "load bootstrap class %s in %p\n", n, t->m->loader); - - int64_t result = Avian_avian_SystemClassLoader_findClass(t, 0, args); - - // fprintf(stderr, "result %p\n", reinterpret_cast(result)); - - return result; -} - -extern "C" JNIEXPORT void JNICALL -Avian_java_lang_VMClassLoader_resolveClass -(Thread*, object, uintptr_t*) -{ - // ignore -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_VMClassLoader_findLoadedClass -(Thread* t, object, uintptr_t* arguments) -{ - object loader = reinterpret_cast(arguments[0]); - - object map = getClassLoaderMap(t, loader); - if (map) { - PROTECT(t, loader); - - object name = reinterpret_cast(arguments[1]); - PROTECT(t, name); - - object n = makeByteArray(t, stringLength(t, name) + 1); - char* s = reinterpret_cast(&byteArrayBody(t, n, 0)); - stringChars(t, name, s); - - replace('.', '/', s); - - return reinterpret_cast - (hashMapFind - (t, getClassLoaderMap(t, loader), n, byteArrayHash, byteArrayEqual)); - } else { - return 0; - } -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_compareAndSwapInt -(Thread*, object, uintptr_t* arguments) -{ - object target = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - int32_t expect = arguments[4]; - int32_t update = arguments[5]; - - return __sync_bool_compare_and_swap - (&cast(target, offset), expect, update); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_compareAndSwapLong -(Thread*, object, uintptr_t* arguments) -{ - object target = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - int64_t expect; memcpy(&expect, arguments + 4, 8); - int64_t update; memcpy(&update, arguments + 6, 8); - - return __sync_bool_compare_and_swap - (&cast(target, offset), expect, update); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_objectFieldOffset -(Thread* t, object, uintptr_t* arguments) -{ - return fieldOffset(t, reinterpret_cast(arguments[1])); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8 -(Thread*, object, uintptr_t*) -{ - return 0; -} diff --git a/src/heapdump.cpp b/src/heapdump.cpp index 41730b0fb6..100a3c7b3d 100644 --- a/src/heapdump.cpp +++ b/src/heapdump.cpp @@ -76,8 +76,7 @@ dumpHeap(Thread* t, FILE* out) local::write1(out, local::Size); local::write4(out, local::objectSize(t, p)); - if (objectClass(t, p) == arrayBody(t, t->m->types, Machine::ClassType)) - { + if (objectClass(t, p) == type(t, Machine::ClassType)) { object name = className(t, p); if (name) { local::write1(out, local::ClassName); diff --git a/src/interpret.cpp b/src/interpret.cpp index 7d362c27d9..a228d6f696 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -429,80 +429,17 @@ class MyStackWalker: public Processor::StackWalker { int frame; }; -object -makeNativeMethodData(Thread* t, object method, void* function) -{ - PROTECT(t, method); - - unsigned count = methodParameterCount(t, method) + 2; - - object data = makeNativeMethodData(t, - function, - 0, // argument table size - count); - - unsigned argumentTableSize = BytesPerWord * 2; - unsigned index = 0; - - nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; - nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE; - - const char* s = reinterpret_cast - (&byteArrayBody(t, methodSpec(t, method), 0)); - ++ s; // skip '(' - while (*s and *s != ')') { - unsigned code = fieldCode(t, *s); - nativeMethodDataParameterTypes(t, data, index++) = fieldType(t, code); - - switch (*s) { - case 'L': - argumentTableSize += BytesPerWord; - while (*s and *s != ';') ++ s; - ++ s; - break; - - case '[': - argumentTableSize += BytesPerWord; - while (*s == '[') ++ s; - switch (*s) { - case 'L': - while (*s and *s != ';') ++ s; - ++ s; - break; - - default: - ++ s; - break; - } - break; - - default: - argumentTableSize += pad(primitiveSize(t, code)); - ++ s; - break; - } - } - - nativeMethodDataArgumentTableSize(t, data) = argumentTableSize; - - return data; -} - inline void -resolveNativeMethodData(Thread* t, object method) +resolveNative(Thread* t, object method) { if (methodCode(t, method) == 0) { - void* p = resolveNativeMethod(t, method); - if (LIKELY(p)) { - PROTECT(t, method); - object data = makeNativeMethodData(t, method, p); - - // ensure other threads see updated methodVmFlags before - // methodCode, and that the native method data is initialized - // before it is visible to those threads: + object native = resolveNativeMethod(t, method); + if (LIKELY(native)) { + // ensure other threads only see the methodCode field populated + // once the object it points do has been populated: storeStoreMemoryBarrier(); - set(t, method, MethodCode, data); + set(t, method, MethodCode, native); } else { object message = makeString (t, "%s.%s%s", @@ -600,27 +537,35 @@ pushResult(Thread* t, unsigned returnCode, uint64_t result, bool indirect) } void -marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count, - object data, bool indirect) +marshalArguments(Thread* t, uintptr_t* args, uint8_t* types, unsigned sp, + object method, bool indirect) { - unsigned offset = 0; - unsigned sp = frameBase(t, t->frame); - for (; i < count; ++i) { - unsigned type = nativeMethodDataParameterTypes(t, data, i + 1); + MethodSpecIterator it + (t, reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0))); + + unsigned argOffset = 0; + unsigned typeOffset = 0; + + while (it.hasNext()) { + unsigned type = fieldType(t, fieldCode(t, *it.next())); + if (types) { + types[typeOffset++] = type; + } switch (type) { case INT8_TYPE: case INT16_TYPE: case INT32_TYPE: case FLOAT_TYPE: - args[offset++] = peekInt(t, sp++); + args[argOffset++] = peekInt(t, sp++); break; case DOUBLE_TYPE: case INT64_TYPE: { uint64_t v = peekLong(t, sp); - memcpy(args + offset, &v, 8); - offset += (8 / BytesPerWord); + memcpy(args + argOffset, &v, 8); + argOffset += (8 / BytesPerWord); sp += 2; } break; @@ -630,9 +575,9 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count, if (*v == 0) { v = 0; } - args[offset++] = reinterpret_cast(v); + args[argOffset++] = reinterpret_cast(v); } else { - args[offset++] = reinterpret_cast(peekObject(t, sp++)); + args[argOffset++] = reinterpret_cast(peekObject(t, sp++)); } } break; @@ -642,39 +587,51 @@ marshalArguments(Thread* t, uintptr_t* args, unsigned i, unsigned count, } unsigned -invokeNativeSlow(Thread* t, object method) +invokeNativeSlow(Thread* t, object method, void* function) { PROTECT(t, method); - object data = methodCode(t, method); - PROTECT(t, data); - pushFrame(t, method); - unsigned count = nativeMethodDataLength(t, data) - 1; - - unsigned size = nativeMethodDataArgumentTableSize(t, data); - uintptr_t args[size / BytesPerWord]; - unsigned offset = 0; - - args[offset++] = reinterpret_cast(t); - - unsigned i = 0; + unsigned footprint = methodParameterFootprint(t, method) + 1; if (methodFlags(t, method) & ACC_STATIC) { - ++ i; - args[offset++] = reinterpret_cast - (pushReference(t, methodClass(t, method))); + ++ footprint; } + unsigned count = methodParameterCount(t, method) + 2; - marshalArguments(t, args + offset, i, count, data, true); + RUNTIME_ARRAY(uintptr_t, args, footprint); + unsigned argOffset = 0; + RUNTIME_ARRAY(uint8_t, types, count); + unsigned typeOffset = 0; + + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(t); + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + object jclass = 0; + PROTECT(t, jclass); + + unsigned sp; + if (methodFlags(t, method) & ACC_STATIC) { + sp = frameBase(t, t->frame); + jclass = getJClass(t, methodClass(t, method)); + RUNTIME_ARRAY_BODY(args)[argOffset++] + = reinterpret_cast(&jclass); + } else { + sp = frameBase(t, t->frame); + object* v = reinterpret_cast(t->stack + ((sp++) * 2) + 1); + if (*v == 0) { + v = 0; + } + RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(v); + } + RUNTIME_ARRAY_BODY(types)[typeOffset++] = POINTER_TYPE; + + marshalArguments + (t, RUNTIME_ARRAY_BODY(args) + argOffset, + RUNTIME_ARRAY_BODY(types) + typeOffset, sp, method, true); unsigned returnCode = methodReturnCode(t, method); unsigned returnType = fieldType(t, returnCode); - void* function = nativeMethodDataFunction(t, data); - uint8_t types[nativeMethodDataLength(t, data)]; - memcpy(&types, - &nativeMethodDataParameterTypes(t, data, 0), - nativeMethodDataLength(t, data)); uint64_t result; if (DebugRun) { @@ -682,25 +639,15 @@ invokeNativeSlow(Thread* t, object method) &byteArrayBody(t, className(t, methodClass(t, method)), 0), &byteArrayBody(t, methodName(t, method), 0)); } - - // if (strcmp(reinterpret_cast - // (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), - // "org/eclipse/swt/internal/C") == 0 - // and strcmp(reinterpret_cast - // (&byteArrayBody(t, methodName(t, method), 0)), - // "memmove") == 0) - // { - // asm("int3"); - // } - + { ENTER(t, Thread::IdleState); result = t->m->system->call (function, - args, - types, - count + 1, - size, + RUNTIME_ARRAY_BODY(args), + RUNTIME_ARRAY_BODY(types), + count, + footprint * BytesPerWord, returnType); } @@ -728,24 +675,32 @@ invokeNative(Thread* t, object method) { PROTECT(t, method); - resolveNativeMethodData(t, method); + resolveNative(t, method); if (UNLIKELY(t->exception)) { return VoidField; } - if (methodVmFlags(t, method) & FastNative) { + object native = methodCode(t, method); + if (nativeFast(t, native)) { pushFrame(t, method); - object data = methodCode(t, method); - uintptr_t arguments[methodParameterFootprint(t, method)]; + unsigned footprint = methodParameterFootprint(t, method) + 1; + RUNTIME_ARRAY(uintptr_t, args, footprint); + unsigned sp = frameBase(t, t->frame); + unsigned argOffset = 0; + if (methodFlags(t, method) & ACC_STATIC) { + ++ footprint; + } else { + RUNTIME_ARRAY_BODY(args)[argOffset++] + = reinterpret_cast(peekObject(t, sp++)); + } + marshalArguments - (t, arguments, (methodFlags(t, method) & ACC_STATIC) ? 1 : 0, - nativeMethodDataLength(t, data) - 1, data, false); + (t, RUNTIME_ARRAY_BODY(args) + argOffset, 0, sp, method, false); uint64_t result = reinterpret_cast - (nativeMethodDataFunction(t, methodCode(t, method))) - (t, method, arguments); + (nativeFunction(t, native))(t, method, RUNTIME_ARRAY_BODY(args)); popFrame(t); @@ -757,7 +712,7 @@ invokeNative(Thread* t, object method) return methodReturnCode(t, method); } else { - return invokeNativeSlow(t, method); + return invokeNativeSlow(t, method, nativeFunction(t, native)); } } @@ -1004,9 +959,7 @@ interpret(Thread* t) object class_ = resolveClassInPool(t, frameMethod(t, frame), index - 1); if (UNLIKELY(exception)) goto throw_; - pushObject(t, makeObjectArray - (t, classLoader(t, methodClass(t, frameMethod(t, frame))), - class_, count)); + pushObject(t, makeObjectArray(t, class_, count)); } else { object message = makeString(t, "%d", count); exception = t->m->classpath->makeThrowable @@ -1070,9 +1023,7 @@ interpret(Thread* t) object array = popObject(t); if (LIKELY(array)) { - if (objectClass(t, array) - == arrayBody(t, t->m->types, Machine::BooleanArrayType)) - { + if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) { if (LIKELY(index >= 0 and static_cast(index) < booleanArrayLength(t, array))) @@ -1113,9 +1064,7 @@ interpret(Thread* t) object array = popObject(t); if (LIKELY(array)) { - if (objectClass(t, array) - == arrayBody(t, t->m->types, Machine::BooleanArrayType)) - { + if (objectClass(t, array) == type(t, Machine::BooleanArrayType)) { if (LIKELY(index >= 0 and static_cast(index) < booleanArrayLength(t, array))) @@ -2259,17 +2208,13 @@ interpret(Thread* t) if (singletonIsObject(t, pool, index - 1)) { object v = singletonObject(t, pool, index - 1); - if (objectClass(t, v) - == arrayBody(t, t->m->types, Machine::ReferenceType)) - { + 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) - == arrayBody(t, t->m->types, Machine::ClassType)) - { + } else if (objectClass(t, v) == type(t, Machine::ClassType)) { pushObject(t, getJClass(t, v)); } else { pushObject(t, v); @@ -3031,7 +2976,7 @@ invoke(Thread* t, object method) class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint)); if (classVmFlags(t, class_) & BootstrapFlag) { - resolveClass(t, t->m->loader, className(t, class_)); + resolveClass(t, root(t, Machine::BootLoader), className(t, class_)); } if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) { @@ -3333,7 +3278,7 @@ class MyProcessor: public Processor { abort(s); } - virtual void visitRoots(HeapWalker*) { + virtual void visitRoots(vm::Thread*, HeapWalker*) { abort(s); } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 02c7af652e..ed36e9451d 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -176,9 +176,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy) } object data = stringData(t, *s); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { return GetStringChars(t, s, isCopy); } else { return &charArrayBody(t, data, stringOffset(t, *s)); @@ -188,9 +186,7 @@ GetStringCritical(Thread* t, jstring s, jboolean* isCopy) void JNICALL ReleaseStringCritical(Thread* t, jstring s, const jchar* chars) { - if (objectClass(t, stringData(t, *s)) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, stringData(t, *s)) == type(t, Machine::ByteArrayType)) { ReleaseStringChars(t, s, chars); } @@ -294,7 +290,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer, ENTER(t, Thread::ActiveState); object c = defineClass - (t, loader ? *loader : t->m->loader, + (t, loader ? *loader : root(t, Machine::BootLoader), reinterpret_cast(buffer), length); return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c)); @@ -308,7 +304,7 @@ FindClass(Thread* t, const char* name) object n = makeByteArray(t, strlen(name) + 1); replace('.', '/', name, &byteArrayBody(t, n, 0)); - object c = resolveClass(t, t->m->loader, n); + object c = resolveClass(t, root(t, Machine::AppLoader), n); return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c)); } @@ -430,8 +426,9 @@ methodID(Thread* t, object method) ACQUIRE(t, t->m->referenceLock); if (methodNativeID(t, method) == 0) { - t->m->jniMethodTable = vectorAppend(t, t->m->jniMethodTable, method); - methodNativeID(t, method) = vectorSize(t, t->m->jniMethodTable); + setRoot(t, Machine::JNIMethodTable, vectorAppend + (t, root(t, Machine::JNIMethodTable), method)); + methodNativeID(t, method) = vectorSize(t, root(t, Machine::JNIMethodTable)); } } @@ -470,7 +467,7 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) inline object getMethod(Thread* t, jmethodID m) { - object method = vectorBody(t, t->m->jniMethodTable, m - 1); + object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1); assert(t, (methodFlags(t, method) & ACC_STATIC) == 0); @@ -733,7 +730,7 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...) inline object getStaticMethod(Thread* t, jmethodID m) { - object method = vectorBody(t, t->m->jniMethodTable, m - 1); + object method = vectorBody(t, root(t, Machine::JNIMethodTable), m - 1); assert(t, methodFlags(t, method) & ACC_STATIC); @@ -1342,9 +1339,7 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) { ENTER(t, Thread::ActiveState); - object a = makeObjectArray - (t, classLoader(t, jclassVmClass(t, *class_)), jclassVmClass(t, *class_), - length); + 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); @@ -1934,7 +1929,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, object method = findMethod(t, c, methods[i].name, methods[i].signature); if (UNLIKELY(t->exception)) return -1; - t->m->processor->registerNative(t, method, methods[i].function); + registerNative(t, method, methods[i].function); } } @@ -1946,7 +1941,7 @@ UnregisterNatives(Thread* t, jclass c) { ENTER(t, Thread::ActiveState); - t->m->processor->unregisterNatives(t, *c); + unregisterNatives(t, *c); return 0; } @@ -2314,21 +2309,21 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) unsigned bcppl = strlen(bootClasspathPrepend); unsigned bcpl = strlen(bootClasspath); unsigned bcpal = strlen(bootClasspathAppend); - unsigned cpl = strlen(classpath); - - unsigned classpathBufferSize = bcppl + bcpl + bcpal + cpl + 4; - RUNTIME_ARRAY(char, classpathBuffer, classpathBufferSize); - char* classpathPointer = RUNTIME_ARRAY_BODY(classpathBuffer); + unsigned bootClasspathBufferSize = bcppl + bcpl + bcpal + 3; + RUNTIME_ARRAY(char, bootClasspathBuffer, bootClasspathBufferSize); + char* bootClasspathPointer = RUNTIME_ARRAY_BODY(bootClasspathBuffer); local::append - (&classpathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR); - local::append(&classpathPointer, bootClasspath, bcpl, PATH_SEPARATOR); - local::append(&classpathPointer, bootClasspathAppend, bcpal, PATH_SEPARATOR); - local::append(&classpathPointer, classpath, cpl, 0); + (&bootClasspathPointer, bootClasspathPrepend, bcppl, PATH_SEPARATOR); + local::append(&bootClasspathPointer, bootClasspath, bcpl, + bcpal ? PATH_SEPARATOR : 0); + local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0); System* s = makeSystem(crashDumpDirectory); Heap* h = makeHeap(s, heapLimit); - Finder* f = makeFinder(s, RUNTIME_ARRAY_BODY(classpathBuffer), bootLibrary); + Finder* bf = makeFinder + (s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary); + Finder* af = makeFinder(s, classpath, bootLibrary); Processor* p = makeProcessor(s, h, true); Classpath* c = makeClasspath(s, h); @@ -2342,15 +2337,9 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) } *m = new (h->allocate(sizeof(Machine))) - Machine(s, h, f, p, c, properties, propertyCount); + Machine(s, h, bf, af, p, c, properties, propertyCount); *t = p->makeThread(*m, 0, 0); - enter(*t, Thread::ActiveState); - - c->boot(*t); - - enter(*t, Thread::IdleState); - return 0; } diff --git a/src/machine.cpp b/src/machine.cpp index e1d2af8ec6..63ba9c60fa 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -167,25 +167,29 @@ turnOffTheLights(Thread* t) enter(t, Thread::ExitState); - for (object* p = &(t->m->finalizers); *p;) { - object f = *p; - *p = finalizerNext(t, *p); + { object p = 0; + PROTECT(t, p); - void (*function)(Thread*, object); - memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); - if (function) { - function(t, finalizerTarget(t, f)); + for (p = t->m->finalizers; p;) { + object f = p; + p = finalizerNext(t, p); + + void (*function)(Thread*, object); + memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); + if (function) { + function(t, finalizerTarget(t, f)); + } } - } - for (object* p = &(t->m->tenuredFinalizers); *p;) { - object f = *p; - *p = finalizerNext(t, *p); + for (p = t->m->tenuredFinalizers; p;) { + object f = p; + p = finalizerNext(t, p); - void (*function)(Thread*, object); - memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); - if (function) { - function(t, finalizerTarget(t, f)); + void (*function)(Thread*, object); + memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); + if (function) { + function(t, finalizerTarget(t, f)); + } } } @@ -197,14 +201,16 @@ turnOffTheLights(Thread* t) Heap* h = m->heap; Processor* p = m->processor; Classpath* c = m->classpath; - Finder* f = m->finder; + Finder* bf = m->bootFinder; + Finder* af = m->appFinder; m->dispose(); h->disposeFixies(); c->dispose(); p->dispose(); h->dispose(); - f->dispose(); + bf->dispose(); + af->dispose(); s->dispose(); } @@ -554,10 +560,10 @@ postCollect(Thread* t) t->heapOffset = 0; t->heapIndex = 0; - if (t->useBackupHeap) { + if (t->flags & Thread::UseBackupHeapFlag) { memset(t->backupHeap, 0, ThreadBackupHeapSizeInBytes); - t->useBackupHeap = false; + t->flags &= ~Thread::UseBackupHeapFlag; t->backupHeapIndex = 0; } @@ -711,7 +717,8 @@ parseUtf8(Thread* t, Stream& s, unsigned length) void removeByteArray(Thread* t, object o) { - hashMapRemove(t, t->m->byteArrayMap, o, byteArrayHash, objectEqual); + hashMapRemove + (t, root(t, Machine::ByteArrayMap), o, byteArrayHash, objectEqual); } object @@ -720,11 +727,11 @@ internByteArray(Thread* t, object array) PROTECT(t, array); object n = hashMapFindNode - (t, t->m->byteArrayMap, array, byteArrayHash, byteArrayEqual); + (t, root(t, Machine::ByteArrayMap), array, byteArrayHash, byteArrayEqual); if (n) { return jreferenceTarget(t, tripleFirst(t, n)); } else { - hashMapInsert(t, t->m->byteArrayMap, array, 0, byteArrayHash); + hashMapInsert(t, root(t, Machine::ByteArrayMap), array, 0, byteArrayHash); addFinalizer(t, array, removeByteArray); return array; } @@ -752,9 +759,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) case CONSTANT_Utf8: { if (singletonObject(t, pool, i) == 0) { object value = parseUtf8(t, s, s.read2()); - if (objectClass(t, value) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, value) == type(t, Machine::ByteArrayType)) { value = internByteArray(t, value); } set(t, pool, SingletonBody + (i * BytesPerWord), value); @@ -1698,8 +1703,19 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, object elementClass) { // todo: arrays should implement Cloneable and Serializable - object vtable = classVirtualTable - (t, arrayBody(t, t->m->types, Machine::JobjectType)); + + if (classVmFlags(t, type(t, Machine::JobjectType)) & BootstrapFlag) { + PROTECT(t, spec); + PROTECT(t, elementClass); + + resolveSystemClass + (t, root(t, Machine::BootLoader), + className(t, type(t, Machine::JobjectType))); + + if (UNLIKELY(t->exception)) return 0; + } + + object vtable = classVirtualTable(t, type(t, Machine::JobjectType)); object c = t->m->processor->makeClass (t, @@ -1708,10 +1724,10 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, 2 * BytesPerWord, BytesPerWord, dimensions, - classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)), + classObjectMask(t, type(t, Machine::ArrayType)), spec, 0, - arrayBody(t, t->m->types, Machine::JobjectType), + type(t, Machine::JobjectType), 0, vtable, 0, @@ -1727,7 +1743,7 @@ makeArrayClass(Thread* t, object loader, unsigned dimensions, object spec, } object -makeArrayClass(Thread* t, object loader, object spec) +makeArrayClass(Thread* t, object loader, object spec, bool throw_) { PROTECT(t, loader); PROTECT(t, spec); @@ -1765,30 +1781,31 @@ makeArrayClass(Thread* t, object loader, object spec) } object elementClass = hashMapFind - (t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual); + (t, root(t, Machine::BootstrapClassMap), elementSpec, byteArrayHash, + byteArrayEqual); if (elementClass == 0) { - elementClass = resolveClass(t, loader, elementSpec); - if (UNLIKELY(t->exception)) return 0; + elementClass = resolveClass(t, loader, elementSpec, throw_); + if (elementClass == 0) return 0; } return makeArrayClass(t, loader, dimensions, spec, elementClass); } object -resolveArrayClass(Thread* t, object loader, object spec) +resolveArrayClass(Thread* t, object loader, object spec, bool throw_) { object c = hashMapFind - (t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual); + (t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash, + byteArrayEqual); if (c) { set(t, c, ClassVirtualTable, - classVirtualTable - (t, arrayBody(t, t->m->types, Machine::JobjectType))); + classVirtualTable(t, type(t, Machine::JobjectType))); return c; } else { - return makeArrayClass(t, loader, spec); + return makeArrayClass(t, loader, spec, throw_); } } @@ -1803,7 +1820,8 @@ removeMonitor(Thread* t, object o) hash = objectHash(t, o); } - object m = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual); + object m = hashMapRemove + (t, root(t, Machine::MonitorMap), o, objectHash, objectEqual); expect(t, m); @@ -1815,14 +1833,15 @@ removeMonitor(Thread* t, object o) void removeString(Thread* t, object o) { - hashMapRemove(t, t->m->stringMap, o, stringHash, objectEqual); + hashMapRemove(t, root(t, Machine::StringMap), o, stringHash, objectEqual); } void bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, unsigned fixedSize, unsigned arrayElementSize, unsigned vtableLength) { - object super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0); + object super = (superType >= 0 + ? vm::type(t, static_cast(superType)) : 0); object mask; if (objectMask) { @@ -1831,7 +1850,8 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, and intArrayBody(t, classObjectMask(t, super), 0) == static_cast(objectMask)) { - mask = classObjectMask(t, arrayBody(t, t->m->types, superType)); + mask = classObjectMask + (t, vm::type(t, static_cast(superType))); } else { mask = makeIntArray(t, 1); intArrayBody(t, mask, 0) = objectMask; @@ -1840,14 +1860,15 @@ bootClass(Thread* t, Machine::Type type, int superType, uint32_t objectMask, mask = 0; } - super = (superType >= 0 ? arrayBody(t, t->m->types, superType) : 0); + super = (superType >= 0 + ? vm::type(t, static_cast(superType)) : 0); object class_ = t->m->processor->makeClass (t, 0, BootstrapFlag, fixedSize, arrayElementSize, arrayElementSize ? 1 : 0, mask, 0, 0, super, 0, 0, 0, 0, 0, 0, - t->m->loader, vtableLength); + root(t, Machine::BootLoader), vtableLength); - set(t, t->m->types, ArrayBody + (type * BytesPerWord), class_); + setType(t, type, class_); } void @@ -1857,7 +1878,7 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name, PROTECT(t, bootMethod); object n = makeByteArray(t, name); - object class_ = arrayBody(t, t->m->types, type); + object class_ = vm::type(t, type); set(t, class_, ClassName, n); @@ -1870,14 +1891,16 @@ bootJavaClass(Thread* t, Machine::Type type, int superType, const char* name, arrayBody(t, vtable, i) = bootMethod; } } else { - vtable = classVirtualTable(t, arrayBody(t, t->m->types, superType)); + vtable = classVirtualTable + (t, vm::type(t, static_cast(superType))); } set(t, class_, ClassVirtualTable, vtable); t->m->processor->initVtable(t, class_); - hashMapInsert(t, t->m->bootstrapClassMap, n, class_, byteArrayHash); + hashMapInsert + (t, root(t, Machine::BootstrapClassMap), n, class_, byteArrayHash); } void @@ -1887,92 +1910,103 @@ boot(Thread* t) m->unsafe = true; - m->loader = allocate(t, FixedSizeOfSystemClassLoader, true); + m->roots = allocate(t, pad((Machine::RootCount + 2) * BytesPerWord), true); + arrayLength(t, m->roots) = Machine::RootCount; + + setRoot(t, Machine::BootLoader, + allocate(t, FixedSizeOfSystemClassLoader, true)); + + setRoot(t, Machine::AppLoader, + allocate(t, FixedSizeOfSystemClassLoader, true)); m->types = allocate(t, pad((TypeCount + 2) * BytesPerWord), true); arrayLength(t, m->types) = TypeCount; #include "type-initializations.cpp" - object arrayClass = arrayBody(t, m->types, Machine::ArrayType); + object arrayClass = type(t, Machine::ArrayType); set(t, m->types, 0, arrayClass); + set(t, m->roots, 0, arrayClass); - object loaderClass = arrayBody - (t, m->types, Machine::SystemClassLoaderType); - set(t, m->loader, 0, loaderClass); + object loaderClass = type(t, Machine::SystemClassLoaderType); + set(t, root(t, Machine::BootLoader), 0, loaderClass); + set(t, root(t, Machine::AppLoader), 0, loaderClass); -#ifdef AVIAN_GNU - classLoaderInitialized(t, m->loader) = true; -#endif + object objectClass = type(t, Machine::JobjectType); - object objectClass = arrayBody(t, m->types, Machine::JobjectType); - - object classClass = arrayBody(t, m->types, Machine::ClassType); + object classClass = type(t, Machine::ClassType); set(t, classClass, 0, classClass); set(t, classClass, ClassSuper, objectClass); - object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType); + object intArrayClass = type(t, Machine::IntArrayType); set(t, intArrayClass, 0, classClass); set(t, intArrayClass, ClassSuper, objectClass); m->unsafe = false; - classVmFlags(t, arrayBody(t, m->types, Machine::SingletonType)) + classVmFlags(t, type(t, Machine::SingletonType)) |= SingletonFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::ContinuationType)) + classVmFlags(t, type(t, Machine::ContinuationType)) |= ContinuationFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JreferenceType)) + classVmFlags(t, type(t, Machine::JreferenceType)) |= ReferenceFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType)) + classVmFlags(t, type(t, Machine::WeakReferenceType)) |= ReferenceFlag | WeakReferenceFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::SoftReferenceType)) + classVmFlags(t, type(t, Machine::SoftReferenceType)) |= ReferenceFlag | WeakReferenceFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::PhantomReferenceType)) + classVmFlags(t, type(t, Machine::PhantomReferenceType)) |= ReferenceFlag | WeakReferenceFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JbooleanType)) + classVmFlags(t, type(t, Machine::JbooleanType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JbyteType)) + classVmFlags(t, type(t, Machine::JbyteType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JcharType)) + classVmFlags(t, type(t, Machine::JcharType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JshortType)) + classVmFlags(t, type(t, Machine::JshortType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JintType)) + classVmFlags(t, type(t, Machine::JintType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JlongType)) + classVmFlags(t, type(t, Machine::JlongType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JfloatType)) + classVmFlags(t, type(t, Machine::JfloatType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JdoubleType)) + classVmFlags(t, type(t, Machine::JdoubleType)) |= PrimitiveFlag; - classVmFlags(t, arrayBody(t, m->types, Machine::JvoidType)) + classVmFlags(t, type(t, Machine::JvoidType)) |= PrimitiveFlag; - set(t, arrayBody(t, m->types, Machine::BooleanArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JbooleanType)); - set(t, arrayBody(t, m->types, Machine::ByteArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JbyteType)); - set(t, arrayBody(t, m->types, Machine::CharArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JcharType)); - set(t, arrayBody(t, m->types, Machine::ShortArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JshortType)); - set(t, arrayBody(t, m->types, Machine::IntArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JintType)); - set(t, arrayBody(t, m->types, Machine::LongArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JlongType)); - set(t, arrayBody(t, m->types, Machine::FloatArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JfloatType)); - set(t, arrayBody(t, m->types, Machine::DoubleArrayType), ClassStaticTable, - arrayBody(t, m->types, Machine::JdoubleType)); + set(t, type(t, Machine::BooleanArrayType), ClassStaticTable, + type(t, Machine::JbooleanType)); + set(t, type(t, Machine::ByteArrayType), ClassStaticTable, + type(t, Machine::JbyteType)); + set(t, type(t, Machine::CharArrayType), ClassStaticTable, + type(t, Machine::JcharType)); + set(t, type(t, Machine::ShortArrayType), ClassStaticTable, + type(t, Machine::JshortType)); + set(t, type(t, Machine::IntArrayType), ClassStaticTable, + type(t, Machine::JintType)); + set(t, type(t, Machine::LongArrayType), ClassStaticTable, + type(t, Machine::JlongType)); + set(t, type(t, Machine::FloatArrayType), ClassStaticTable, + type(t, Machine::JfloatType)); + set(t, type(t, Machine::DoubleArrayType), ClassStaticTable, + type(t, Machine::JdoubleType)); - m->classMap = makeHashMap(t, 0, 0); + setRoot(t, Machine::ClassMap, makeHashMap(t, 0, 0)); - m->bootstrapClassMap = makeHashMap(t, 0, 0); + { object map = makeHashMap(t, 0, 0); + set(t, root(t, Machine::AppLoader), ClassLoaderMap, map); + } - m->stringMap = makeWeakHashMap(t, 0, 0); + set(t, root(t, Machine::AppLoader), ClassLoaderParent, + root(t, Machine::BootLoader)); + + 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, 1); @@ -2074,15 +2108,16 @@ class HeapClient: public Heap::Client { namespace vm { -Machine::Machine(System* system, Heap* heap, Finder* finder, - Processor* processor, Classpath* classpath, +Machine::Machine(System* system, Heap* heap, Finder* bootFinder, + Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount): vtable(&javaVMVTable), system(system), heapClient(new (heap->allocate(sizeof(HeapClient))) HeapClient(this)), heap(heap), - finder(finder), + bootFinder(bootFinder), + appFinder(appFinder), processor(processor), classpath(classpath), rootThread(0), @@ -2102,24 +2137,13 @@ Machine::Machine(System* system, Heap* heap, Finder* finder, referenceLock(0), shutdownLock(0), libraries(0), - loader(0), - classMap(0), - loadClassMethod(0), - bootstrapClassMap(0), - monitorMap(0), - stringMap(0), - byteArrayMap(0), types(0), - jniMethodTable(0), + roots(0), finalizers(0), tenuredFinalizers(0), finalizeQueue(0), weakReferences(0), tenuredWeakReferences(0), - shutdownHooks(0), - objectsToFinalize(0), - nullPointerException(0), - arrayIndexOutOfBoundsException(0), unsafe(false), triedBuiltinOnLoad(false), heapPoolIndex(0) @@ -2194,13 +2218,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): (m->heap->allocate(ThreadHeapSizeInBytes))), heap(defaultHeap), backupHeapIndex(0), - useBackupHeap(false), - waiting(false), - tracing(false), - daemon(false) -#ifdef VM_STRESS - , stress(false) -#endif // VM_STRESS + flags(ActiveFlag) { } void @@ -2241,16 +2259,10 @@ Thread::init() boot(this); } - m->byteArrayMap = makeWeakHashMap(this, 0, 0); - m->monitorMap = makeWeakHashMap(this, 0, 0); + setRoot(this, Machine::ByteArrayMap, makeWeakHashMap(this, 0, 0)); + setRoot(this, Machine::MonitorMap, makeWeakHashMap(this, 0, 0)); - m->jniMethodTable = makeVector(this, 0, 0); - - m->nullPointerException = m->classpath->makeThrowable - (this, Machine::NullPointerExceptionType); - - m->arrayIndexOutOfBoundsException = m->classpath->makeThrowable - (this, Machine::IndexOutOfBoundsExceptionType); + setRoot(this, Machine::JNIMethodTable, makeVector(this, 0, 0)); m->localThread->set(this); } else { @@ -2265,6 +2277,21 @@ Thread::init() } threadPeer(this, javaThread) = reinterpret_cast(this); + + if (parent == 0) { + enter(this, Thread::ActiveState); + + m->classpath->boot(this); + + setRoot(this, Machine::NullPointerException, m->classpath->makeThrowable + (this, Machine::NullPointerExceptionType)); + + setRoot(this, Machine::ArrayIndexOutOfBoundsException, + m->classpath->makeThrowable + (this, Machine::IndexOutOfBoundsExceptionType)); + + enter(this, Thread::IdleState); + } } void @@ -2303,10 +2330,10 @@ shutDown(Thread* t) { ACQUIRE(t, t->m->shutdownLock); - object hooks = t->m->shutdownHooks; + object hooks = root(t, Machine::ShutdownHooks); PROTECT(t, hooks); - t->m->shutdownHooks = 0; + setRoot(t, Machine::ShutdownHooks, 0); object h = hooks; PROTECT(t, h); @@ -2364,7 +2391,6 @@ enter(Thread* t, Thread::State s) return; } - #ifdef USE_ATOMIC_OPERATIONS # define INCREMENT atomicIncrement # define ACQUIRE_LOCK ACQUIRE_RAW(t, t->m->stateLock) @@ -2411,12 +2437,24 @@ enter(Thread* t, Thread::State s) // The java.lang.Thread implementation may or may not notify the // VM when the daemon field in the Java object changes, so we sync // up the native field whenever the thread transitions to idle: - if (t->daemon != threadDaemon(t, t->javaThread)) { + + // todo: this won't always help if some other thread sets the + // daemon field. The thread trying to shut down the VM really + // just needs to count from scratch every time any thread makes a + // transition. + + if (UNLIKELY(((t->flags & Thread::DaemonFlag) != 0) + != threadDaemon(t, t->javaThread))) + { ACQUIRE_LOCK; - t->daemon = threadDaemon(t, t->javaThread); + if (threadDaemon(t, t->javaThread)) { + atomicOr(&(t->flags), Thread::DaemonFlag); + } else { + atomicAnd(&(t->flags), ~Thread::DaemonFlag); + } - if (t->daemon) { + if (t->flags & Thread::DaemonFlag) { ++ t->m->daemonCount; } else { expect(t, t->m->daemonCount); @@ -2426,7 +2464,7 @@ enter(Thread* t, Thread::State s) t->m->stateLock->notifyAll(t->systemThread); } - if (t->state == Thread::ActiveState) { + if (LIKELY(t->state == Thread::ActiveState)) { // fast path assert(t, t->m->activeCount > 0); INCREMENT(&(t->m->activeCount), -1); @@ -2475,7 +2513,7 @@ enter(Thread* t, Thread::State s) } break; case Thread::ActiveState: - if (t->state == Thread::IdleState and t->m->exclusive == 0) { + if (LIKELY(t->state == Thread::IdleState and t->m->exclusive == 0)) { // fast path INCREMENT(&(t->m->activeCount), 1); @@ -2563,7 +2601,7 @@ object allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, unsigned sizeInBytes, bool objectMask) { - if (UNLIKELY(t->useBackupHeap)) { + if (UNLIKELY(t->flags & Thread::UseBackupHeapFlag)) { expect(t, t->backupHeapIndex + ceiling(sizeInBytes, BytesPerWord) <= ThreadBackupHeapSizeInWords); @@ -2571,7 +2609,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, t->backupHeapIndex += ceiling(sizeInBytes, BytesPerWord); cast(o, 0) = 0; return o; - } else if (UNLIKELY(t->tracing)) { + } else if (UNLIKELY(t->flags & Thread::TracingFlag)) { expect(t, t->heapIndex + ceiling(sizeInBytes, BytesPerWord) <= ThreadHeapSizeInWords); return allocateSmall(t, sizeInBytes); @@ -2721,9 +2759,7 @@ stringUTFLength(Thread* t, object string, unsigned start, unsigned length) if (length) { object data = stringData(t, string); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { result = length; } else { for (unsigned i = 0; i < length; ++i) { @@ -2746,9 +2782,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length, { if (length) { object data = stringData(t, string); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { memcpy(chars, &byteArrayBody(t, data, stringOffset(t, string) + start), length); @@ -2767,9 +2801,7 @@ stringChars(Thread* t, object string, unsigned start, unsigned length, { if (length) { object data = stringData(t, string); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { for (unsigned i = 0; i < length; ++i) { chars[i] = byteArrayBody(t, data, stringOffset(t, string) + start + i); } @@ -2791,9 +2823,7 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length, if (length) { object data = stringData(t, string); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { memcpy(chars, &byteArrayBody(t, data, stringOffset(t, string) + start), length); @@ -2824,11 +2854,14 @@ stringUTFChars(Thread* t, object string, unsigned start, unsigned length, bool isAssignableFrom(Thread* t, object a, object b) { + assert(t, a); + assert(t, b); + if (a == b) return true; if (classFlags(t, a) & ACC_INTERFACE) { if (classVmFlags(t, b) & BootstrapFlag) { - resolveSystemClass(t, className(t, b)); + resolveSystemClass(t, root(t, Machine::BootLoader), className(t, b)); if (UNLIKELY(t->exception)) { t->exception = 0; return false; @@ -2966,15 +2999,6 @@ primitiveSize(Thread* t, unsigned code) } } -object -findLoadedSystemClass(Thread* t, object spec) -{ - PROTECT(t, spec); - ACQUIRE(t, t->m->classLock); - - return hashMapFind(t, t->m->classMap, spec, byteArrayHash, byteArrayEqual); -} - object parseClass(Thread* t, object loader, const uint8_t* data, unsigned size) { @@ -3084,18 +3108,27 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size) } object -resolveSystemClass(Thread* t, object spec) +resolveSystemClass(Thread* t, object loader, object spec, bool throw_) { + PROTECT(t, loader); PROTECT(t, spec); ACQUIRE(t, t->m->classLock); object class_ = hashMapFind - (t, t->m->classMap, spec, byteArrayHash, byteArrayEqual); + (t, getClassLoaderMap(t, loader), spec, byteArrayHash, byteArrayEqual); if (class_ == 0) { + if (classLoaderParent(t, loader)) { + class_ = resolveSystemClass + (t, classLoaderParent(t, loader), spec, false); + if (class_) { + return class_; + } + } + if (byteArrayBody(t, spec, 0) == '[') { - class_ = resolveArrayClass(t, t->m->loader, spec); + class_ = resolveArrayClass(t, loader, spec, throw_); } else { RUNTIME_ARRAY(char, file, byteArrayLength(t, spec) + 6); memcpy(RUNTIME_ARRAY_BODY(file), @@ -3105,7 +3138,8 @@ resolveSystemClass(Thread* t, object spec) ".class", 7); - System::Region* region = t->m->finder->find(RUNTIME_ARRAY_BODY(file)); + System::Region* region = getFinder(t, loader)->find + (RUNTIME_ARRAY_BODY(file)); if (region) { if (Verbose) { @@ -3113,8 +3147,7 @@ resolveSystemClass(Thread* t, object spec) } // parse class file - class_ = parseClass - (t, t->m->loader, region->start(), region->length()); + class_ = parseClass(t, loader, region->start(), region->length()); region->dispose(); if (LIKELY(t->exception == 0)) { @@ -3125,7 +3158,7 @@ resolveSystemClass(Thread* t, object spec) } object bootstrapClass = hashMapFind - (t, t->m->bootstrapClassMap, spec, byteArrayHash, + (t, root(t, Machine::BootstrapClassMap), spec, byteArrayHash, byteArrayEqual); if (bootstrapClass) { @@ -3141,8 +3174,9 @@ resolveSystemClass(Thread* t, object spec) if (class_) { PROTECT(t, class_); - hashMapInsert(t, t->m->classMap, spec, class_, byteArrayHash); - } else if (t->exception == 0) { + hashMapInsert + (t, getClassLoaderMap(t, loader), spec, class_, byteArrayHash); + } else if (throw_ and t->exception == 0) { object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); t->exception = t->m->classpath->makeThrowable (t, Machine::ClassNotFoundExceptionType, message); @@ -3153,10 +3187,26 @@ resolveSystemClass(Thread* t, object spec) } object -resolveClass(Thread* t, object loader, object spec) +findLoadedClass(Thread* t, object loader, object spec) { - if (loader == t->m->loader) { - return resolveSystemClass(t, spec); + PROTECT(t, spec); + ACQUIRE(t, t->m->classLock); + + object map = getClassLoaderMap(t, loader); + if (map) { + return hashMapFind(t, map, spec, byteArrayHash, byteArrayEqual); + } else { + return 0; + } +} + +object +resolveClass(Thread* t, object loader, object spec, bool throw_) +{ + if (loader == root(t, Machine::BootLoader) + or loader == root(t, Machine::AppLoader)) + { + return resolveSystemClass(t, loader, spec, throw_); } else { PROTECT(t, loader); PROTECT(t, spec); @@ -3173,39 +3223,44 @@ resolveClass(Thread* t, object loader, object spec) if (class_ == 0) { if (byteArrayBody(t, spec, 0) == '[') { - class_ = resolveArrayClass(t, loader, spec); + class_ = resolveArrayClass(t, loader, spec, throw_); } else { - if (t->m->loadClassMethod == 0) { + if (root(t, Machine::LoadClassMethod) == 0) { object m = resolveMethod - (t, t->m->loader, "java/lang/ClassLoader", "loadClass", - "(Ljava/lang/String;)Ljava/lang/Class;"); + (t, root(t, Machine::BootLoader), "java/lang/ClassLoader", + "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); if (m) { - t->m->loadClassMethod = m; + setRoot(t, Machine::LoadClassMethod, m); - object classLoaderClass = arrayBody - (t, t->m->types, Machine::ClassLoaderType); + object classLoaderClass = type(t, Machine::ClassLoaderType); if (classVmFlags(t, classLoaderClass) & BootstrapFlag) { - resolveSystemClass(t, vm::className(t, classLoaderClass)); + resolveSystemClass + (t, root(t, Machine::BootLoader), + vm::className(t, classLoaderClass)); } } } if (LIKELY(t->exception == 0)) { object method = findVirtualMethod - (t, t->m->loadClassMethod, objectClass(t, loader)); + (t, root(t, Machine::LoadClassMethod), objectClass(t, loader)); if (LIKELY(t->exception == 0)) { PROTECT(t, method); - object specString = makeString - (t, "%s", &byteArrayBody(t, spec, 0)); + RUNTIME_ARRAY(char, s, byteArrayLength(t, spec)); + replace('/', '.', RUNTIME_ARRAY_BODY(s), reinterpret_cast + (&byteArrayBody(t, spec, 0))); - replace('/', '.', reinterpret_cast - (&byteArrayBody(t, stringData(t, specString), 0))); + object specString = makeString(t, "%s", s); class_ = t->m->processor->invoke(t, method, loader, specString); + + if (LIKELY(class_ and t->exception == 0)) { + class_ = jclassVmClass(t, class_); + } } } } @@ -3216,7 +3271,7 @@ resolveClass(Thread* t, object loader, object spec) hashMapInsert(t, classLoaderMap(t, loader), spec, class_, byteArrayHash); - } else if (t->exception == 0) { + } else if (throw_ and t->exception == 0) { object message = makeString(t, "%s", &byteArrayBody(t, spec, 0)); t->exception = t->m->classpath->makeThrowable (t, Machine::ClassNotFoundExceptionType, message); @@ -3399,10 +3454,10 @@ initClass(Thread* t, object c) } object -makeObjectArray(Thread* t, object loader, object elementClass, unsigned count) +makeObjectArray(Thread* t, object elementClass, unsigned count) { object arrayClass = resolveObjectArrayClass - (t, loader, className(t, elementClass)); + (t, classLoader(t, elementClass), className(t, elementClass)); PROTECT(t, arrayClass); object array = makeArray(t, count); @@ -3524,7 +3579,8 @@ objectMonitor(Thread* t, object o, bool createNew) { assert(t, t->state == Thread::ActiveState); - object m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); + object m = hashMapFind + (t, root(t, Machine::MonitorMap), o, objectHash, objectEqual); if (m) { if (DebugMonitors) { @@ -3538,7 +3594,9 @@ objectMonitor(Thread* t, object o, bool createNew) { ENTER(t, Thread::ExclusiveState); - m = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual); + m = hashMapFind + (t, root(t, Machine::MonitorMap), o, objectHash, objectEqual); + if (m) { if (DebugMonitors) { fprintf(stderr, "found monitor %p for object %x\n", @@ -3556,7 +3614,7 @@ objectMonitor(Thread* t, object o, bool createNew) objectHash(t, o)); } - hashMapInsert(t, t->m->monitorMap, o, m, objectHash); + hashMapInsert(t, root(t, Machine::MonitorMap), o, m, objectHash); addFinalizer(t, o, removeMonitor); } @@ -3574,11 +3632,13 @@ intern(Thread* t, object s) ACQUIRE(t, t->m->referenceLock); - object n = hashMapFindNode(t, t->m->stringMap, s, stringHash, stringEqual); + object n = hashMapFindNode + (t, root(t, Machine::StringMap), s, stringHash, stringEqual); + if (n) { return jreferenceTarget(t, tripleFirst(t, n)); } else { - hashMapInsert(t, t->m->stringMap, s, 0, stringHash); + hashMapInsert(t, root(t, Machine::StringMap), s, 0, stringHash); addFinalizer(t, s, removeString); return s; } @@ -3615,20 +3675,20 @@ collect(Thread* t, Heap::CollectionType type) if (not stress) t->stress = false; #endif - object f = m->finalizeQueue; - m->finalizeQueue = 0; + 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 { - m->objectsToFinalize = makePair - (t, finalizerTarget(t, f), m->objectsToFinalize); + setRoot(t, Machine::ObjectsToFinalize, makePair + (t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize))); } } - if (m->objectsToFinalize and m->finalizeThread == 0) { + if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) { m->finalizeThread = m->processor->makeThread (m, t->m->classpath->makeThread(t, m->rootThread), m->rootThread); @@ -3702,19 +3762,8 @@ walkNext(Thread* t, object o, int previous) void visitRoots(Machine* m, Heap::Visitor* v) { - v->visit(&(m->loader)); - v->visit(&(m->classMap)); - v->visit(&(m->loadClassMethod)); - v->visit(&(m->bootstrapClassMap)); - v->visit(&(m->monitorMap)); - v->visit(&(m->stringMap)); - v->visit(&(m->byteArrayMap)); v->visit(&(m->types)); - v->visit(&(m->jniMethodTable)); - v->visit(&(m->shutdownHooks)); - v->visit(&(m->objectsToFinalize)); - v->visit(&(m->nullPointerException)); - v->visit(&(m->arrayIndexOutOfBoundsException)); + v->visit(&(m->roots)); for (Thread* t = m->rootThread; t; t = t->peer) { ::visitRoots(t, v); @@ -3751,8 +3800,8 @@ printTrace(Thread* t, object exception) } object trace = throwableTrace(t, e); - for (unsigned i = 0; i < arrayLength(t, trace); ++i) { - object e = arrayBody(t, trace, i); + for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) { + object e = objectArrayBody(t, trace, i); const int8_t* class_ = &byteArrayBody (t, className(t, methodClass(t, traceElementMethod(t, e))), 0); const int8_t* method = &byteArrayBody @@ -3789,11 +3838,11 @@ makeTrace(Thread* t, Processor::StackWalker* walker) virtual bool visit(Processor::StackWalker* walker) { if (trace == 0) { - trace = makeArray(t, walker->count()); + trace = makeObjectArray(t, walker->count()); } object e = makeTraceElement(t, walker->method(), walker->ip()); - vm_assert(t, index < arrayLength(t, trace)); + vm_assert(t, index < objectArrayLength(t, trace)); set(t, trace, ArrayBody + (index * BytesPerWord), e); ++ index; return true; @@ -3807,7 +3856,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker) walker->walk(&v); - return v.trace ? v.trace : makeArray(t, 0); + return v.trace ? v.trace : makeObjectArray(t, 0); } object @@ -3828,7 +3877,7 @@ makeTrace(Thread* t, Thread* target) t->m->processor->walkStack(target, &v); - return v.trace ? v.trace : makeArray(t, 0); + return v.trace ? v.trace : makeObjectArray(t, 0); } void @@ -3842,7 +3891,9 @@ runFinalizeThread(Thread* t) while (true) { { ACQUIRE(t, t->m->stateLock); - while (t->m->finalizeThread and t->m->objectsToFinalize == 0) { + while (t->m->finalizeThread + and root(t, Machine::ObjectsToFinalize) == 0) + { ENTER(t, Thread::IdleState); t->m->stateLock->wait(t->systemThread, 0); } @@ -3850,8 +3901,8 @@ runFinalizeThread(Thread* t) if (t->m->finalizeThread == 0) { return; } else { - list = t->m->objectsToFinalize; - t->m->objectsToFinalize = 0; + list = root(t, Machine::ObjectsToFinalize); + setRoot(t, Machine::ObjectsToFinalize, 0); } } @@ -3926,7 +3977,7 @@ vmPrintTrace(Thread* t) int line = t->m->processor->lineNumber (t, walker->method(), walker->ip()); - fprintf(stderr, " at %s.%s (%x) ", class_, method, walker->ip()); + fprintf(stderr, " at %s.%s ", class_, method); switch (line) { case NativeLine: diff --git a/src/machine.h b/src/machine.h index cc2394a757..ec2677109e 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1120,6 +1120,24 @@ struct JNIEnvVTable { #endif }; +inline void +atomicOr(uint32_t* p, int v) +{ + for (uint32_t old = *p; + not atomicCompareAndSwap32(p, old, old | v); + old = *p) + { } +} + +inline void +atomicAnd(uint32_t* p, int v) +{ + for (uint32_t old = *p; + not atomicCompareAndSwap32(p, old, old & v); + old = *p) + { } +} + inline int strcmp(const int8_t* a, const int8_t* b) { @@ -1164,8 +1182,26 @@ class Machine { ImmortalAllocation }; - Machine(System* system, Heap* heap, Finder* finder, Processor* processor, - Classpath* classpath, const char** properties, + enum Root { + BootLoader, + AppLoader, + ClassMap, + LoadClassMethod, + BootstrapClassMap, + MonitorMap, + StringMap, + ByteArrayMap, + JNIMethodTable, + ShutdownHooks, + ObjectsToFinalize, + NullPointerException, + ArrayIndexOutOfBoundsException + }; + + static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1; + + Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, + Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount); ~Machine() { @@ -1178,7 +1214,8 @@ class Machine { System* system; Heap::Client* heapClient; Heap* heap; - Finder* finder; + Finder* bootFinder; + Finder* appFinder; Processor* processor; Classpath* classpath; Thread* rootThread; @@ -1198,24 +1235,13 @@ class Machine { System::Monitor* referenceLock; System::Monitor* shutdownLock; System::Library* libraries; - object loader; - object classMap; - object loadClassMethod; - object bootstrapClassMap; - object monitorMap; - object stringMap; - object byteArrayMap; object types; - object jniMethodTable; + object roots; object finalizers; object tenuredFinalizers; object finalizeQueue; object weakReferences; object tenuredWeakReferences; - object shutdownHooks; - object objectsToFinalize; - object nullPointerException; - object arrayIndexOutOfBoundsException; bool unsafe; bool triedBuiltinOnLoad; JavaVMVTable javaVMVTable; @@ -1261,6 +1287,13 @@ class Thread { ExitState }; + static const unsigned UseBackupHeapFlag = 1 << 0; + static const unsigned WaitingFlag = 1 << 1; + static const unsigned TracingFlag = 1 << 2; + static const unsigned DaemonFlag = 1 << 3; + static const unsigned StressFlag = 1 << 4; + static const unsigned ActiveFlag = 1 << 5; + class Protector { public: Protector(Thread* t): t(t), next(t->protector) { @@ -1371,11 +1404,7 @@ class Thread { uintptr_t* heap; uintptr_t backupHeap[ThreadBackupHeapSizeInWords]; unsigned backupHeapIndex; - bool useBackupHeap; - bool waiting; - bool tracing; - bool daemon; - bool stress; + unsigned flags; }; class Classpath { @@ -1600,9 +1629,9 @@ ensure(Thread* t, unsigned sizeInBytes) > ThreadHeapSizeInWords) { if (sizeInBytes <= ThreadBackupHeapSizeInBytes) { - expect(t, not t->useBackupHeap); + expect(t, (t->flags & Thread::UseBackupHeapFlag) == 0); - t->useBackupHeap = true; + atomicOr(&(t->flags), Thread::UseBackupHeapFlag); return true; } else { @@ -1719,16 +1748,52 @@ instanceOf(Thread* t, object class_, object o); #include "type-declarations.cpp" +inline object& +root(Thread* t, Machine::Root root) +{ + return arrayBody(t, t->m->roots, root); +} + +inline void +setRoot(Thread* t, Machine::Root root, object value) +{ + set(t, t->m->roots, ArrayBody + (root * BytesPerWord), value); +} + +inline object +type(Thread* t, Machine::Type type) +{ + return arrayBody(t, t->m->types, type); +} + +inline void +setType(Thread* t, Machine::Type type, object value) +{ + set(t, t->m->types, ArrayBody + (type * BytesPerWord), value); +} + inline object getClassLoaderMap(Thread* t, object loader) { - if (loader == t->m->loader) { - return t->m->classMap; + if (loader == root(t, Machine::BootLoader)) { + return root(t, Machine::ClassMap); } else { return classLoaderMap(t, loader); } } +inline Finder* +getFinder(Thread* t, object loader) +{ + if (loader == root(t, Machine::BootLoader)) { + return t->m->bootFinder; + } else if (loader == root(t, Machine::AppLoader)) { + return t->m->appFinder; + } else { + abort(t); + } +} + inline bool objectFixed(Thread*, object o) { @@ -1927,9 +1992,7 @@ stringHash(Thread* t, object s) { if (stringHashCode(t, s) == 0 and stringLength(t, s)) { object data = stringData(t, s); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { stringHashCode(t, s) = hash (&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s)); } else { @@ -1944,9 +2007,7 @@ inline uint16_t stringCharAt(Thread* t, object s, int i) { object data = stringData(t, s); - if (objectClass(t, data) - == arrayBody(t, t->m->types, Machine::ByteArrayType)) - { + if (objectClass(t, data) == type(t, Machine::ByteArrayType)) { return byteArrayBody(t, data, stringOffset(t, s) + i); } else { return charArrayBody(t, data, stringOffset(t, s) + i); @@ -2063,7 +2124,7 @@ fieldSize(Thread* t, object field) } object -findLoadedSystemClass(Thread* t, object spec); +findLoadedClass(Thread* t, object loader, object spec); inline bool emptyMethod(Thread* t, object method) @@ -2080,7 +2141,7 @@ object parseClass(Thread* t, object loader, const uint8_t* data, unsigned length); object -resolveClass(Thread* t, object loader, object name); +resolveClass(Thread* t, object loader, object name, bool throw_ = true); inline object resolveClass(Thread* t, object loader, const char* name) @@ -2091,12 +2152,12 @@ resolveClass(Thread* t, object loader, const char* name) } object -resolveSystemClass(Thread* t, object name); +resolveSystemClass(Thread* t, object loader, object name, bool throw_ = true); inline object -resolveSystemClass(Thread* t, const char* name) +resolveSystemClass(Thread* t, object loader, const char* name) { - return resolveSystemClass(t, makeByteArray(t, "%s", name)); + return resolveSystemClass(t, loader, makeByteArray(t, "%s", name)); } void @@ -2150,13 +2211,12 @@ void initClass(Thread* t, object c); object -makeObjectArray(Thread* t, object loader, object elementClass, unsigned count); +makeObjectArray(Thread* t, object elementClass, unsigned count); inline object makeObjectArray(Thread* t, unsigned count) { - return makeObjectArray - (t, t->m->loader, arrayBody(t, t->m->types, Machine::JobjectType), count); + return makeObjectArray(t, type(t, Machine::JobjectType), count); } object @@ -2398,10 +2458,10 @@ monitorAppendWait(Thread* t, object monitor) { assert(t, monitorOwner(t, monitor) == t); - expect(t, not t->waiting); + expect(t, (t->flags & Thread::WaitingFlag) == 0); expect(t, t->waitNext == 0); - t->waiting = true; + atomicOr(&(t->flags), Thread::WaitingFlag); if (monitorWaitTail(t, monitor)) { static_cast(monitorWaitTail(t, monitor))->waitNext = t; @@ -2434,7 +2494,7 @@ monitorRemoveWait(Thread* t, object monitor) } t->waitNext = 0; - t->waiting = false; + atomicAnd(&(t->flags), ~Thread::WaitingFlag); return; } else { @@ -2489,7 +2549,7 @@ monitorWait(Thread* t, object monitor, int64_t time) monitorDepth(t, monitor) = depth; - if (t->waiting) { + if (t->flags & Thread::WaitingFlag) { monitorRemoveWait(t, monitor); } else { expect(t, not monitorFindWait(t, monitor)); @@ -2509,7 +2569,7 @@ monitorPollWait(Thread* t, object monitor) if (next) { monitorWaitHead(t, monitor) = next->waitNext; - next->waiting = false; + atomicAnd(&(next->flags), ~Thread::WaitingFlag); next->waitNext = 0; if (next == monitorWaitTail(t, monitor)) { monitorWaitTail(t, monitor) = 0; @@ -2677,7 +2737,13 @@ setDaemon(Thread* t, object thread, bool daemon) if ((threadDaemon(t, thread) != 0) != daemon) { threadDaemon(t, thread) = daemon; - t->daemon = daemon; + + Thread* p = reinterpret_cast(threadPeer(t, thread)); + if (daemon) { + atomicOr(&(p->flags), Thread::DaemonFlag); + } else { + atomicAnd(&(p->flags), ~Thread::DaemonFlag); + } if (daemon) { ++ t->m->daemonCount; @@ -2832,7 +2898,7 @@ resolveClassInObject(Thread* t, object loader, object container, unsigned classOffset) { object o = cast(container, classOffset); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType)) { + if (objectClass(t, o) == type(t, Machine::ByteArrayType)) { PROTECT(t, container); o = resolveClass(t, loader, o); @@ -2847,7 +2913,7 @@ inline object resolveClassInPool(Thread* t, object loader, object method, unsigned index) { object o = singletonObject(t, codePool(t, methodCode(t, method)), index); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) { + if (objectClass(t, o) == type(t, Machine::ReferenceType)) { PROTECT(t, method); o = resolveClass(t, loader, referenceName(t, o)); @@ -2872,7 +2938,7 @@ resolve(Thread* t, object loader, object method, unsigned index, Machine::Type errorType) { object o = singletonObject(t, codePool(t, methodCode(t, method)), index); - if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType)) + if (objectClass(t, o) == type(t, Machine::ReferenceType)) { PROTECT(t, method); @@ -2953,21 +3019,49 @@ inline object primitiveClass(Thread* t, char name) { switch (name) { - case 'B': return arrayBody(t, t->m->types, Machine::JbyteType); - case 'C': return arrayBody(t, t->m->types, Machine::JcharType); - case 'D': return arrayBody(t, t->m->types, Machine::JdoubleType); - case 'F': return arrayBody(t, t->m->types, Machine::JfloatType); - case 'I': return arrayBody(t, t->m->types, Machine::JintType); - case 'J': return arrayBody(t, t->m->types, Machine::JlongType); - case 'S': return arrayBody(t, t->m->types, Machine::JshortType); - case 'V': return arrayBody(t, t->m->types, Machine::JvoidType); - case 'Z': return arrayBody(t, t->m->types, Machine::JbooleanType); + case 'B': return type(t, Machine::JbyteType); + case 'C': return type(t, Machine::JcharType); + case 'D': return type(t, Machine::JdoubleType); + case 'F': return type(t, Machine::JfloatType); + case 'I': return type(t, Machine::JintType); + case 'J': return type(t, Machine::JlongType); + case 'S': return type(t, Machine::JshortType); + case 'V': return type(t, Machine::JvoidType); + case 'Z': return type(t, Machine::JbooleanType); default: t->exception = t->m->classpath->makeThrowable (t, Machine::IllegalArgumentExceptionType); return 0; } } + +inline void +registerNative(Thread* t, object method, void* function) +{ + PROTECT(t, method); + + expect(t, methodFlags(t, method) & ACC_NATIVE); + + object native = makeNative(t, function, false); + + // ensure other threads only see the methodCode field populated + // once the object it points to has been populated: + storeStoreMemoryBarrier(); + + set(t, method, MethodCode, native); +} + +inline void +unregisterNatives(Thread* t, object c) { + if (classMethodTable(t, c)) { + for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { + object method = arrayBody(t, classMethodTable(t, c), i); + if (methodFlags(t, method) & ACC_NATIVE) { + set(t, method, MethodCode, 0); + } + } + } +} object defineClass(Thread* t, object loader, const uint8_t* buffer, unsigned length); diff --git a/src/process.h b/src/process.h index ae1f2831fa..0b4ead129e 100644 --- a/src/process.h +++ b/src/process.h @@ -77,7 +77,8 @@ populateMultiArray(Thread* t, object array, int32_t* counts, &byteArrayBody(t, spec, 1), byteArrayLength(t, spec) - 1); - object class_ = resolveSystemClass(t, elementSpec); + object class_ = resolveClass + (t, classLoader(t, objectClass(t, array)), elementSpec); PROTECT(t, class_); for (int32_t i = 0; i < counts[index]; ++i) { diff --git a/src/processor.h b/src/processor.h index 8cff2b0782..ee3983f01c 100644 --- a/src/processor.h +++ b/src/processor.h @@ -128,7 +128,7 @@ class Processor { DelayedPromise** addresses, object method) = 0; virtual void - visitRoots(HeapWalker* w) = 0; + visitRoots(Thread* t, HeapWalker* w) = 0; virtual unsigned* makeCallTable(Thread* t, HeapWalker* w) = 0; @@ -153,10 +153,6 @@ class Processor { walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start) = 0; - virtual void registerNative(Thread* t, object method, void* function) = 0; - - virtual void unregisterNatives(Thread* t, object c) = 0; - object invoke(Thread* t, object method, object this_, ...) { diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 0e8a6bc758..bec29c7e69 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1137,7 +1137,7 @@ parseMember(Object* t, Object* p, Object* declarations) bool isNew; Object* member = parseMember(t, cdr(cdr(p)), declarations, &isNew); memberName(member) = string(car(cdr(p))); - return isNew ? member : 0; + return 0; } else { return Scalar::make(t, declaration(spec, declarations), spec, string(car(cdr(p))), diff --git a/src/types.def b/src/types.def index bdf13bf0fb..0ddeb92a3c 100644 --- a/src/types.def +++ b/src/types.def @@ -37,11 +37,6 @@ (type fieldAddendum avian/FieldAddendum) -(type nativeMethodData - (void* function) - (uint16_t argumentTableSize) - (array uint8_t parameterTypes)) - (type pointer (void* value)) diff --git a/src/util.cpp b/src/util.cpp index a15b57d77b..0745f98f72 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -318,8 +318,7 @@ hashMapFindNode(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)) { - bool weak = objectClass(t, map) - == arrayBody(t, t->m->types, Machine::WeakHashMapType); + bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType); object array = hashMapArray(t, map); if (array) { @@ -367,9 +366,7 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object), } if (oldArray) { - bool weak = objectClass(t, map) - == arrayBody(t, t->m->types, Machine::WeakHashMapType); - + bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType); for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) { object next; for (object p = arrayBody(t, oldArray, i); p; p = next) { @@ -407,8 +404,7 @@ hashMapInsert(Thread* t, object map, object key, object value, uint32_t h = hash(t, key); - bool weak = objectClass(t, map) - == arrayBody(t, t->m->types, Machine::WeakHashMapType); + bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType); object array = hashMapArray(t, map); @@ -432,7 +428,8 @@ hashMapInsert(Thread* t, object map, object key, object value, object r = makeWeakReference(t, 0, 0, 0, 0); jreferenceTarget(t, r) = key; jreferenceVmNext(t, r) = t->m->weakReferences; - k = t->m->weakReferences = r; + t->m->weakReferences = r; + k = r; array = hashMapArray(t, map); } @@ -465,8 +462,7 @@ hashMapRemove(Thread* t, object map, object key, uint32_t (*hash)(Thread*, object), bool (*equal)(Thread*, object, object)) { - bool weak = objectClass(t, map) - == arrayBody(t, t->m->types, Machine::WeakHashMapType); + bool weak = objectClass(t, map) == type(t, Machine::WeakHashMapType); object array = hashMapArray(t, map); object o = 0;