From 70928832841b918f15c710aa407934f277e9893f Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Wed, 9 Aug 2017 13:17:10 +0300 Subject: [PATCH 1/3] Add "markingMode": "none" to the android key in the app/package.json to switch the memory management to one, that will not traverse the JS heap graph --- .gitignore | 6 +- runtime/src/main/java/com/tns/AppConfig.java | 10 ++- runtime/src/main/java/com/tns/Runtime.java | 40 +++++++++ runtime/src/main/jni/ObjectManager.cpp | 83 +++++++++++++++++-- runtime/src/main/jni/ObjectManager.h | 20 +++++ test-app/app/src/main/assets/app/package.json | 3 +- 6 files changed, 153 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index c2acc737a..98b1827b7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,8 @@ obj/ bin/ .svn/ -**/.vscode/ \ No newline at end of file +**/.vscode/ + +.project +.DS_Store +.settings diff --git a/runtime/src/main/java/com/tns/AppConfig.java b/runtime/src/main/java/com/tns/AppConfig.java index 3dad082f6..51e3359e9 100644 --- a/runtime/src/main/java/com/tns/AppConfig.java +++ b/runtime/src/main/java/com/tns/AppConfig.java @@ -17,7 +17,8 @@ private enum KnownKeys { GcThrottleTime("gcThrottleTime", 0), MemoryCheckInterval("memoryCheckInterval", 0), FreeMemoryRatio("freeMemoryRatio", 0.0), - Profiling("profiling", ""); + Profiling("profiling", ""), + MarkingMode("markingMode", "Full"); public static final KnownKeys[] asArray = { V8FlagsKey, @@ -28,7 +29,8 @@ private enum KnownKeys { GcThrottleTime, MemoryCheckInterval, FreeMemoryRatio, - Profiling + Profiling, + MarkingMode }; private final String name; @@ -111,6 +113,9 @@ public AppConfig(File appDir) { if (androidObject.has(KnownKeys.FreeMemoryRatio.getName())) { values[KnownKeys.FreeMemoryRatio.getIndex()] = androidObject.getDouble(KnownKeys.FreeMemoryRatio.getName()); } + if (androidObject.has(KnownKeys.MarkingMode.getName())) { + values[KnownKeys.MarkingMode.getIndex()] = androidObject.getString(KnownKeys.MarkingMode.getName()); + } } } } catch (Exception e) { @@ -146,4 +151,5 @@ public double getFreeMemoryRatio() { public String getProfilingMode() { return (String)values[KnownKeys.Profiling.getIndex()]; } + public String getMarkingMode() { return (String)values[KnownKeys.MarkingMode.getIndex()]; } } diff --git a/runtime/src/main/java/com/tns/Runtime.java b/runtime/src/main/java/com/tns/Runtime.java index d7fe54dc1..e356f707a 100644 --- a/runtime/src/main/java/com/tns/Runtime.java +++ b/runtime/src/main/java/com/tns/Runtime.java @@ -202,6 +202,14 @@ public DynamicConfiguration getDynamicConfig() { return dynamicConfig; } + public int getMarkingMode() { + String mode = staticConfiguration == null || staticConfiguration.appConfig == null ? "full" : staticConfiguration.appConfig.getMarkingMode(); + if ("none".equals(mode)) { + return 1; + } + return 0; + } + public static boolean isInitialized() { Runtime runtime = Runtime.getCurrentRuntime(); @@ -806,6 +814,38 @@ private void makeInstanceWeak(ByteBuffer buff, int length, boolean keepAsWeak) { } } + @RuntimeCallable + private boolean makeInstanceWeakAndCheckIfAlive(int javaObjectID) { + if (logger.isEnabled()) { + logger.write("makeInstanceWeakAndCheckIfAlive instance " + javaObjectID); + } + Object instance = strongInstances.get(javaObjectID); + if (instance == null) { + WeakReference ref = weakInstances.get(javaObjectID); + if (ref == null) { + return false; + } else { + instance = ref.get(); + if (instance == null) { + // The Java was moved from strong to weak, and then the Java instance was collected. + weakInstances.remove(javaObjectID); + weakJavaObjectToID.remove(Integer.valueOf(javaObjectID)); + return false; + } else { + return true; + } + } + } else { + strongInstances.delete(javaObjectID); + strongJavaObjectToID.remove(instance); + + weakJavaObjectToID.put(instance, Integer.valueOf(javaObjectID)); + weakInstances.put(javaObjectID, new WeakReference(instance)); + + return true; + } + } + @RuntimeCallable private void checkWeakObjectAreAlive(ByteBuffer input, ByteBuffer output, int length) { input.position(0); diff --git a/runtime/src/main/jni/ObjectManager.cpp b/runtime/src/main/jni/ObjectManager.cpp index 96a0a19ad..68dbfb48b 100644 --- a/runtime/src/main/jni/ObjectManager.cpp +++ b/runtime/src/main/jni/ObjectManager.cpp @@ -17,8 +17,14 @@ using namespace v8; using namespace std; using namespace tns; -ObjectManager::ObjectManager(jobject javaRuntimeObject) - : m_javaRuntimeObject(javaRuntimeObject), m_env(JEnv()), m_numberOfGC(0), m_currentObjectId(0), m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000, this) { +ObjectManager::ObjectManager(jobject javaRuntimeObject) : + m_javaRuntimeObject(javaRuntimeObject), + m_env(JEnv()), + m_numberOfGC(0), + m_currentObjectId(0), + m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000, this), + m_markingMode(JavaScriptMarkingMode::Full) { + auto runtimeClass = m_env.FindClass("com/tns/Runtime"); assert(runtimeClass != nullptr); @@ -31,6 +37,9 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject) MAKE_INSTANCE_WEAK_BATCH_METHOD_ID = m_env.GetMethodID(runtimeClass, "makeInstanceWeak", "(Ljava/nio/ByteBuffer;IZ)V"); assert(MAKE_INSTANCE_WEAK_BATCH_METHOD_ID != nullptr); + MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID = m_env.GetMethodID(runtimeClass, "makeInstanceWeakAndCheckIfAlive", "(I)Z"); + assert(MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID != nullptr); + CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID = m_env.GetMethodID(runtimeClass, "checkWeakObjectAreAlive", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)V"); assert(CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID != nullptr); @@ -45,6 +54,14 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject) auto useGlobalRefs = m_env.CallStaticBooleanMethod(runtimeClass, useGlobalRefsMethodID); m_useGlobalRefs = useGlobalRefs == JNI_TRUE; + + auto getMarkingModeMethodID = m_env.GetMethodID(runtimeClass, "getMarkingMode", "()I"); + jint markingMode = m_env.CallIntMethod(m_javaRuntimeObject, getMarkingModeMethodID); + switch(markingMode) { + case 1: + m_markingMode = JavaScriptMarkingMode::None; + break; + } } void ObjectManager::SetInstanceIsolate(Isolate* isolate) { @@ -57,8 +74,10 @@ void ObjectManager::Init(Isolate* isolate) { auto jsWrapperFunc = jsWrapperFuncTemplate->GetFunction(); m_poJsWrapperFunc = new Persistent(isolate, jsWrapperFunc); - isolate->AddGCPrologueCallback(ObjectManager::OnGcStartedStatic, kGCTypeAll); - isolate->AddGCEpilogueCallback(ObjectManager::OnGcFinishedStatic, kGCTypeAll); + if (m_markingMode != JavaScriptMarkingMode::None) { + isolate->AddGCPrologueCallback(ObjectManager::OnGcStartedStatic, kGCTypeAll); + isolate->AddGCEpilogueCallback(ObjectManager::OnGcFinishedStatic, kGCTypeAll); + } } @@ -211,7 +230,11 @@ void ObjectManager::Link(const Local& object, uint32_t javaObjectID, jcl auto state = new ObjectWeakCallbackState(this, jsInstanceInfo, objectHandle); // subscribe for JS GC event - objectHandle->SetWeak(state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer); + if (m_markingMode == JavaScriptMarkingMode::None) { + objectHandle->SetWeak(state, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer); + } else { + objectHandle->SetWeak(state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer); + } auto jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); @@ -263,6 +286,56 @@ void ObjectManager::JSObjectWeakCallbackStatic(const WeakCallbackInfoJSObjectWeakCallback(isolate, callbackState); } +void ObjectManager::JSObjectFinalizerStatic(const WeakCallbackInfo& data) { + ObjectWeakCallbackState* callbackState = data.GetParameter(); + + ObjectManager* thisPtr = callbackState->thisPtr; + + auto isolate = data.GetIsolate(); + + thisPtr->JSObjectFinalizer(isolate, callbackState); +} + +void ObjectManager::JSObjectFinalizer(Isolate* isolate, ObjectWeakCallbackState* callbackState) { + Persistent* po = callbackState->target; + + auto jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); + auto jsInstance = po->Get(m_isolate); + auto jsInfo = jsInstance->GetInternalField(jsInfoIdx); + if (jsInfo->IsUndefined()) { + // Typescript object layout has an object instance as child of the actual registered instance. checking for that + auto prototypeObject = jsInstance->GetPrototype().As(); + if (!prototypeObject.IsEmpty() && prototypeObject->IsObject()) { + DEBUG_WRITE("GetJSInstanceInfo: need to check prototype :%d", prototypeObject->GetIdentityHash()); + if (IsJsRuntimeObject(prototypeObject)) { + jsInfo = prototypeObject->GetInternalField(jsInfoIdx); + } + } + } + + if (jsInfo.IsEmpty() || !jsInfo->IsExternal()) { + // The JavaScript instance has been forcefully disconnected from the Java instance. + po->Reset(); + return; + } + + auto external = jsInfo.As(); + auto jsInstanceInfo = static_cast(external->Value()); + auto javaObjectID = jsInstanceInfo->JavaObjectID; + + jboolean isJavaInstanceAlive = m_env.CallBooleanMethod(m_javaRuntimeObject, MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID, javaObjectID); + if (isJavaInstanceAlive) { + // If the Java instance is alive, keep the JavaScript instance alive. + // TODO: Check should we really register the finalizer again? + po->SetWeak(callbackState, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer); + } else { + // If the Java instance is dead, this JavaScript instance can be let die. + delete jsInstanceInfo; + jsInstance->SetInternalField(jsInfoIdx, Undefined(m_isolate)); + po->Reset(); + } +} + /* * When JS GC happens change state of the java counterpart to mirror state of JS object and REVIVE the JS object unconditionally * "Regular" js objects are pushed into the "regular objects" array diff --git a/runtime/src/main/jni/ObjectManager.h b/runtime/src/main/jni/ObjectManager.h index b9b0f3d00..0c5db7526 100644 --- a/runtime/src/main/jni/ObjectManager.h +++ b/runtime/src/main/jni/ObjectManager.h @@ -57,6 +57,18 @@ class ObjectManager { END }; + enum class JavaScriptMarkingMode { + /** + * For JavaScript instances with implementation objects that were marked for collection, + * MarkReachableObjects will scann the whole graph of reachable objects and keep strong reference to + * the Java instances of implementation objects. + */ + Full, + /** + * Fully suppress the MarkReachableObjects. + */ + None + }; private: @@ -142,8 +154,12 @@ class ObjectManager { static void JSObjectWeakCallbackStatic(const v8::WeakCallbackInfo& data); + static void JSObjectFinalizerStatic(const v8::WeakCallbackInfo& data); + void JSObjectWeakCallback(v8::Isolate* isolate, ObjectWeakCallbackState* callbackState); + void JSObjectFinalizer(v8::Isolate* isolate, ObjectWeakCallbackState* callbackState); + bool HasImplObject(v8::Isolate* isolate, const v8::Local& obj); void MarkReachableObjects(v8::Isolate* isolate, const v8::Local& obj); @@ -196,6 +212,8 @@ class ObjectManager { bool m_useGlobalRefs; + JavaScriptMarkingMode m_markingMode; + jclass JAVA_LANG_CLASS; jmethodID GET_NAME_METHOD_ID; @@ -206,6 +224,8 @@ class ObjectManager { jmethodID MAKE_INSTANCE_WEAK_BATCH_METHOD_ID; + jmethodID MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID; + jmethodID CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID; v8::Persistent* m_poJsWrapperFunc; diff --git a/test-app/app/src/main/assets/app/package.json b/test-app/app/src/main/assets/app/package.json index 37d761fcb..a9e6c65c3 100644 --- a/test-app/app/src/main/assets/app/package.json +++ b/test-app/app/src/main/assets/app/package.json @@ -5,6 +5,7 @@ "profilerOutputDir": "", "gcThrottleTime": 500, "memoryCheckInterval": 10, - "freeMemoryRatio": 0.50 + "freeMemoryRatio": 0.50, + "markingMode": "full" } } \ No newline at end of file From 052b28eac00983f0e7ace768538a7a5364d1a2aa Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Thu, 24 Aug 2017 15:08:28 +0300 Subject: [PATCH 2/3] Apply some refactoring after PR reviews --- .gitignore | 2 + runtime/src/main/java/com/tns/AppConfig.java | 68 ++++++---------- .../src/main/java/com/tns/MarkingMode.java | 9 +++ runtime/src/main/java/com/tns/Runtime.java | 12 +-- runtime/src/main/jni/ObjectManager.cpp | 80 +++++++------------ runtime/src/main/jni/ObjectManager.h | 9 ++- 6 files changed, 79 insertions(+), 101 deletions(-) create mode 100644 runtime/src/main/java/com/tns/MarkingMode.java diff --git a/.gitignore b/.gitignore index 98b1827b7..bf94681b7 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ bin/ .project .DS_Store .settings + +build-artifacts/ \ No newline at end of file diff --git a/runtime/src/main/java/com/tns/AppConfig.java b/runtime/src/main/java/com/tns/AppConfig.java index 51e3359e9..09f32c5d6 100644 --- a/runtime/src/main/java/com/tns/AppConfig.java +++ b/runtime/src/main/java/com/tns/AppConfig.java @@ -18,20 +18,7 @@ private enum KnownKeys { MemoryCheckInterval("memoryCheckInterval", 0), FreeMemoryRatio("freeMemoryRatio", 0.0), Profiling("profiling", ""), - MarkingMode("markingMode", "Full"); - - public static final KnownKeys[] asArray = { - V8FlagsKey, - CodeCacheKey, - HeapSnapshotScriptKey, - SnapshotFile, - ProfilerOutputDirKey, - GcThrottleTime, - MemoryCheckInterval, - FreeMemoryRatio, - Profiling, - MarkingMode - }; + MarkingMode("markingMode", com.tns.MarkingMode.values()[0]); private final String name; private final Object defaultValue; @@ -44,19 +31,9 @@ private enum KnownKeys { public String getName() { return name; } - public Object getDefaultValue() { return defaultValue; } - - int getIndex() { - for (int i=0; i(markingMode); } void ObjectManager::SetInstanceIsolate(Isolate* isolate) { @@ -99,32 +94,35 @@ JniLocalRef ObjectManager::GetJavaObjectByJsObject(const Local& object) ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfo(const Local& object) { JSInstanceInfo* jsInstanceInfo = nullptr; + if (IsJsRuntimeObject(object)) { + return GetJSInstanceInfoFromRuntimeObject(object); + } + return nullptr; +} - auto isolate = m_isolate; - HandleScope handleScope(isolate); +ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfoFromRuntimeObject(const Local& object) { + HandleScope handleScope(m_isolate); - if (IsJsRuntimeObject(object)) { - const int jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); - auto jsInfo = object->GetInternalField(jsInfoIdx); - if (jsInfo->IsUndefined()) { - //Typescript object layout has an object instance as child of the actual registered instance. checking for that - auto prototypeObject = object->GetPrototype().As(); - - if (!prototypeObject.IsEmpty() && prototypeObject->IsObject()) { - DEBUG_WRITE("GetJSInstanceInfo: need to check prototype :%d", prototypeObject->GetIdentityHash()); - if (IsJsRuntimeObject(prototypeObject)) { - jsInfo = prototypeObject->GetInternalField(jsInfoIdx); - } + const int jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); + auto jsInfo = object->GetInternalField(jsInfoIdx); + if (jsInfo->IsUndefined()) { + //Typescript object layout has an object instance as child of the actual registered instance. checking for that + auto prototypeObject = object->GetPrototype().As(); + + if (!prototypeObject.IsEmpty() && prototypeObject->IsObject()) { + DEBUG_WRITE("GetJSInstanceInfo: need to check prototype :%d", prototypeObject->GetIdentityHash()); + if (IsJsRuntimeObject(prototypeObject)) { + jsInfo = prototypeObject->GetInternalField(jsInfoIdx); } } + } - if (!jsInfo.IsEmpty() && jsInfo->IsExternal()) { - auto external = jsInfo.As(); - jsInstanceInfo = static_cast(external->Value()); - } + if (!jsInfo.IsEmpty() && jsInfo->IsExternal()) { + auto external = jsInfo.As(); + return static_cast(external->Value()); } - return jsInstanceInfo; + return nullptr; } bool ObjectManager::IsJsRuntimeObject(const v8::Local& object) { @@ -297,41 +295,25 @@ void ObjectManager::JSObjectFinalizerStatic(const WeakCallbackInfo* po = callbackState->target; + auto jsInstanceInfo = GetJSInstanceInfoFromRuntimeObject(po->Get(m_isolate)); - auto jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); - auto jsInstance = po->Get(m_isolate); - auto jsInfo = jsInstance->GetInternalField(jsInfoIdx); - if (jsInfo->IsUndefined()) { - // Typescript object layout has an object instance as child of the actual registered instance. checking for that - auto prototypeObject = jsInstance->GetPrototype().As(); - if (!prototypeObject.IsEmpty() && prototypeObject->IsObject()) { - DEBUG_WRITE("GetJSInstanceInfo: need to check prototype :%d", prototypeObject->GetIdentityHash()); - if (IsJsRuntimeObject(prototypeObject)) { - jsInfo = prototypeObject->GetInternalField(jsInfoIdx); - } - } - } - - if (jsInfo.IsEmpty() || !jsInfo->IsExternal()) { - // The JavaScript instance has been forcefully disconnected from the Java instance. + if (!jsInstanceInfo) { po->Reset(); return; } - auto external = jsInfo.As(); - auto jsInstanceInfo = static_cast(external->Value()); auto javaObjectID = jsInstanceInfo->JavaObjectID; - jboolean isJavaInstanceAlive = m_env.CallBooleanMethod(m_javaRuntimeObject, MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID, javaObjectID); if (isJavaInstanceAlive) { // If the Java instance is alive, keep the JavaScript instance alive. - // TODO: Check should we really register the finalizer again? po->SetWeak(callbackState, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer); } else { // If the Java instance is dead, this JavaScript instance can be let die. delete jsInstanceInfo; - jsInstance->SetInternalField(jsInfoIdx, Undefined(m_isolate)); + auto jsInfoIdx = static_cast(MetadataNodeKeys::JsInfo); + po->Get(m_isolate)->SetInternalField(jsInfoIdx, Undefined(m_isolate)); po->Reset(); } } diff --git a/runtime/src/main/jni/ObjectManager.h b/runtime/src/main/jni/ObjectManager.h index 0c5db7526..41787a073 100644 --- a/runtime/src/main/jni/ObjectManager.h +++ b/runtime/src/main/jni/ObjectManager.h @@ -57,10 +57,13 @@ class ObjectManager { END }; - enum class JavaScriptMarkingMode { + /** + * Memory management modes. Keep the members in sync with the java/com/tns/MarkingMode. + */ + enum JavaScriptMarkingMode { /** * For JavaScript instances with implementation objects that were marked for collection, - * MarkReachableObjects will scann the whole graph of reachable objects and keep strong reference to + * MarkReachableObjects will scan the whole graph of reachable objects and keep strong reference to * the Java instances of implementation objects. */ Full, @@ -140,6 +143,8 @@ class ObjectManager { JSInstanceInfo* GetJSInstanceInfo(const v8::Local& object); + JSInstanceInfo* GetJSInstanceInfoFromRuntimeObject(const v8::Local& object); + void ReleaseJSInstance(v8::Persistent* po, JSInstanceInfo* jsInstanceInfo); void ReleaseRegularObjects(); From 1708cbab1edf35eb96ecfa5502870200d788c6f1 Mon Sep 17 00:00:00 2001 From: Panayot Cankov Date: Fri, 25 Aug 2017 12:14:00 +0300 Subject: [PATCH 3/3] Addressed some comments in PR review --- runtime/src/main/java/com/tns/AppConfig.java | 18 ++++++++++-------- runtime/src/main/java/com/tns/Runtime.java | 2 +- runtime/src/main/jni/ObjectManager.cpp | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/runtime/src/main/java/com/tns/AppConfig.java b/runtime/src/main/java/com/tns/AppConfig.java index 09f32c5d6..3c342fac7 100644 --- a/runtime/src/main/java/com/tns/AppConfig.java +++ b/runtime/src/main/java/com/tns/AppConfig.java @@ -1,14 +1,12 @@ package com.tns; import java.io.File; - import org.json.JSONObject; - import android.os.Build; import android.util.Log; class AppConfig { - private enum KnownKeys { + protected enum KnownKeys { V8FlagsKey("v8Flags", "--expose_gc"), CodeCacheKey("codeCache", false), HeapSnapshotScriptKey("heapSnapshotScript", ""), @@ -18,7 +16,7 @@ private enum KnownKeys { MemoryCheckInterval("memoryCheckInterval", 0), FreeMemoryRatio("freeMemoryRatio", 0.0), Profiling("profiling", ""), - MarkingMode("markingMode", com.tns.MarkingMode.values()[0]); + MarkingMode("markingMode", com.tns.MarkingMode.full); private final String name; private final Object defaultValue; @@ -52,7 +50,7 @@ public AppConfig(File appDir) { try { rootObject = FileSystem.readJSONFile(packageInfo); if (rootObject != null) { - if (rootObject.has(KnownKeys.Profiling.name())) { + if (rootObject.has(KnownKeys.Profiling.getName())) { String profiling = rootObject.getString(KnownKeys.Profiling.getName()); values[KnownKeys.Profiling.ordinal()] = profiling; } @@ -92,9 +90,12 @@ public AppConfig(File appDir) { } if (androidObject.has(KnownKeys.MarkingMode.getName())) { try { - String value = androidObject.getString(KnownKeys.MarkingMode.getName()); - values[KnownKeys.MarkingMode.ordinal()] = MarkingMode.valueOf(value); - } catch(Throwable e) { + String markingModeString = androidObject.getString(KnownKeys.MarkingMode.getName()); + MarkingMode markingMode = MarkingMode.valueOf(markingModeString); + values[KnownKeys.MarkingMode.ordinal()] = markingMode; + } catch(Exception e) { + e.printStackTrace(); + Log.v("JS", "Failed to parse marking mode. The default " + ((MarkingMode)KnownKeys.MarkingMode.getDefaultValue()).name() + " will be used."); } } } @@ -131,5 +132,6 @@ public double getFreeMemoryRatio() { public String getProfilingMode() { return (String)values[KnownKeys.Profiling.ordinal()]; } + public MarkingMode getMarkingMode() { return (MarkingMode)values[KnownKeys.MarkingMode.ordinal()]; } } diff --git a/runtime/src/main/java/com/tns/Runtime.java b/runtime/src/main/java/com/tns/Runtime.java index 9287e3d8c..e4651ef67 100644 --- a/runtime/src/main/java/com/tns/Runtime.java +++ b/runtime/src/main/java/com/tns/Runtime.java @@ -207,7 +207,7 @@ public int getMarkingModeOrdinal() { if (staticConfiguration != null && staticConfiguration.appConfig != null) { return staticConfiguration.appConfig.getMarkingMode().ordinal(); } else { - return MarkingMode.values()[0].ordinal(); + return ((MarkingMode)AppConfig.KnownKeys.MarkingMode.getDefaultValue()).ordinal(); } } diff --git a/runtime/src/main/jni/ObjectManager.cpp b/runtime/src/main/jni/ObjectManager.cpp index 0744a4fa2..774917104 100644 --- a/runtime/src/main/jni/ObjectManager.cpp +++ b/runtime/src/main/jni/ObjectManager.cpp @@ -299,7 +299,7 @@ void ObjectManager::JSObjectFinalizer(Isolate* isolate, ObjectWeakCallbackState* Persistent* po = callbackState->target; auto jsInstanceInfo = GetJSInstanceInfoFromRuntimeObject(po->Get(m_isolate)); - if (!jsInstanceInfo) { + if (jsInstanceInfo == nullptr) { po->Reset(); return; }