@@ -17,8 +17,13 @@ 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
+
22
27
auto runtimeClass = m_env.FindClass (" com/tns/Runtime" );
23
28
assert (runtimeClass != nullptr );
24
29
@@ -31,6 +36,9 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
31
36
MAKE_INSTANCE_WEAK_BATCH_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeak" , " (Ljava/nio/ByteBuffer;IZ)V" );
32
37
assert (MAKE_INSTANCE_WEAK_BATCH_METHOD_ID != nullptr );
33
38
39
+ MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeakAndCheckIfAlive" , " (I)Z" );
40
+ assert (MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID != nullptr );
41
+
34
42
CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " checkWeakObjectAreAlive" , " (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)V" );
35
43
assert (CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID != nullptr );
36
44
@@ -45,6 +53,10 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
45
53
46
54
auto useGlobalRefs = m_env.CallStaticBooleanMethod (runtimeClass, useGlobalRefsMethodID);
47
55
m_useGlobalRefs = useGlobalRefs == JNI_TRUE;
56
+
57
+ auto getMarkingModeOrdinalMethodID = m_env.GetMethodID (runtimeClass, " getMarkingModeOrdinal" , " ()I" );
58
+ jint markingMode = m_env.CallIntMethod (m_javaRuntimeObject, getMarkingModeOrdinalMethodID);
59
+ m_markingMode = static_cast <JavaScriptMarkingMode>(markingMode);
48
60
}
49
61
50
62
void ObjectManager::SetInstanceIsolate (Isolate* isolate) {
@@ -57,8 +69,10 @@ void ObjectManager::Init(Isolate* isolate) {
57
69
auto jsWrapperFunc = jsWrapperFuncTemplate->GetFunction ();
58
70
m_poJsWrapperFunc = new Persistent<Function>(isolate, jsWrapperFunc);
59
71
60
- isolate->AddGCPrologueCallback (ObjectManager::OnGcStartedStatic, kGCTypeAll );
61
- isolate->AddGCEpilogueCallback (ObjectManager::OnGcFinishedStatic, kGCTypeAll );
72
+ if (m_markingMode != JavaScriptMarkingMode::None) {
73
+ isolate->AddGCPrologueCallback (ObjectManager::OnGcStartedStatic, kGCTypeAll );
74
+ isolate->AddGCEpilogueCallback (ObjectManager::OnGcFinishedStatic, kGCTypeAll );
75
+ }
62
76
}
63
77
64
78
@@ -80,32 +94,35 @@ JniLocalRef ObjectManager::GetJavaObjectByJsObject(const Local<Object>& object)
80
94
81
95
ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfo (const Local<Object>& object) {
82
96
JSInstanceInfo* jsInstanceInfo = nullptr ;
97
+ if (IsJsRuntimeObject (object)) {
98
+ return GetJSInstanceInfoFromRuntimeObject (object);
99
+ }
100
+ return nullptr ;
101
+ }
83
102
84
- auto isolate = m_isolate;
85
- HandleScope handleScope (isolate );
103
+ ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfoFromRuntimeObject ( const Local<Object>& object) {
104
+ HandleScope handleScope (m_isolate );
86
105
87
- if (IsJsRuntimeObject (object)) {
88
- const int jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
89
- auto jsInfo = object->GetInternalField (jsInfoIdx);
90
- if (jsInfo->IsUndefined ()) {
91
- // Typescript object layout has an object instance as child of the actual registered instance. checking for that
92
- auto prototypeObject = object->GetPrototype ().As <Object>();
93
-
94
- if (!prototypeObject.IsEmpty () && prototypeObject->IsObject ()) {
95
- DEBUG_WRITE (" GetJSInstanceInfo: need to check prototype :%d" , prototypeObject->GetIdentityHash ());
96
- if (IsJsRuntimeObject (prototypeObject)) {
97
- jsInfo = prototypeObject->GetInternalField (jsInfoIdx);
98
- }
106
+ const int jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
107
+ auto jsInfo = object->GetInternalField (jsInfoIdx);
108
+ if (jsInfo->IsUndefined ()) {
109
+ // Typescript object layout has an object instance as child of the actual registered instance. checking for that
110
+ auto prototypeObject = object->GetPrototype ().As <Object>();
111
+
112
+ if (!prototypeObject.IsEmpty () && prototypeObject->IsObject ()) {
113
+ DEBUG_WRITE (" GetJSInstanceInfo: need to check prototype :%d" , prototypeObject->GetIdentityHash ());
114
+ if (IsJsRuntimeObject (prototypeObject)) {
115
+ jsInfo = prototypeObject->GetInternalField (jsInfoIdx);
99
116
}
100
117
}
118
+ }
101
119
102
- if (!jsInfo.IsEmpty () && jsInfo->IsExternal ()) {
103
- auto external = jsInfo.As <External>();
104
- jsInstanceInfo = static_cast <JSInstanceInfo*>(external->Value ());
105
- }
120
+ if (!jsInfo.IsEmpty () && jsInfo->IsExternal ()) {
121
+ auto external = jsInfo.As <External>();
122
+ return static_cast <JSInstanceInfo*>(external->Value ());
106
123
}
107
124
108
- return jsInstanceInfo ;
125
+ return nullptr ;
109
126
}
110
127
111
128
bool ObjectManager::IsJsRuntimeObject (const v8::Local<v8::Object>& object) {
@@ -211,7 +228,11 @@ void ObjectManager::Link(const Local<Object>& object, uint32_t javaObjectID, jcl
211
228
auto state = new ObjectWeakCallbackState (this , jsInstanceInfo, objectHandle);
212
229
213
230
// subscribe for JS GC event
214
- objectHandle->SetWeak (state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer );
231
+ if (m_markingMode == JavaScriptMarkingMode::None) {
232
+ objectHandle->SetWeak (state, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer );
233
+ } else {
234
+ objectHandle->SetWeak (state, JSObjectWeakCallbackStatic, WeakCallbackType::kFinalizer );
235
+ }
215
236
216
237
auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
217
238
@@ -263,6 +284,40 @@ void ObjectManager::JSObjectWeakCallbackStatic(const WeakCallbackInfo<ObjectWeak
263
284
thisPtr->JSObjectWeakCallback (isolate, callbackState);
264
285
}
265
286
287
+ void ObjectManager::JSObjectFinalizerStatic (const WeakCallbackInfo<ObjectWeakCallbackState>& data) {
288
+ ObjectWeakCallbackState* callbackState = data.GetParameter ();
289
+
290
+ ObjectManager* thisPtr = callbackState->thisPtr ;
291
+
292
+ auto isolate = data.GetIsolate ();
293
+
294
+ thisPtr->JSObjectFinalizer (isolate, callbackState);
295
+ }
296
+
297
+ void ObjectManager::JSObjectFinalizer (Isolate* isolate, ObjectWeakCallbackState* callbackState) {
298
+ HandleScope handleScope (m_isolate);
299
+ Persistent<Object>* po = callbackState->target ;
300
+ auto jsInstanceInfo = GetJSInstanceInfoFromRuntimeObject (po->Get (m_isolate));
301
+
302
+ if (jsInstanceInfo == nullptr ) {
303
+ po->Reset ();
304
+ return ;
305
+ }
306
+
307
+ auto javaObjectID = jsInstanceInfo->JavaObjectID ;
308
+ jboolean isJavaInstanceAlive = m_env.CallBooleanMethod (m_javaRuntimeObject, MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID, javaObjectID);
309
+ if (isJavaInstanceAlive) {
310
+ // If the Java instance is alive, keep the JavaScript instance alive.
311
+ po->SetWeak (callbackState, JSObjectFinalizerStatic, WeakCallbackType::kFinalizer );
312
+ } else {
313
+ // If the Java instance is dead, this JavaScript instance can be let die.
314
+ delete jsInstanceInfo;
315
+ auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
316
+ po->Get (m_isolate)->SetInternalField (jsInfoIdx, Undefined (m_isolate));
317
+ po->Reset ();
318
+ }
319
+ }
320
+
266
321
/*
267
322
* When JS GC happens change state of the java counterpart to mirror state of JS object and REVIVE the JS object unconditionally
268
323
* "Regular" js objects are pushed into the "regular objects" array
0 commit comments