diff --git a/compiler/src/jlang/extension/JLangClassDeclExt.java b/compiler/src/jlang/extension/JLangClassDeclExt.java index 8c5fc90b..1a303763 100644 --- a/compiler/src/jlang/extension/JLangClassDeclExt.java +++ b/compiler/src/jlang/extension/JLangClassDeclExt.java @@ -19,6 +19,7 @@ import java.util.stream.Stream; import static jlang.extension.JLangSynchronizedExt.buildMonitorFunc; +import static jlang.extension.JLangSynchronizedExt.buildMonitorFuncWithGlobalMutex; import static jlang.util.Constants.REGISTER_CLASS_FUNC; import static jlang.util.Constants.RUNTIME_ARRAY; import static org.bytedeco.javacpp.LLVM.*; @@ -192,9 +193,7 @@ public static void buildClassLoadingFunc(LLVMTranslator v, ClassType ct, ClassBo Runnable buildBody = () -> { // Synchronize the class loading function. - LLVMValueRef globalMutexPtr = v.utils.getGlobal(Constants.GLOBAL_MUTEX_OBJECT, v.utils.toLL(v.ts.Object())); - LLVMValueRef globalMutex = LLVMBuildLoad(v.builder, globalMutexPtr, "load.classLoad"); - buildMonitorFunc(v, Constants.MONITOR_ENTER, globalMutex); + buildMonitorFuncWithGlobalMutex(v, Constants.MONITOR_ENTER); // Allocate and store a new java.lang.Class instance. // Note that we do not call any constructors for the allocated class objects. @@ -252,7 +251,7 @@ public static void buildClassLoadingFunc(LLVMTranslator v, ClassType ct, ClassBo } } - buildMonitorFunc(v, Constants.MONITOR_EXIT, globalMutex); + buildMonitorFuncWithGlobalMutex(v, Constants.MONITOR_EXIT); // Return the loaded class. LLVMBuildRet(v.builder, clazz); diff --git a/compiler/src/jlang/extension/JLangSynchronizedExt.java b/compiler/src/jlang/extension/JLangSynchronizedExt.java index 9b8a4911..e8743fd7 100644 --- a/compiler/src/jlang/extension/JLangSynchronizedExt.java +++ b/compiler/src/jlang/extension/JLangSynchronizedExt.java @@ -3,7 +3,9 @@ package jlang.extension; import jlang.ast.JLangExt; +import jlang.util.Constants; import jlang.visit.LLVMTranslator; +import org.bytedeco.javacpp.LLVM.LLVMBasicBlockRef; import org.bytedeco.javacpp.LLVM.LLVMTypeRef; import org.bytedeco.javacpp.LLVM.LLVMValueRef; import polyglot.ast.Node; @@ -24,6 +26,15 @@ public Node leaveTranslateLLVM(LLVMTranslator v) { return super.leaveTranslateLLVM(v); } + public static void buildMonitorFuncWithGlobalMutex(LLVMTranslator v, String op) { + LLVMTypeRef getGlobalMutexFuncType = v.utils.functionType( + v.utils.toLL(v.ts.Object()) + ); + LLVMValueRef getGlobalMutexFunc = v.utils.getFunction(Constants.GET_GLOBAL_MUTEX_OBJECT, getGlobalMutexFuncType); + LLVMValueRef globalMutex = v.utils.buildFunCall(getGlobalMutexFunc); + buildMonitorFunc(v, op, globalMutex); + } + public static void buildMonitorFunc(LLVMTranslator v, String op, LLVMValueRef syncObj) { LLVMValueRef cast = LLVMBuildBitCast(v.builder, syncObj, v.utils.toLL(v.ts.Object()), "cast_l"); LLVMTypeRef monitorFuncType = v.utils.functionType( diff --git a/compiler/src/jlang/util/Constants.java b/compiler/src/jlang/util/Constants.java index 88df419e..9511e298 100644 --- a/compiler/src/jlang/util/Constants.java +++ b/compiler/src/jlang/util/Constants.java @@ -35,7 +35,7 @@ public class Constants { public static final String RESUME_UNWIND_EXCEPTION = "_Unwind_Resume"; public static final String MONITOR_ENTER = "jni_MonitorEnter"; public static final String MONITOR_EXIT = "jni_MonitorExit"; - public static final String GLOBAL_MUTEX_OBJECT = "Polyglot_native_GlobalMutexObject"; + public static final String GET_GLOBAL_MUTEX_OBJECT = "getGlobalMutexObject"; public static final Set NON_INVOKE_FUNCTIONS = new HashSet<>(CollectionUtil.list( CALLOC, CREATE_EXCEPTION, EXTRACT_EXCEPTION diff --git a/compiler/src/jlang/util/LLVMUtils.java b/compiler/src/jlang/util/LLVMUtils.java index 65c9fdd6..7405de12 100644 --- a/compiler/src/jlang/util/LLVMUtils.java +++ b/compiler/src/jlang/util/LLVMUtils.java @@ -22,6 +22,7 @@ import java.util.stream.IntStream; import static jlang.extension.JLangSynchronizedExt.buildMonitorFunc; +import static jlang.extension.JLangSynchronizedExt.buildMonitorFuncWithGlobalMutex; import static org.bytedeco.javacpp.LLVM.*; /** @@ -805,9 +806,7 @@ public LLVMValueRef buildGlobalCStr(String str) { /** Emits a check to ensure that the given class has been loaded by the runtime. */ public void buildClassLoadCheck(ClassType ct) { // Synchronize the class loading function. - LLVMValueRef globalMutexPtr = v.utils.getGlobal(Constants.GLOBAL_MUTEX_OBJECT, v.utils.toLL(v.ts.Object())); - LLVMValueRef globalMutex = LLVMBuildLoad(v.builder, globalMutexPtr, "load.classLoad"); - buildMonitorFunc(v, Constants.MONITOR_ENTER, globalMutex); + buildMonitorFuncWithGlobalMutex(v, Constants.MONITOR_ENTER); LLVMBasicBlockRef loadClass = v.utils.buildBlock("load.class"); LLVMBasicBlockRef end = v.utils.buildBlock("continue"); @@ -827,7 +826,7 @@ public void buildClassLoadCheck(ClassType ct) { LLVMPositionBuilderAtEnd(v.builder, end); - buildMonitorFunc(v, Constants.MONITOR_EXIT, globalMutex); + buildMonitorFuncWithGlobalMutex(v, Constants.MONITOR_EXIT); } /** diff --git a/runtime/linux_version.map b/runtime/linux_version.map index abe95487..f8301236 100644 --- a/runtime/linux_version.map +++ b/runtime/linux_version.map @@ -19,6 +19,7 @@ SUNWprivate_1.1 { __createInterfaceTables; __java_personality_v0; __GC_malloc; + getGlobalMutexObject; local: *; }; diff --git a/runtime/native/class.cpp b/runtime/native/class.cpp index 5000c038..0e8de0f9 100644 --- a/runtime/native/class.cpp +++ b/runtime/native/class.cpp @@ -690,12 +690,11 @@ jclass LoadJavaClassFromLib(const char *name) { * function will be invoked. The class name is in the format java.lang.Class */ jclass FindClass(const char *name) { - Monitor::Instance().enter(nullptr); + ScopedLock scopedLock(Monitor::Instance().globalMutex()); jclass clazz = GetJavaClassFromName(name); if (clazz == nullptr) { clazz = LoadJavaClassFromLib(name); } - Monitor::Instance().exit(nullptr); return clazz; } @@ -704,11 +703,10 @@ jclass FindClass(const char *name) { * function will be invoked. The class name is in the format java/lang/Class */ jclass FindClassFromPathName(const char *name) { - Monitor::Instance().enter(nullptr); + ScopedLock scopedLock(Monitor::Instance().globalMutex()); jclass clazz = GetJavaClassFromPathName(name); if (clazz == nullptr) { clazz = LoadJavaClassFromLib(name); } - Monitor::Instance().exit(nullptr); return clazz; } \ No newline at end of file diff --git a/runtime/native/factory.cpp b/runtime/native/factory.cpp index 2daed56d..5bea2cec 100644 --- a/runtime/native/factory.cpp +++ b/runtime/native/factory.cpp @@ -4,6 +4,7 @@ #include "class.h" #include "rep.h" +#include "monitor.h" #include #include @@ -66,6 +67,8 @@ jstring CreateJavaString(jcharArray chars) { } jobject CreateJavaObject(jclass clazz) { + ScopedLock lock(Monitor::Instance().globalMutex()); + auto info = GetJavaClassInfo(clazz); // TODO set exception (class is interface or abstract) if (info == NULL || info->cdv == NULL) { @@ -81,6 +84,8 @@ jobject CreateJavaObject(jclass clazz) { jobject CloneJavaObject(jobject obj) { // TODO set exception if class is not cloneable + ScopedLock lock(Monitor::Instance().globalMutex()); + auto objRep = Unwrap(obj); auto cdv = objRep->Cdv(); auto cls = cdv->Class()->Wrap(); diff --git a/runtime/native/monitor.cpp b/runtime/native/monitor.cpp index 27ba8067..9e14c3e3 100644 --- a/runtime/native/monitor.cpp +++ b/runtime/native/monitor.cpp @@ -48,18 +48,14 @@ static void initSyncVars(jobject obj) { // A fake object to hold the sync_var of class loading function. // The class loading code could utilize this global object to ensure that // every class is only initilized by one thread once. -JObjectRep __Polyglot_native_GlobalMutexObject; - -static jobject getGlobalMutexObject() { +extern "C" jobject getGlobalMutexObject() { + static JObjectRep __Polyglot_native_GlobalMutexObject; if (__Polyglot_native_GlobalMutexObject.SyncVars() == nullptr) { initSyncVars(__Polyglot_native_GlobalMutexObject.Wrap()); } return __Polyglot_native_GlobalMutexObject.Wrap(); } -jobject Polyglot_native_GlobalMutexObject = getGlobalMutexObject(); - - Monitor::Monitor() { if (pthread_mutex_init(&mutex, nullptr) != 0) { perror("mutex init failed");