@@ -30,12 +30,16 @@ using namespace xamarin::android;
30
30
31
31
typedef struct MonoJavaGCBridgeInfo {
32
32
MonoClass *klass;
33
- MonoClassField *handle;
34
- MonoClassField *handle_type;
35
- MonoClassField *refs_added;
36
- MonoClassField *weak_handle;
33
+ MonoClassField *jniObjectReferenceControlBlock;
37
34
} MonoJavaGCBridgeInfo;
38
35
36
+ typedef struct JniObjectReferenceControlBlock {
37
+ jobject handle;
38
+ int handle_type;
39
+ jobject weak_handle;
40
+ int refs_added;
41
+ } JniObjectReferenceControlBlock;
42
+
39
43
#define NUM_GC_BRIDGE_TYPES (4 )
40
44
41
45
struct JavaInteropGCBridge {
@@ -366,13 +370,10 @@ java_interop_gc_bridge_register_bridgeable_type (
366
370
MonoJavaGCBridgeInfo *info = &bridge->mono_java_gc_bridge_info [i];
367
371
368
372
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" ));
373
373
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 )
376
377
return -1 ;
377
378
bridge->num_bridge_types ++;
378
379
return 0 ;
@@ -780,6 +781,18 @@ get_gc_bridge_info_for_object (JavaInteropGCBridge *bridge, MonoObject *object)
780
781
return get_gc_bridge_info_for_class (bridge, mono_object_get_class (object));
781
782
}
782
783
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
+
783
796
typedef mono_bool (*MonodroidGCTakeRefFunc) (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id);
784
797
785
798
static MonodroidGCTakeRefFunc take_global_ref;
@@ -788,12 +801,11 @@ static MonodroidGCTakeRefFunc take_weak_global_ref;
788
801
static mono_bool
789
802
take_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
790
803
{
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 )
793
806
return 0 ;
794
807
795
- jobject weak;
796
- mono_field_get_value (obj, bridge_info->weak_handle , &weak);
808
+ jobject weak = control_block->weak_handle ;
797
809
798
810
jobject handle = env->CallObjectMethod (weak, bridge->WeakReference_get );
799
811
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,
808
820
java_interop_gc_bridge_weak_gref_log_delete (bridge, weak, get_object_ref_type (env, weak), thread_name, thread_id, " take_global_ref_java" );
809
821
env->DeleteGlobalRef (weak);
810
822
weak = NULL ;
811
- mono_field_set_value (obj, bridge_info->weak_handle , &weak);
812
823
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;
817
827
818
828
return handle != NULL ;
819
829
}
820
830
821
831
static mono_bool
822
832
take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
823
833
{
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 )
826
836
return 0 ;
827
837
828
- jobject handle;
829
- mono_field_get_value (obj, bridge_info->handle , &handle);
838
+ jobject handle = control_block->handle ;
830
839
831
840
jobject weaklocal = env->NewObject (bridge->WeakReference_class , bridge->WeakReference_init , handle);
832
841
jobject weakglobal = env->NewGlobalRef (weaklocal);
@@ -838,22 +847,20 @@ take_weak_global_ref_java (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject
838
847
839
848
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" );
840
849
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;
843
852
844
853
return 1 ;
845
854
}
846
855
847
856
static mono_bool
848
857
take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
849
858
{
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 )
852
861
return 0 ;
853
862
854
- jobject weak;
855
- mono_field_get_value (obj, bridge_info->handle , &weak);
856
-
863
+ jobject weak = control_block->handle ;
857
864
jobject handle = env->NewGlobalRef (weak);
858
865
log_gref (bridge, " *try_take_global obj=%p -> wref=%p handle=%p\n " , obj, weak, handle);
859
866
@@ -868,22 +875,20 @@ take_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj,
868
875
thread_name, thread_id, " take_global_ref_jni" );
869
876
env->DeleteWeakGlobalRef (weak);
870
877
871
- mono_field_set_value (obj, bridge_info->handle , &handle);
878
+ control_block->handle = handle;
879
+ control_block->handle_type = JNIGlobalRefType;
872
880
873
- int type = JNIGlobalRefType;
874
- mono_field_set_value (obj, bridge_info->handle_type , &type);
875
881
return handle != NULL ;
876
882
}
877
883
878
884
static mono_bool
879
885
take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *obj, const char *thread_name, int64_t thread_id)
880
886
{
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 )
883
889
return 0 ;
884
890
885
- jobject handle;
886
- mono_field_get_value (obj, bridge_info->handle , &handle);
891
+ jobject handle = control_block->handle ;
887
892
888
893
log_gref (bridge, " *take_weak obj=%p; handle=%p\n " , obj, handle);
889
894
@@ -896,10 +901,8 @@ take_weak_global_ref_jni (JavaInteropGCBridge *bridge, JNIEnv *env, MonoObject *
896
901
thread_name, thread_id, " take_weak_global_ref_jni" );
897
902
env->DeleteGlobalRef (handle);
898
903
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;
903
906
904
907
return 1 ;
905
908
}
@@ -921,17 +924,18 @@ get_add_reference_method (JavaInteropGCBridge *bridge, JNIEnv *env, jobject obj,
921
924
}
922
925
923
926
static 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)
925
928
{
926
929
MonoClass *klass = mono_object_get_class (obj);
927
930
928
- jobject handle;
929
- mono_field_get_value (obj, bridge_info->handle , &handle);
931
+ jobject handle = control_block->handle ;
930
932
931
933
jmethodID add_method_id = get_add_reference_method (bridge, env, handle, klass);
932
934
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 ;
935
939
env->CallVoidMethod (handle, add_method_id, reffed_handle);
936
940
#if DEBUG
937
941
if (bridge->gref_log_level > 1 )
@@ -979,28 +983,30 @@ gc_prepare_for_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int nu
979
983
/* add java refs for items on the list which reference each other */
980
984
for (int i = 0 ; i < num_sccs; i++) {
981
985
MonoGCBridgeSCC *scc = sccs [i];
982
- MonoJavaGCBridgeInfo *bridge_info = NULL ;
986
+
987
+ JniObjectReferenceControlBlock *control_block = NULL ;
988
+
983
989
/* start at the second item, ref j from j-1 */
984
990
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;
988
994
}
989
995
}
990
996
/* ref the first from the last */
991
997
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;
995
1001
}
996
1002
}
997
1003
}
998
1004
999
1005
/* add the cross scc refs */
1000
1006
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;
1004
1010
}
1005
1011
}
1006
1012
@@ -1041,19 +1047,18 @@ gc_cleanup_after_java_collection (JavaInteropGCBridge *bridge, JNIEnv *env, int
1041
1047
sccs [i]->is_alive = 0 ;
1042
1048
for (int j = 0 ; j < sccs [i]->num_objs ; j++) {
1043
1049
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 )
1046
1053
continue ;
1047
1054
1048
- jobject jref;
1049
- mono_field_get_value (obj, bridge_info->handle , &jref);
1055
+ jobject jref = control_block->handle ;
1050
1056
if (jref) {
1051
1057
alive++;
1052
1058
if (j > 0 )
1053
1059
assert (sccs [i]->is_alive );
1054
1060
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 ;
1057
1062
if (refs_added) {
1058
1063
jmethodID clear_method_id = get_clear_references_method (bridge, env, jref);
1059
1064
if (clear_method_id) {
@@ -1201,13 +1206,12 @@ gc_bridge_class_kind (MonoClass *klass)
1201
1206
static mono_bool
1202
1207
gc_is_bridge_object (MonoObject *object)
1203
1208
{
1204
- void *handle;
1205
1209
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 ;;
1209
1213
1210
- mono_field_get_value (object, bridge_info ->handle , &handle) ;
1214
+ void *handle = control_block ->handle ;
1211
1215
if (handle == NULL ) {
1212
1216
#if DEBUG
1213
1217
MonoClass *mclass = mono_object_get_class (object);
0 commit comments