@@ -30,12 +30,16 @@ using namespace xamarin::android;
3030
3131typedef struct MonoJavaGCBridgeInfo {
3232 MonoClass *klass;
33- MonoClassField *handle;
34- MonoClassField *handle_type;
35- MonoClassField *refs_added;
36- MonoClassField *weak_handle;
33+ MonoClassField *jniObjectReferenceControlBlock;
3734} MonoJavaGCBridgeInfo;
3835
36+ typedef struct JniObjectReferenceControlBlock {
37+ jobject handle;
38+ int handle_type;
39+ jobject weak_handle;
40+ int refs_added;
41+ } JniObjectReferenceControlBlock;
42+
3943#define NUM_GC_BRIDGE_TYPES (4 )
4044
4145struct JavaInteropGCBridge {
@@ -366,13 +370,10 @@ java_interop_gc_bridge_register_bridgeable_type (
366370 MonoJavaGCBridgeInfo *info = &bridge->mono_java_gc_bridge_info [i];
367371
368372 info->klass = mono_class_from_mono_type (type);
369- info->handle = mono_class_get_field_from_name (info->klass , const_cast <char *> (" handle" ));
370- info->handle_type = mono_class_get_field_from_name (info->klass , const_cast <char *> (" handle_type" ));
371- info->refs_added = mono_class_get_field_from_name (info->klass , const_cast <char *> (" refs_added" ));
372- info->weak_handle = mono_class_get_field_from_name (info->klass , const_cast <char *> (" weak_handle" ));
373373
374- if (info->klass == NULL || info->handle == NULL || info->handle_type == NULL ||
375- info->refs_added == NULL || info->weak_handle == NULL )
374+ info->jniObjectReferenceControlBlock = mono_class_get_field_from_name (info->klass , const_cast <char *> (" jniObjectReferenceControlBlock" ));
375+
376+ if (info->klass == NULL || info->jniObjectReferenceControlBlock == NULL )
376377 return -1 ;
377378 bridge->num_bridge_types ++;
378379 return 0 ;
@@ -780,6 +781,18 @@ get_gc_bridge_info_for_object (JavaInteropGCBridge *bridge, MonoObject *object)
780781 return get_gc_bridge_info_for_class (bridge, mono_object_get_class (object));
781782}
782783
784+ static JniObjectReferenceControlBlock*
785+ get_gc_control_block_for_object (JavaInteropGCBridge *bridge, MonoObject *obj)
786+ {
787+ MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
788+ if (bridge_info == NULL )
789+ return NULL ;
790+
791+ JniObjectReferenceControlBlock *control_block;
792+ mono_field_get_value (obj, bridge_info->jniObjectReferenceControlBlock , &control_block);
793+ return control_block;
794+ }
795+
783796typedef mono_bool (*MonodroidGCTakeRefFunc) (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id);
784797
785798static MonodroidGCTakeRefFunc take_global_ref;
@@ -788,12 +801,11 @@ static MonodroidGCTakeRefFunc take_weak_global_ref;
788801static mono_bool
789802take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
790803{
791- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
792- if (bridge_info == NULL )
804+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
805+ if (control_block == NULL )
793806 return 0 ;
794807
795- jobject weak;
796- mono_field_get_value (obj, bridge_info->weak_handle , &weak);
808+ jobject weak = control_block->weak_handle ;
797809
798810 jobject handle = env->CallObjectMethod (weak, bridge->WeakReference_get );
799811 log_gref (bridge, " *try_take_global_2_1 obj=%p -> wref=%p handle=%p\n " , obj, weak, handle);
@@ -808,25 +820,22 @@ take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj,
808820 java_interop_gc_bridge_weak_gref_log_delete (bridge, weak, get_object_ref_type (env, weak), thread_name, thread_id, " take_global_ref_java" );
809821 env->DeleteGlobalRef (weak);
810822 weak = NULL ;
811- mono_field_set_value (obj, bridge_info->weak_handle , &weak);
812823
813- mono_field_set_value (obj, bridge_info->handle , &handle);
814-
815- int type = JNIGlobalRefType;
816- mono_field_set_value (obj, bridge_info->handle_type , &type);
824+ control_block->weak_handle = weak;
825+ control_block->handle = handle;
826+ control_block->handle_type = JNIGlobalRefType;
817827
818828 return handle != NULL ;
819829}
820830
821831static mono_bool
822832take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
823833{
824- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
825- if (bridge_info == NULL )
834+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
835+ if (control_block == NULL )
826836 return 0 ;
827837
828- jobject handle;
829- mono_field_get_value (obj, bridge_info->handle , &handle);
838+ jobject handle = control_block->handle ;
830839
831840 jobject weaklocal = env->NewObject (bridge->WeakReference_class , bridge->WeakReference_init , handle);
832841 jobject weakglobal = env->NewGlobalRef (weaklocal);
@@ -838,22 +847,20 @@ take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject
838847
839848 java_interop_gc_bridge_gref_log_delete (bridge, handle, get_object_ref_type (env, handle), thread_name, thread_id, " take_weak_global_ref_2_1_compat" );
840849 env->DeleteGlobalRef (handle);
841-
842- mono_field_set_value (obj, bridge_info ->weak_handle , & weakglobal) ;
850+ control_block-> handle = NULL ;
851+ control_block ->weak_handle = weakglobal;
843852
844853 return 1 ;
845854}
846855
847856static mono_bool
848857take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
849858{
850- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
851- if (bridge_info == NULL )
859+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
860+ if (control_block == NULL )
852861 return 0 ;
853862
854- jobject weak;
855- mono_field_get_value (obj, bridge_info->handle , &weak);
856-
863+ jobject weak = control_block->handle ;
857864 jobject handle = env->NewGlobalRef (weak);
858865 log_gref (bridge, " *try_take_global obj=%p -> wref=%p handle=%p\n " , obj, weak, handle);
859866
@@ -868,22 +875,20 @@ take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj,
868875 thread_name, thread_id, " take_global_ref_jni" );
869876 env->DeleteWeakGlobalRef (weak);
870877
871- mono_field_set_value (obj, bridge_info->handle , &handle);
878+ control_block->handle = handle;
879+ control_block->handle_type = JNIGlobalRefType;
872880
873- int type = JNIGlobalRefType;
874- mono_field_set_value (obj, bridge_info->handle_type , &type);
875881 return handle != NULL ;
876882}
877883
878884static mono_bool
879885take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
880886{
881- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
882- if (bridge_info == NULL )
887+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
888+ if (control_block == NULL )
883889 return 0 ;
884890
885- jobject handle;
886- mono_field_get_value (obj, bridge_info->handle , &handle);
891+ jobject handle = control_block->handle ;
887892
888893 log_gref (bridge, " *take_weak obj=%p; handle=%p\n " , obj, handle);
889894
@@ -896,10 +901,8 @@ take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *
896901 thread_name, thread_id, " take_weak_global_ref_jni" );
897902 env->DeleteGlobalRef (handle);
898903
899- mono_field_set_value (obj, bridge_info->handle , &weak);
900-
901- int type = JNIWeakGlobalRefType;
902- mono_field_set_value (obj, bridge_info->handle_type , &type);
904+ control_block->handle = weak;
905+ control_block->handle_type = JNIWeakGlobalRefType;
903906
904907 return 1 ;
905908}
@@ -921,17 +924,18 @@ get_add_reference_method (JavaInteropGCBridge *bridge, JNIEnv *env, jobject obj,
921924}
922925
923926static mono_bool
924- add_reference (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, MonoJavaGCBridgeInfo *bridge_info , MonoObject *reffed_obj)
927+ add_reference (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, JniObjectReferenceControlBlock *control_block , MonoObject *reffed_obj)
925928{
926929 MonoClass *klass = mono_object_get_class (obj);
927930
928- jobject handle;
929- mono_field_get_value (obj, bridge_info->handle , &handle);
931+ jobject handle = control_block->handle ;
930932
931933 jmethodID add_method_id = get_add_reference_method (bridge, env, handle, klass);
932934 if (add_method_id) {
933- jobject reffed_handle;
934- mono_field_get_value (reffed_obj, bridge_info->handle , &reffed_handle);
935+ JniObjectReferenceControlBlock *reffed_control_block = get_gc_control_block_for_object (bridge, reffed_obj);
936+ if (reffed_control_block == NULL )
937+ return 0 ;
938+ jobject reffed_handle = reffed_control_block->handle ;
935939 env->CallVoidMethod (handle, add_method_id, reffed_handle);
936940#if DEBUG
937941 if (bridge->gref_log_level > 1 )
@@ -979,28 +983,30 @@ gc_prepare_for_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int nu
979983 /* add java refs for items on the list which reference each other */
980984 for (int i = 0 ; i < num_sccs; i++) {
981985 MonoGCBridgeSCC *scc = sccs [i];
982- MonoJavaGCBridgeInfo *bridge_info = NULL ;
986+
987+ JniObjectReferenceControlBlock *control_block = NULL ;
988+
983989 /* start at the second item, ref j from j-1 */
984990 for (int j = 1 ; j < scc->num_objs ; j++) {
985- bridge_info = get_gc_bridge_info_for_object (bridge, scc->objs [j-1 ]);
986- if (bridge_info != NULL && add_reference (bridge, env, scc->objs [j-1 ], bridge_info , scc->objs [j])) {
987- mono_field_set_value (scc-> objs [j- 1 ], bridge_info-> refs_added , & ref_val) ;
991+ control_block = get_gc_control_block_for_object (bridge, scc->objs [j-1 ]);
992+ if (control_block != NULL && add_reference (bridge, env, scc->objs [j-1 ], control_block , scc->objs [j])) {
993+ control_block-> refs_added = ref_val;
988994 }
989995 }
990996 /* ref the first from the last */
991997 if (scc->num_objs > 1 ) {
992- bridge_info = get_gc_bridge_info_for_object (bridge, scc->objs [scc->num_objs -1 ]);
993- if (bridge_info != NULL && add_reference (bridge, env, scc->objs [scc->num_objs -1 ], bridge_info , scc->objs [0 ])) {
994- mono_field_set_value (scc-> objs [scc-> num_objs - 1 ], bridge_info-> refs_added , & ref_val) ;
998+ control_block = get_gc_control_block_for_object (bridge, scc->objs [scc->num_objs -1 ]);
999+ if (control_block != NULL && add_reference (bridge, env, scc->objs [scc->num_objs -1 ], control_block , scc->objs [0 ])) {
1000+ control_block-> refs_added = ref_val;
9951001 }
9961002 }
9971003 }
9981004
9991005 /* add the cross scc refs */
10001006 for (int i = 0 ; i < num_xrefs; i++) {
1001- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, sccs [xrefs [i].src_scc_index ]->objs [0 ]);
1002- if (bridge_info != NULL && add_reference (bridge, env, sccs [xrefs [i].src_scc_index ]->objs [0 ], bridge_info , sccs [xrefs [i].dst_scc_index ]->objs [0 ])) {
1003- mono_field_set_value (sccs [xrefs [i]. src_scc_index ]-> objs [ 0 ], bridge_info-> refs_added , & ref_val) ;
1007+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, sccs [xrefs [i].src_scc_index ]->objs [0 ]);
1008+ if (control_block != NULL && add_reference (bridge, env, sccs [xrefs [i].src_scc_index ]->objs [0 ], control_block , sccs [xrefs [i].dst_scc_index ]->objs [0 ])) {
1009+ control_block-> refs_added = ref_val;
10041010 }
10051011 }
10061012
@@ -1041,19 +1047,18 @@ gc_cleanup_after_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int
10411047 sccs [i]->is_alive = 0 ;
10421048 for (int j = 0 ; j < sccs [i]->num_objs ; j++) {
10431049 MonoObject *obj = sccs [i]->objs [j];
1044- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (bridge, obj);
1045- if (bridge_info == NULL )
1050+
1051+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (bridge, obj);
1052+ if (control_block == NULL )
10461053 continue ;
10471054
1048- jobject jref;
1049- mono_field_get_value (obj, bridge_info->handle , &jref);
1055+ jobject jref = control_block->handle ;
10501056 if (jref) {
10511057 alive++;
10521058 if (j > 0 )
10531059 assert (sccs [i]->is_alive );
10541060 sccs [i]->is_alive = 1 ;
1055- int refs_added;
1056- mono_field_get_value (obj, bridge_info->refs_added , &refs_added);
1061+ int refs_added = control_block->refs_added ;
10571062 if (refs_added) {
10581063 jmethodID clear_method_id = get_clear_references_method (bridge, env, jref);
10591064 if (clear_method_id) {
@@ -1201,13 +1206,12 @@ gc_bridge_class_kind (MonoClass *klass)
12011206static mono_bool
12021207gc_is_bridge_object (MonoObject *object)
12031208{
1204- void *handle;
12051209
1206- MonoJavaGCBridgeInfo *bridge_info = get_gc_bridge_info_for_object (mono_bridge, object);
1207- if (bridge_info == NULL )
1208- return 0 ;
1210+ JniObjectReferenceControlBlock *control_block = get_gc_control_block_for_object (mono_bridge, object);
1211+ if (control_block == NULL )
1212+ return 0 ;;
12091213
1210- mono_field_get_value (object, bridge_info ->handle , &handle) ;
1214+ void *handle = control_block ->handle ;
12111215 if (handle == NULL ) {
12121216#if DEBUG
12131217 MonoClass *mclass = mono_object_get_class (object);
0 commit comments