diff --git a/README.md b/README.md index 7bf40c33a2..baf68ce626 100644 --- a/README.md +++ b/README.md @@ -388,7 +388,7 @@ the following, starting from the Avian directory: git clone https://android.googlesource.com/platform/external/openssl \ external/openssl (cd external/openssl && \ - git checkout 7b972f1aa23172c4430ada7f3236fa1fd9b31756) + git checkout 1417357d893849c4b6afdd98c32b6ca1b4b19a8b) git clone https://android.googlesource.com/platform/external/zlib \ external/zlib @@ -396,12 +396,11 @@ the following, starting from the Avian directory: git checkout 15b6223aa57a347ce113729253802cb2fdeb4ad0) git clone git://git.openssl.org/openssl.git openssl-upstream - (cd openssl-upstream && \ - git checkout OpenSSL_1_0_1e) + (cd openssl-upstream && git checkout OpenSSL_1_0_1h) git clone https://github.com/dicej/android-libcore64 libcore - curl -Of http://oss.readytalk.com/avian/expat-2.1.0.tar.gz + curl -Of http://oss.readytalk.com/avian-web/expat-2.1.0.tar.gz (cd external && tar xzf ../expat-2.1.0.tar.gz && mv expat-2.1.0 expat) (cd external/expat && CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure \ @@ -417,16 +416,8 @@ NB: use 'CC="gcc -fPIC" ./Configure darwin64-x86_64-cc' when building for x86_64 OS X instead of 'CC="gcc -fPIC" ./config': (cd openssl-upstream \ - && (for x in \ - progs \ - handshake_cutthrough \ - jsse \ - channelid \ - eng_dyn_dirs \ - fix_clang_build \ - tls12_digests \ - alpn; \ - do patch -p1 < ../external/openssl/patches/$x.patch; done) \ + && (for x in ../external/openssl/patches/*.patch; \ + do patch -p1 < $x; done) \ && CC="gcc -fPIC" ./config && make) cd ../avian diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index c950a0dd74..0a75c98b6f 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -195,5 +195,8 @@ public abstract class ClassLoader { } return urls; } - + + static native Class getCaller(); + + static native void load(String name, Class caller, boolean mapName); } diff --git a/classpath/java/lang/Runtime.java b/classpath/java/lang/Runtime.java index f4f0e40718..863e0c4598 100644 --- a/classpath/java/lang/Runtime.java +++ b/classpath/java/lang/Runtime.java @@ -29,7 +29,7 @@ public class Runtime { public void load(String path) { if (path != null) { - load(path, false); + ClassLoader.load(path, ClassLoader.getCaller(), false); } else { throw new NullPointerException(); } @@ -37,7 +37,7 @@ public class Runtime { public void loadLibrary(String path) { if (path != null) { - load(path, true); + ClassLoader.load(path, ClassLoader.getCaller(), true); } else { throw new NullPointerException(); } @@ -120,8 +120,6 @@ public class Runtime { private static native int waitFor(long pid, long tid); - private static native void load(String name, boolean mapName); - private static native void kill(long pid); public native void gc(); diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 7b8dd5cbb1..357ef92428 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -108,11 +108,11 @@ public abstract class System { private static native String doMapLibraryName(String name); public static void load(String path) { - Runtime.getRuntime().load(path); + ClassLoader.load(path, ClassLoader.getCaller(), false); } public static void loadLibrary(String name) { - Runtime.getRuntime().loadLibrary(name); + ClassLoader.load(name, ClassLoader.getCaller(), true); } public static void gc() { diff --git a/makefile b/makefile index b7afb7611e..33663cd29b 100755 --- a/makefile +++ b/makefile @@ -260,6 +260,9 @@ ifneq ($(android),) platform-lflags := -lgdi32 -lshlwapi -lwsock32 else android-cflags += -fPIC -DHAVE_SYS_UIO_H + blacklist = $(luni-native)/java_math_NativeBN.cpp + + luni-cpps := $(filter-out $(blacklist),$(luni-cpps)) icu-libs := $(android)/external/icu4c/lib/libicui18n.a \ $(android)/external/icu4c/lib/libicuuc.a \ $(android)/external/icu4c/lib/libicudata.a diff --git a/src/avian/machine.h b/src/avian/machine.h index 0184d08f61..f0cc3c3252 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1423,11 +1423,11 @@ class Thread { class LibraryLoadStack: public AutoResource { public: - LibraryLoadStack(Thread* t, object class_): - AutoResource(t), - next(t->libraryLoadStack), - class_(class_), - protector(t, &(this->class_)) + LibraryLoadStack(Thread* t, object classLoader) + : AutoResource(t), + next(t->libraryLoadStack), + classLoader(classLoader), + protector(t, &(this->classLoader)) { t->libraryLoadStack = this; } @@ -1441,7 +1441,7 @@ class Thread { } LibraryLoadStack* next; - object class_; + object classLoader; SingleProtector protector; }; @@ -1610,6 +1610,8 @@ class Classpath { canTailCall(Thread* t, object caller, object calleeClassName, object calleeMethodName, object calleeMethodSpec) = 0; + virtual object libraryClassLoader(Thread* t, object caller) = 0; + virtual void shutDown(Thread* t) = 0; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 99c2965ce7..7d9e6d3dc3 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -55,6 +55,8 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) { object name = reinterpret_cast(arguments[1]); + Thread::LibraryLoadStack stack(t, reinterpret_cast(arguments[2])); + unsigned length = stringLength(t, name); THREAD_RUNTIME_ARRAY(t, char, n, length + 1); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); @@ -568,6 +570,17 @@ class MyClasspath : public Classpath { return true; } + virtual object libraryClassLoader(Thread* t, object caller) + { + return strcmp( + "java/lang/Runtime", + reinterpret_cast( + &byteArrayBody(t, className(t, methodClass(t, caller)), 0))) + == 0 + ? t->libraryLoadStack->classLoader + : classLoader(t, methodClass(t, caller)); + } + virtual void shutDown(Thread*) { @@ -988,6 +1001,12 @@ register_org_apache_harmony_dalvik_NativeTestTarget(_JNIEnv*) return 0; } +int register_java_math_NativeBN(_JNIEnv*) +{ + // ignore + return 0; +} + extern "C" AVIAN_EXPORT int64_t JNICALL Avian_java_lang_String_compareTo (Thread* t, object, uintptr_t* arguments) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index b7e2299adc..7bed10ce32 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -179,10 +179,37 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } - virtual bool - canTailCall(Thread*, object, object, object, object) + virtual bool canTailCall(Thread* t, + object, + object calleeClassName, + object calleeMethodName, + object) { - return true; + // we can't tail call System.load[Library] or + // Runtime.load[Library] due to their use of + // ClassLoader.getCaller, which gets confused if we elide stack + // frames. + + return ( + (strcmp("loadLibrary", + reinterpret_cast(&byteArrayBody(t, calleeMethodName, 0))) + and strcmp("load", + reinterpret_cast( + &byteArrayBody(t, calleeMethodName, 0)))) + or (strcmp( + "java/lang/System", + reinterpret_cast(&byteArrayBody(t, calleeClassName, 0))) + and strcmp("java/lang/Runtime", + reinterpret_cast( + &byteArrayBody(t, calleeClassName, 0))))); + } + + virtual object libraryClassLoader(Thread* t, object caller) + { + return (methodClass(t, caller) == type(t, Machine::ClassLoaderType) + and t->libraryLoadStack) + ? t->libraryLoadStack->classLoader + : classLoader(t, methodClass(t, caller)); } virtual void @@ -550,12 +577,23 @@ Avian_java_lang_System_identityHashCode } } +extern "C" AVIAN_EXPORT int64_t JNICALL + Avian_java_lang_ClassLoader_getCaller(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast( + getJClass(t, methodClass(t, getCaller(t, 2)))); +} + extern "C" AVIAN_EXPORT void JNICALL -Avian_java_lang_Runtime_load -(Thread* t, object, uintptr_t* arguments) + Avian_java_lang_ClassLoader_load(Thread* t, object, uintptr_t* arguments) { object name = reinterpret_cast(arguments[0]); - bool mapName = arguments[1]; + + Thread::LibraryLoadStack stack( + t, + classLoader(t, jclassVmClass(t, reinterpret_cast(arguments[1])))); + + bool mapName = arguments[2]; unsigned length = stringLength(t, name); THREAD_RUNTIME_ARRAY(t, char, n, length + 1); diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 5eb5671f17..6e63aa454f 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -844,6 +844,32 @@ class MyClasspath : public Classpath { (&byteArrayBody(t, calleeClassName, 0)))); } + virtual object libraryClassLoader(Thread* t, object caller) + { +#ifdef AVIAN_OPENJDK_SRC + return (methodClass(t, caller) == type(t, Machine::ClassLoaderType) + and t->libraryLoadStack) + ? t->libraryLoadStack->classLoader +#else + return strcmp( + "java/lang/ClassLoader$NativeLibrary", + reinterpret_cast( + &byteArrayBody(t, className(t, methodClass(t, caller)), 0))) + == 0 + ? classLoader( + t, + jclassVmClass(t, + t->m->processor->invoke( + t, + resolveMethod(t, + methodClass(t, caller), + "getFromClass", + "()Ljava/lang/Class;"), + 0))) +#endif + : classLoader(t, methodClass(t, caller)); + } + virtual void shutDown(Thread* t) { @@ -1845,8 +1871,9 @@ management_JNI_OnLoad(JavaVM*, void*); void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) { - Thread::LibraryLoadStack stack - (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); + Thread::LibraryLoadStack stack( + t, + classLoader(t, jclassVmClass(t, reinterpret_cast(arguments[0])))); object name = reinterpret_cast(arguments[1]); THREAD_RUNTIME_ARRAY(t, char, n, stringLength(t, name) + 1); diff --git a/src/continuations-x86.S b/src/continuations-x86.S index d088bdaf72..53584090b8 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,12 +10,6 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2256 -#define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2264 -#define THREAD_EXCEPTION_OFFSET 2272 -#define THREAD_EXCEPTION_HANDLER 2280 - #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 #define CONTINUATION_RETURN_ADDRESS_OFFSET 40 @@ -24,7 +18,7 @@ #define CONTINUATION_BODY 64 // call the next continuation, if any - movq THREAD_CONTINUATION(%rbx),%rcx + movq TARGET_THREAD_CONTINUATION(%rbx),%rcx cmpq $0,%rcx je LOCAL(vmInvoke_exit) @@ -69,34 +63,28 @@ LOCAL(vmInvoke_continuationTest): // consume the continuation movq CONTINUATION_NEXT(%rcx),%rdi - movq %rdi,THREAD_CONTINUATION(%rbx) + movq %rdi,TARGET_THREAD_CONTINUATION(%rbx) // call the continuation unless we're handling an exception - movq THREAD_EXCEPTION(%rbx),%rsi + movq TARGET_THREAD_EXCEPTION(%rbx),%rsi cmpq $0,%rsi jne LOCAL(vmInvoke_handleException) jmp *CONTINUATION_ADDRESS(%rcx) LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead - movq $0,THREAD_EXCEPTION(%rbx) - movq THREAD_EXCEPTION_STACK_ADJUSTMENT(%rbx),%rdi + movq $0,TARGET_THREAD_EXCEPTION(%rbx) + movq TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(%rbx),%rdi subq %rdi,%rsp - movq THREAD_EXCEPTION_OFFSET(%rbx),%rdi + movq TARGET_THREAD_EXCEPTIONOFFSET(%rbx),%rdi movq %rsi,(%rsp,%rdi,1) - jmp *THREAD_EXCEPTION_HANDLER(%rbx) + jmp *TARGET_THREAD_EXCEPTIONHANDLER(%rbx) LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 2164 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2168 -#define THREAD_EXCEPTION_OFFSET 2172 -#define THREAD_EXCEPTION_HANDLER 2176 - #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 #define CONTINUATION_RETURN_ADDRESS_OFFSET 20 @@ -111,7 +99,7 @@ LOCAL(vmInvoke_exit): #endif // call the next continuation, if any - movl THREAD_CONTINUATION(%ebx),%ecx + movl TARGET_THREAD_CONTINUATION(%ebx),%ecx cmpl $0,%ecx je LOCAL(vmInvoke_exit) @@ -169,10 +157,10 @@ LOCAL(vmInvoke_offset): // consume the continuation movl CONTINUATION_NEXT(%ecx),%edi - movl %edi,THREAD_CONTINUATION(%ebx) + movl %edi,TARGET_THREAD_CONTINUATION(%ebx) // call the continuation unless we're handling an exception - movl THREAD_EXCEPTION(%ebx),%esi + movl TARGET_THREAD_EXCEPTION(%ebx),%esi cmpl $0,%esi jne LOCAL(vmInvoke_handleException) @@ -180,13 +168,13 @@ LOCAL(vmInvoke_offset): LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead - movl $0,THREAD_EXCEPTION(%ebx) - movl THREAD_EXCEPTION_STACK_ADJUSTMENT(%ebx),%edi + movl $0,TARGET_THREAD_EXCEPTION(%ebx) + movl TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(%ebx),%edi subl %edi,%esp - movl THREAD_EXCEPTION_OFFSET(%ebx),%edi + movl TARGET_THREAD_EXCEPTIONOFFSET(%ebx),%edi movl %esi,(%esp,%edi,1) - jmp *THREAD_EXCEPTION_HANDLER(%ebx) + jmp *TARGET_THREAD_EXCEPTIONHANDLER(%ebx) LOCAL(vmInvoke_exit): diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 9f8e7c3fb8..dda50462c1 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -349,20 +349,11 @@ findClass(Thread* t, uintptr_t* arguments) object caller = getCaller(t, 0); - object loader; - if (caller) { - if (methodClass(t, caller) == type(t, Machine::ClassLoaderType) - and t->libraryLoadStack) - { - loader = classLoader(t, t->libraryLoadStack->class_); - } else { - loader = classLoader(t, methodClass(t, caller)); - } - } else { - loader = root(t, Machine::AppLoader); - } - - object c = resolveClass(t, loader, n); + object c + = resolveClass(t, + caller ? t->m->classpath->libraryClassLoader(t, caller) + : root(t, Machine::AppLoader), + n); if (t->m->classpath->mayInitClasses()) { PROTECT(t, c); diff --git a/test/JNI.java b/test/JNI.java index 955bfc9052..a7fb40c62d 100644 --- a/test/JNI.java +++ b/test/JNI.java @@ -3,6 +3,8 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; public class JNI { + private static boolean onLoadCalled; + static { System.loadLibrary("test"); } @@ -64,6 +66,8 @@ public class JNI { public static final int field950 = 950; public static void main(String[] args) throws Exception { + expect(onLoadCalled); + expect(addDoubles (1.0d, 2.0d, 3.0d, 4.0d, 5.0d, 6.0d, 7.0d, 8.0d, 9.0d, 10.0d, 11.0d, 12.0d, 13.0d, 14.0d, 15.0d, 16.0d, 17.0d, 18.0d, 19.0d, 20.0d) diff --git a/test/jni.cpp b/test/jni.cpp index 8b8d6dc8c9..6bc11e12c2 100644 --- a/test/jni.cpp +++ b/test/jni.cpp @@ -1,6 +1,24 @@ #include #include "jni-util.h" +extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) +{ + JNIEnv* e; + if (vm->GetEnv(reinterpret_cast(&e), JNI_VERSION_1_6) != JNI_OK) { + return -1; + } + + jclass c = e->FindClass("JNI"); + if (c == 0) { + return -1; + } + + e->SetStaticBooleanField( + c, e->GetStaticFieldID(c, "onLoadCalled", "Z"), true); + + return JNI_VERSION_1_6; +} + extern "C" JNIEXPORT jdouble JNICALL Java_JNI_addDoubles (JNIEnv*, jclass,