@@ -17,8 +17,14 @@ using namespace v8;
17
17
using namespace std ;
18
18
using namespace tns ;
19
19
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
+
22
28
auto runtimeClass = m_env.FindClass (" com/tns/Runtime" );
23
29
assert (runtimeClass != nullptr );
24
30
@@ -31,6 +37,9 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
31
37
MAKE_INSTANCE_WEAK_BATCH_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeak" , " (Ljava/nio/ByteBuffer;IZ)V" );
32
38
assert (MAKE_INSTANCE_WEAK_BATCH_METHOD_ID != nullptr );
33
39
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
+
34
43
CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " checkWeakObjectAreAlive" , " (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)V" );
35
44
assert (CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID != nullptr );
36
45
@@ -45,6 +54,14 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
45
54
46
55
auto useGlobalRefs = m_env.CallStaticBooleanMethod (runtimeClass, useGlobalRefsMethodID);
47
56
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
+ }
48
65
}
49
66
50
67
void ObjectManager::SetInstanceIsolate (Isolate* isolate) {
@@ -57,8 +74,10 @@ void ObjectManager::Init(Isolate* isolate) {
57
74
auto jsWrapperFunc = jsWrapperFuncTemplate->GetFunction ();
58
75
m_poJsWrapperFunc = new Persistent<Function>(isolate, jsWrapperFunc);
59
76
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
+ }
62
81
}
63
82
64
83
@@ -211,7 +230,11 @@ void ObjectManager::Link(const Local<Object>& object, uint32_t javaObjectID, jcl
211
230
auto state = new ObjectWeakCallbackState (this , jsInstanceInfo, objectHandle);
212
231
213
232
// 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
+ }
215
238
216
239
auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
217
240
@@ -263,6 +286,56 @@ void ObjectManager::JSObjectWeakCallbackStatic(const WeakCallbackInfo<ObjectWeak
263
286
thisPtr->JSObjectWeakCallback (isolate, callbackState);
264
287
}
265
288
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
+
266
339
/*
267
340
* When JS GC happens change state of the java counterpart to mirror state of JS object and REVIVE the JS object unconditionally
268
341
* "Regular" js objects are pushed into the "regular objects" array
0 commit comments