From ca84dd26f1dc6f1fd372b184d7e4191cf818a9e0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Mar 2013 15:43:49 -0700 Subject: [PATCH] fix System.loadLibrary for OpenJDK tails=true build --- src/avian/machine.h | 4 ++++ src/classpath-android.cpp | 6 ++++++ src/classpath-avian.cpp | 6 ++++++ src/classpath-openjdk.cpp | 24 ++++++++++++++++++++++++ src/compile.cpp | 20 ++++++++++++++++---- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index 8f1ec1d3d2..7263b183a6 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1583,6 +1583,10 @@ class Classpath { virtual int64_t getDirectBufferCapacity(Thread* t, object buffer) = 0; + virtual bool + canTailCall(Thread* t, object caller, object calleeClassName, + object calleeMethodName, object calleeMethodSpec) = 0; + virtual void dispose() = 0; }; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index d70f3defe2..b2a2a174b3 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -439,6 +439,12 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread*, object, object, object, object) + { + return true; + } + virtual void dispose() { diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index f0ea0367e7..5617b92070 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -174,6 +174,12 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread*, object, object, object, object) + { + return true; + } + virtual void dispose() { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 2fdf0d3b42..da53a7532e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -842,6 +842,30 @@ class MyClasspath : public Classpath { return fieldAtOffset(b, fieldOffset(t, field)); } + virtual bool + canTailCall(Thread* t, object, object calleeClassName, + object calleeMethodName, object) + { + // we can't tail call System.loadLibrary or Runtime.loadLibrary + // due to their use of System.getCallerClass, which gets confused + // if we elide stack frames. + + return (strcmp("loadLibrary", 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))))) + + // and we can't tail call Reflection.getCallerClass because the + // number of stack frames will be wrong + + and (strcmp("getCallerClass", reinterpret_cast + (&byteArrayBody(t, calleeMethodName, 0))) + or strcmp("sun/reflect/Reflection", reinterpret_cast + (&byteArrayBody(t, calleeClassName, 0)))); + } + virtual void dispose() { diff --git a/src/compile.cpp b/src/compile.cpp index d2c509b0ac..259b6f5858 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3730,7 +3730,8 @@ returnsNext(MyThread* t, object code, unsigned ip) bool isTailCall(MyThread* t, object code, unsigned ip, object caller, - int calleeReturnCode) + int calleeReturnCode, object calleeClassName, + object calleeMethodName, object calleeMethodSpec) { return avian::codegen::TailCalls and ((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0) @@ -3738,21 +3739,32 @@ isTailCall(MyThread* t, object code, unsigned ip, object caller, and (not needsReturnBarrier(t, caller)) and (methodReturnCode(t, caller) == VoidField or methodReturnCode(t, caller) == calleeReturnCode) - and returnsNext(t, code, ip); + and returnsNext(t, code, ip) + and t->m->classpath->canTailCall + (t, caller, calleeClassName, calleeMethodName, calleeMethodSpec); } bool isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee) { - return isTailCall(t, code, ip, caller, methodReturnCode(t, callee)); + return isTailCall + (t, code, ip, caller, methodReturnCode(t, callee), + className(t, methodClass(t, callee)), methodName(t, callee), + methodSpec(t, callee)); } bool isReferenceTailCall(MyThread* t, object code, unsigned ip, object caller, object calleeReference) { + object c = referenceClass(t, calleeReference); + if (objectClass(t, c) == type(t, Machine::ClassType)) { + c = className(t, c); + } + return isTailCall - (t, code, ip, caller, methodReferenceReturnCode(t, calleeReference)); + (t, code, ip, caller, methodReferenceReturnCode(t, calleeReference), + c, referenceName(t, calleeReference), referenceSpec(t, calleeReference)); } bool