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 b1d16a7055..e0d02c98b2 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 bfa222549e..f0cc3c3252 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1421,6 +1421,30 @@ class Thread { SingleProtector protector; }; + class LibraryLoadStack: public AutoResource { + public: + LibraryLoadStack(Thread* t, object classLoader) + : AutoResource(t), + next(t->libraryLoadStack), + classLoader(classLoader), + protector(t, &(this->classLoader)) + { + t->libraryLoadStack = this; + } + + ~LibraryLoadStack() { + t->libraryLoadStack = next; + } + + virtual void release() { + this->LibraryLoadStack::~LibraryLoadStack(); + } + + LibraryLoadStack* next; + object classLoader; + SingleProtector protector; + }; + class Checkpoint { public: Checkpoint(Thread* t): @@ -1516,6 +1540,7 @@ class Thread { unsigned heapOffset; Protector* protector; ClassInitStack* classInitStack; + LibraryLoadStack* libraryLoadStack; Resource* resource; Checkpoint* checkpoint; Runnable runnable; @@ -1585,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/avian/target-fields.h b/src/avian/target-fields.h index 60e4c48c49..9efc1212e8 100644 --- a/src/avian/target-fields.h +++ b/src/avian/target-fields.h @@ -16,42 +16,42 @@ # if (TARGET_BYTES_PER_WORD == 8) #define TARGET_THREAD_EXCEPTION 80 -#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2256 -#define TARGET_THREAD_EXCEPTIONOFFSET 2264 -#define TARGET_THREAD_EXCEPTIONHANDLER 2272 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2264 +#define TARGET_THREAD_EXCEPTIONOFFSET 2272 +#define TARGET_THREAD_EXCEPTIONHANDLER 2280 -#define TARGET_THREAD_IP 2216 -#define TARGET_THREAD_STACK 2224 -#define TARGET_THREAD_NEWSTACK 2232 -#define TARGET_THREAD_SCRATCH 2240 -#define TARGET_THREAD_CONTINUATION 2248 -#define TARGET_THREAD_TAILADDRESS 2280 -#define TARGET_THREAD_VIRTUALCALLTARGET 2288 -#define TARGET_THREAD_VIRTUALCALLINDEX 2296 -#define TARGET_THREAD_HEAPIMAGE 2304 -#define TARGET_THREAD_CODEIMAGE 2312 -#define TARGET_THREAD_THUNKTABLE 2320 -#define TARGET_THREAD_STACKLIMIT 2368 +#define TARGET_THREAD_IP 2224 +#define TARGET_THREAD_STACK 2232 +#define TARGET_THREAD_NEWSTACK 2240 +#define TARGET_THREAD_SCRATCH 2248 +#define TARGET_THREAD_CONTINUATION 2256 +#define TARGET_THREAD_TAILADDRESS 2288 +#define TARGET_THREAD_VIRTUALCALLTARGET 2296 +#define TARGET_THREAD_VIRTUALCALLINDEX 2304 +#define TARGET_THREAD_HEAPIMAGE 2312 +#define TARGET_THREAD_CODEIMAGE 2320 +#define TARGET_THREAD_THUNKTABLE 2328 +#define TARGET_THREAD_STACKLIMIT 2376 # elif (TARGET_BYTES_PER_WORD == 4) #define TARGET_THREAD_EXCEPTION 44 -#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2164 -#define TARGET_THREAD_EXCEPTIONOFFSET 2168 -#define TARGET_THREAD_EXCEPTIONHANDLER 2172 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2168 +#define TARGET_THREAD_EXCEPTIONOFFSET 2172 +#define TARGET_THREAD_EXCEPTIONHANDLER 2176 -#define TARGET_THREAD_IP 2144 -#define TARGET_THREAD_STACK 2148 -#define TARGET_THREAD_NEWSTACK 2152 -#define TARGET_THREAD_SCRATCH 2156 -#define TARGET_THREAD_CONTINUATION 2160 -#define TARGET_THREAD_TAILADDRESS 2176 -#define TARGET_THREAD_VIRTUALCALLTARGET 2180 -#define TARGET_THREAD_VIRTUALCALLINDEX 2184 -#define TARGET_THREAD_HEAPIMAGE 2188 -#define TARGET_THREAD_CODEIMAGE 2192 -#define TARGET_THREAD_THUNKTABLE 2196 -#define TARGET_THREAD_STACKLIMIT 2220 +#define TARGET_THREAD_IP 2148 +#define TARGET_THREAD_STACK 2152 +#define TARGET_THREAD_NEWSTACK 2156 +#define TARGET_THREAD_SCRATCH 2160 +#define TARGET_THREAD_CONTINUATION 2164 +#define TARGET_THREAD_TAILADDRESS 2180 +#define TARGET_THREAD_VIRTUALCALLTARGET 2184 +#define TARGET_THREAD_VIRTUALCALLINDEX 2188 +#define TARGET_THREAD_HEAPIMAGE 2192 +#define TARGET_THREAD_CODEIMAGE 2196 +#define TARGET_THREAD_THUNKTABLE 2200 +#define TARGET_THREAD_STACKLIMIT 2224 # else # error 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 aa65c445a1..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,6 +1871,10 @@ management_JNI_OnLoad(JavaVM*, void*); void JNICALL loadLibrary(Thread* t, object, uintptr_t* arguments) { + 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); stringChars(t, name, RUNTIME_ARRAY_BODY(n)); diff --git a/src/continuations-x86.S b/src/continuations-x86.S index 071e4e7123..53584090b8 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,12 +10,6 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2248 -#define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2256 -#define THREAD_EXCEPTION_OFFSET 2264 -#define THREAD_EXCEPTION_HANDLER 2272 - #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 2160 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 -#define THREAD_EXCEPTION_OFFSET 2168 -#define THREAD_EXCEPTION_HANDLER 2172 - #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 be88848935..dda50462c1 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -349,10 +349,11 @@ findClass(Thread* t, uintptr_t* arguments) object caller = getCaller(t, 0); - object c = resolveClass(t, - caller ? classLoader(t, methodClass(t, caller)) - : root(t, Machine::AppLoader), - 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/src/machine.cpp b/src/machine.cpp index 93ddf5d5bc..33356f3ea5 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3337,6 +3337,7 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent): heapOffset(0), protector(0), classInitStack(0), + libraryLoadStack(0), runnable(this), defaultHeap(static_cast (m->heap->allocate(ThreadHeapSizeInBytes))), 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,