@@ -17,8 +17,14 @@ using namespace v8;
1717using namespace std ;
1818using namespace tns ;
1919
20- ObjectManager::ObjectManager (jobject javaRuntimeObject)
21- : m_javaRuntimeObject(javaRuntimeObject), m_env(JEnv()), m_numberOfGC(0 ), m_currentObjectId(0 ), m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000 , this ) {
20+ ObjectManager::ObjectManager (jobject javaRuntimeObject) :
21+ m_javaRuntimeObject(javaRuntimeObject),
22+ m_env(JEnv()),
23+ m_numberOfGC(0 ),
24+ m_currentObjectId(0 ),
25+ m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000 , this ),
26+ m_markingMode(JavaScriptMarkingMode::Full) {
27+
2228 auto runtimeClass = m_env.FindClass (" com/tns/Runtime" );
2329 assert (runtimeClass != nullptr );
2430
@@ -31,6 +37,9 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
3137 MAKE_INSTANCE_WEAK_BATCH_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeak" , " (Ljava/nio/ByteBuffer;IZ)V" );
3238 assert (MAKE_INSTANCE_WEAK_BATCH_METHOD_ID != nullptr );
3339
40+ MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeakAndCheckIfAlive" , " (I)Z" );
41+ assert (MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID != nullptr );
42+
3443 CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " checkWeakObjectAreAlive" , " (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)V" );
3544 assert (CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID != nullptr );
3645
@@ -45,6 +54,14 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
4554
4655 auto useGlobalRefs = m_env.CallStaticBooleanMethod (runtimeClass, useGlobalRefsMethodID);
4756 m_useGlobalRefs = useGlobalRefs == JNI_TRUE;
57+
58+ auto getMarkingModeMethodID = m_env.GetMethodID (runtimeClass, " getMarkingMode" , " ()I" );
59+ jint markingMode = m_env.CallIntMethod (m_javaRuntimeObject, getMarkingModeMethodID);
60+ switch (markingMode) {
61+ case 1 :
62+ m_markingMode = JavaScriptMarkingMode::None;
63+ break ;
64+ }
4865}
4966
5067void ObjectManager::SetInstanceIsolate (Isolate* isolate) {
@@ -57,8 +74,10 @@ void ObjectManager::Init(Isolate* isolate) {
5774 auto jsWrapperFunc = jsWrapperFuncTemplate->GetFunction ();
5875 m_poJsWrapperFunc = new Persistent<Function>(isolate, jsWrapperFunc);
5976
60- isolate->AddGCPrologueCallback (ObjectManager::OnGcStartedStatic, kGCTypeAll );
61- isolate->AddGCEpilogueCallback (ObjectManager::OnGcFinishedStatic, kGCTypeAll );
77+ if (m_markingMode != JavaScriptMarkingMode::None) {
78+ isolate->AddGCPrologueCallback (ObjectManager::OnGcStartedStatic, kGCTypeAll );
79+ isolate->AddGCEpilogueCallback (ObjectManager::OnGcFinishedStatic, kGCTypeAll );
80+ }
6281}
6382
6483
@@ -211,7 +230,11 @@ void ObjectManager::Link(const Local<Object>& object, uint32_t javaObjectID, jcl
211230 auto state = new ObjectWeakCallbackState (this , jsInstanceInfo, objectHandle);
212231
213232 // subscribe for JS GC event
214- objectHandle->SetWeak (state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer );
233+ if (m_markingMode == JavaScriptMarkingMode::None) {
234+ objectHandle->SetWeak (state, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer );
235+ } else {
236+ objectHandle->SetWeak (state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer );
237+ }
215238
216239 auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
217240
@@ -263,6 +286,56 @@ void ObjectManager::JSObjectWeakCallbackStatic(const WeakCallbackInfo<ObjectWeak
263286 thisPtr->JSObjectWeakCallback (isolate, callbackState);
264287}
265288
289+ void ObjectManager::JSObjectFinalizerStatic (const WeakCallbackInfo<ObjectWeakCallbackState>& data) {
290+ ObjectWeakCallbackState* callbackState = data.GetParameter ();
291+
292+ ObjectManager* thisPtr = callbackState->thisPtr ;
293+
294+ auto isolate = data.GetIsolate ();
295+
296+ thisPtr->JSObjectFinalizer (isolate, callbackState);
297+ }
298+
299+ void ObjectManager::JSObjectFinalizer (Isolate* isolate, ObjectWeakCallbackState* callbackState) {
300+ Persistent<Object>* po = callbackState->target ;
301+
302+ auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
303+ auto jsInstance = po->Get (m_isolate);
304+ auto jsInfo = jsInstance->GetInternalField (jsInfoIdx);
305+ if (jsInfo->IsUndefined ()) {
306+ // Typescript object layout has an object instance as child of the actual registered instance. checking for that
307+ auto prototypeObject = jsInstance->GetPrototype ().As <Object>();
308+ if (!prototypeObject.IsEmpty () && prototypeObject->IsObject ()) {
309+ DEBUG_WRITE (" GetJSInstanceInfo: need to check prototype :%d" , prototypeObject->GetIdentityHash ());
310+ if (IsJsRuntimeObject (prototypeObject)) {
311+ jsInfo = prototypeObject->GetInternalField (jsInfoIdx);
312+ }
313+ }
314+ }
315+
316+ if (jsInfo.IsEmpty () || !jsInfo->IsExternal ()) {
317+ // The JavaScript instance has been forcefully disconnected from the Java instance.
318+ po->Reset ();
319+ return ;
320+ }
321+
322+ auto external = jsInfo.As <External>();
323+ auto jsInstanceInfo = static_cast <JSInstanceInfo *>(external->Value ());
324+ auto javaObjectID = jsInstanceInfo->JavaObjectID ;
325+
326+ jboolean isJavaInstanceAlive = m_env.CallBooleanMethod (m_javaRuntimeObject, MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID, javaObjectID);
327+ if (isJavaInstanceAlive) {
328+ // If the Java instance is alive, keep the JavaScript instance alive.
329+ // TODO: Check should we really register the finalizer again?
330+ po->SetWeak (callbackState, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer );
331+ } else {
332+ // If the Java instance is dead, this JavaScript instance can be let die.
333+ delete jsInstanceInfo;
334+ jsInstance->SetInternalField (jsInfoIdx, Undefined (m_isolate));
335+ po->Reset ();
336+ }
337+ }
338+
266339/*
267340 * When JS GC happens change state of the java counterpart to mirror state of JS object and REVIVE the JS object unconditionally
268341 * "Regular" js objects are pushed into the "regular objects" array
0 commit comments