@@ -17,8 +17,13 @@ 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+
2227 auto runtimeClass = m_env.FindClass (" com/tns/Runtime" );
2328 assert (runtimeClass != nullptr );
2429
@@ -31,6 +36,9 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
3136 MAKE_INSTANCE_WEAK_BATCH_METHOD_ID = m_env.GetMethodID (runtimeClass, " makeInstanceWeak" , " (Ljava/nio/ByteBuffer;IZ)V" );
3237 assert (MAKE_INSTANCE_WEAK_BATCH_METHOD_ID != nullptr );
3338
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+
3442 CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID = m_env.GetMethodID (runtimeClass, " checkWeakObjectAreAlive" , " (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)V" );
3543 assert (CHECK_WEAK_OBJECTS_ARE_ALIVE_METHOD_ID != nullptr );
3644
@@ -45,6 +53,10 @@ ObjectManager::ObjectManager(jobject javaRuntimeObject)
4553
4654 auto useGlobalRefs = m_env.CallStaticBooleanMethod (runtimeClass, useGlobalRefsMethodID);
4755 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);
4860}
4961
5062void ObjectManager::SetInstanceIsolate (Isolate* isolate) {
@@ -57,8 +69,10 @@ void ObjectManager::Init(Isolate* isolate) {
5769 auto jsWrapperFunc = jsWrapperFuncTemplate->GetFunction ();
5870 m_poJsWrapperFunc = new Persistent<Function>(isolate, jsWrapperFunc);
5971
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+ }
6276}
6377
6478
@@ -80,32 +94,35 @@ JniLocalRef ObjectManager::GetJavaObjectByJsObject(const Local<Object>& object)
8094
8195ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfo (const Local<Object>& object) {
8296 JSInstanceInfo* jsInstanceInfo = nullptr ;
97+ if (IsJsRuntimeObject (object)) {
98+ return GetJSInstanceInfoFromRuntimeObject (object);
99+ }
100+ return nullptr ;
101+ }
83102
84- auto isolate = m_isolate;
85- HandleScope handleScope (isolate );
103+ ObjectManager::JSInstanceInfo* ObjectManager::GetJSInstanceInfoFromRuntimeObject ( const Local<Object>& object) {
104+ HandleScope handleScope (m_isolate );
86105
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);
99116 }
100117 }
118+ }
101119
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 ());
106123 }
107124
108- return jsInstanceInfo ;
125+ return nullptr ;
109126}
110127
111128bool ObjectManager::IsJsRuntimeObject (const v8::Local<v8::Object>& object) {
@@ -211,7 +228,11 @@ void ObjectManager::Link(const Local<Object>& object, uint32_t javaObjectID, jcl
211228 auto state = new ObjectWeakCallbackState (this , jsInstanceInfo, objectHandle);
212229
213230 // 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+ }
215236
216237 auto jsInfoIdx = static_cast <int >(MetadataNodeKeys::JsInfo);
217238
@@ -263,6 +284,40 @@ void ObjectManager::JSObjectWeakCallbackStatic(const WeakCallbackInfo<ObjectWeak
263284 thisPtr->JSObjectWeakCallback (isolate, callbackState);
264285}
265286
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+
266321/*
267322 * When JS GC happens change state of the java counterpart to mirror state of JS object and REVIVE the JS object unconditionally
268323 * "Regular" js objects are pushed into the "regular objects" array
0 commit comments