@@ -193,6 +193,7 @@ def test_native_class(self):
193
193
ID_OBJ11 = 9
194
194
ID_OBJ12 = 10
195
195
ID_OBJ13 = 11
196
+ ID_OBJ14 = 12
196
197
197
198
# don't rely on deterministic Java GC behavior by default on GraalPy
198
199
RELY_ON_GC = os .environ .get ("RELY_ON_GC" , not GRAALPY )
@@ -337,12 +338,16 @@ def assert_is_freed(id): pass
337
338
assert_is_alive (ID_OBJ1 )
338
339
339
340
del obj1
341
+ ####################################### GC #######################################
340
342
self ._trigger_gc ()
343
+ ##################################################################################
341
344
assert_is_alive (ID_OBJ0 )
342
345
assert_is_alive (ID_OBJ1 )
343
346
344
347
del obj0
348
+ ####################################### GC #######################################
345
349
self ._trigger_gc ()
350
+ ##################################################################################
346
351
assert_is_freed (ID_OBJ0 )
347
352
assert_is_freed (ID_OBJ1 )
348
353
@@ -356,6 +361,7 @@ def assert_is_freed(id): pass
356
361
obj9 = TestCycle0 (ID_OBJ9 )
357
362
obj10 = TestCycle0 (ID_OBJ10 )
358
363
obj11 = TestCycle0 (ID_OBJ11 )
364
+ obj14 = TestCycle0 (ID_OBJ14 )
359
365
360
366
# Legend
361
367
# '=>'
@@ -385,6 +391,8 @@ def assert_is_freed(id): pass
385
391
# update_refs: 10 1 11
386
392
# subtract_refs: 10 0 10
387
393
# move_unreachable: 10 0 10
394
+ # update_refs: 10 11 11
395
+ # subtract_refs: 10 10 10
388
396
# commit_weak_cand: obj2 => obj3 =ht-> l => obj2
389
397
obj2 .set_obj (obj3 )
390
398
l = [obj2 ]
@@ -400,7 +408,9 @@ def assert_is_freed(id): pass
400
408
# establish cycle: obj4 => obj5 =ht=> l1 => obj4
401
409
# update_refs: 10 1 11
402
410
# subtract_refs: 10 0 10
403
- # move_unreachable: 10 10 10
411
+ # move_unreachable: 10 1 10
412
+ # update_refs: 10 11 11
413
+ # subtract_refs: 10 10 10
404
414
# commit_weak_cand: obj4 => obj5 =ht-> l1 => obj4
405
415
obj4 .set_obj (obj5 )
406
416
l1 = [obj4 ]
@@ -422,6 +432,8 @@ def assert_is_freed(id): pass
422
432
# update_refs: 1 11
423
433
# subtract_refs: 1 10
424
434
# move_unreachable: 1 10
435
+ # update_refs: 1 11
436
+ # subtract_refs: 1 10
425
437
# commit_weak_cand: N => obj10 =ht=> l2
426
438
l2 = ["hello" ]
427
439
obj10 .set_obj (l2 )
@@ -433,14 +445,28 @@ def assert_is_freed(id): pass
433
445
# update_refs: 11 11
434
446
# subtract_refs: 11 10
435
447
# move_unreachable: 11 10
436
- # commit_weak_cand: N => obj11 =ht=> l3
448
+ # update_refs: 11 11
449
+ # subtract_refs: 11 10
450
+ # commit_weak_cand: J/N => obj11 =ht=> l3
437
451
l3 = ["hello" ]
438
452
obj11 .set_obj (l3 )
439
453
TestCycle0 .set_global_obj (1 , obj11 )
440
454
htid_l3 = get_handle_table_id (l3 )
441
455
del l3
442
456
# difference to previous situation: obj11 is still reachable from Java
443
457
458
+ # J => obj14 =ht=> l3
459
+ # update_refs: 10 11
460
+ # subtract_refs: 10 10
461
+ # move_unreachable: 10 10
462
+ # update_refs: 10 11
463
+ # subtract_refs: 10 10
464
+ # commit_weak_cand: J/N => obj11 =ht=> l3
465
+ l4 = ["world" ]
466
+ obj14 .set_obj (l4 )
467
+ htid_l4 = get_handle_table_id (l4 )
468
+ del l4
469
+
444
470
# everything should still be alive
445
471
assert_is_alive (ID_OBJ2 )
446
472
assert_is_alive (ID_OBJ3 )
@@ -452,17 +478,21 @@ def assert_is_freed(id): pass
452
478
assert_is_alive (ID_OBJ9 )
453
479
assert_is_alive (ID_OBJ10 )
454
480
assert_is_alive (ID_OBJ11 )
481
+ assert_is_alive (ID_OBJ14 )
455
482
assert is_strong_handle_table_ref (htid_l )
456
483
assert is_strong_handle_table_ref (htid_l1 )
457
484
assert is_strong_handle_table_ref (htid_l2 )
458
485
assert is_strong_handle_table_ref (htid_l3 )
486
+ assert is_strong_handle_table_ref (htid_l4 )
459
487
assert is_strong_handle_table_ref (htid_d0 )
460
488
461
489
del obj2 , l , obj3
462
490
del obj4 , obj5
463
491
del obj6 , d0 , obj7
464
492
493
+ ####################################### GC #######################################
465
494
self ._trigger_gc ()
495
+ ##################################################################################
466
496
467
497
# Delete Java ref after GC. This will provoke the situation where 'PythonAbstractNativeObject' of obj11 will
468
498
# die after references where potentially replicated. This tests if dangling pointers appear for the managed
@@ -479,19 +509,29 @@ def assert_is_freed(id): pass
479
509
assert_is_alive (ID_OBJ8 )
480
510
assert_is_alive (ID_OBJ9 )
481
511
assert_is_alive (ID_OBJ10 )
512
+ assert_is_alive (ID_OBJ14 )
482
513
assert is_strong_handle_table_ref (htid_l2 )
483
514
assert is_strong_handle_table_ref (htid_l3 )
484
515
assert not is_strong_handle_table_ref (htid_l )
485
516
assert not is_strong_handle_table_ref (htid_l1 )
517
+ assert not is_strong_handle_table_ref (htid_l4 )
486
518
assert not is_strong_handle_table_ref (htid_d0 )
487
519
488
520
rescued_obj4 = l1 [0 ]
489
521
del l1
522
+
523
+ __graalpython__ .tdebug ("uff" )
524
+ TestCycle0 .set_global_obj (2 , obj14 )
525
+ del obj14
526
+ ####################################### GC #######################################
490
527
self ._trigger_gc ()
528
+ ##################################################################################
491
529
# still reachable
492
530
assert_is_alive (ID_OBJ4 )
493
531
assert_is_alive (ID_OBJ5 )
532
+ assert_is_alive (ID_OBJ14 )
494
533
assert rescued_obj4 .get_obj ().get_obj ()[0 ] is rescued_obj4
534
+ assert is_strong_handle_table_ref (htid_l4 )
495
535
496
536
del rescued_obj4
497
537
@@ -516,7 +556,9 @@ def assert_is_freed(id): pass
516
556
517
557
del obj12 , obj13 , l2 , l3
518
558
559
+ ####################################### GC #######################################
519
560
self ._trigger_gc ()
561
+ ##################################################################################
520
562
521
563
assert_is_freed (ID_OBJ4 )
522
564
assert_is_freed (ID_OBJ5 )
0 commit comments