90
90
ASSERT((p)->abandoned_heap || (P)->heap_sz == (P)->hend - (P)->heap); \
91
91
ASSERT((P)->heap <= (P)->htop && (P)->htop <= (P)->hend); \
92
92
ASSERT((P)->heap <= (P)->stop && (P)->stop <= (P)->hend); \
93
- ASSERT((p)->abandoned_heap || ( (P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend)); \
93
+ ASSERT(((P)->heap <= (P)->high_water && (P)->high_water <= (P)->hend)); \
94
94
OverRunCheck((P)); \
95
95
} while (0)
96
96
#else
@@ -525,12 +525,28 @@ delay_garbage_collection(Process *p, int need, int fcalls)
525
525
ssz = orig_hend - orig_stop ;
526
526
hsz = ssz + need + ERTS_DELAY_GC_EXTRA_FREE + S_RESERVED ;
527
527
528
- hfrag = new_message_buffer (hsz );
528
+ /* Allocate one extra word at the end to save the high water mark. */
529
+ hfrag = new_message_buffer (hsz + 1 );
529
530
530
531
copy_erlang_stack (p , & hfrag -> mem [0 ], hsz );
531
532
532
533
p -> heap = p -> htop = & hfrag -> mem [0 ];
533
- p -> hend = hend = & hfrag -> mem [hsz ];
534
+ hend = & hfrag -> mem [hsz ];
535
+
536
+ /* Save the original high water mark at the end of the current
537
+ * heap to make it possible to do a minor GC later. */
538
+ if (p -> abandoned_heap ) {
539
+ * hend = (Eterm ) (p -> hend [0 ]);
540
+ } else {
541
+ * hend = (Eterm ) p -> high_water ;
542
+ }
543
+
544
+ p -> hend = hend ;
545
+
546
+ /* Keep the high water mark pointing into the current heap to ensure
547
+ * that the test for the safe range in the update_record_in_place (JIT)
548
+ * stays honest. */
549
+ p -> high_water = p -> heap ;
534
550
535
551
if (p -> abandoned_heap ) {
536
552
/*
@@ -543,7 +559,7 @@ delay_garbage_collection(Process *p, int need, int fcalls)
543
559
Uint used = orig_htop - orig_heap ;
544
560
hfrag -> used_size = used ;
545
561
p -> mbuf_sz += used ;
546
- ASSERT (hfrag -> used_size <= hfrag -> alloc_size );
562
+ ASSERT (hfrag -> used_size <= hfrag -> alloc_size - 1 );
547
563
ASSERT (!hfrag -> off_heap .first && !hfrag -> off_heap .overhead );
548
564
hfrag -> next = p -> mbuf ;
549
565
p -> mbuf = hfrag ;
@@ -559,11 +575,6 @@ delay_garbage_collection(Process *p, int need, int fcalls)
559
575
}
560
576
p -> abandoned_heap = orig_heap ;
561
577
erts_adjust_memory_break (p , orig_htop - p -> high_water );
562
-
563
- /* Point at the end of the address range to ensure that
564
- * test for the safe range in the new heap in the
565
- * update_record_in_place instruction fails. */
566
- p -> high_water = (Eterm * ) (Uint ) - 1 ;
567
578
}
568
579
569
580
#ifdef CHECK_FOR_HOLES
@@ -637,21 +648,39 @@ young_gen_usage(Process *p, Uint *ext_msg_usage)
637
648
return hsz ;
638
649
}
639
650
640
- #define ERTS_GET_ORIG_HEAP (Proc , Heap , HTop ) \
641
- do { \
642
- Eterm *aheap__ = (Proc)->abandoned_heap; \
643
- if (!aheap__) { \
644
- (Heap) = (Proc)->heap; \
645
- (HTop) = (Proc)->htop; \
646
- } \
647
- else { \
648
- (Heap) = aheap__; \
649
- if ((Proc)->flags & F_ABANDONED_HEAP_USE) \
650
- (HTop) = aheap__ + aheap__[(Proc)->heap_sz-1]; \
651
- else \
652
- (HTop) = aheap__ + (Proc)->heap_sz; \
653
- } \
654
- } while (0)
651
+ static Eterm *
652
+ get_orig_heap (Process * p , Eterm * * p_htop , Eterm * * p_high_water ) {
653
+ Eterm * aheap = p -> abandoned_heap ;
654
+ Eterm * htop ;
655
+
656
+ /* See delay_garbage_collection(). */
657
+
658
+ ASSERT (aheap != NULL );
659
+
660
+ if (p -> flags & F_ABANDONED_HEAP_USE ) {
661
+ htop = aheap + aheap [p -> heap_sz - 1 ];
662
+ } else {
663
+ htop = aheap + p -> heap_sz ;
664
+ }
665
+
666
+ * p_htop = htop ;
667
+
668
+ if (p_high_water ) {
669
+ Eterm * high_water ;
670
+
671
+ high_water = (Eterm * )(p -> hend [0 ]);
672
+
673
+ ASSERT (aheap <= high_water );
674
+ ASSERT (high_water <= htop );
675
+
676
+ /* The high water pointer must be aligned to a word boundary. */
677
+ ASSERT (((UWord ) high_water ) % sizeof (UWord ) == 0 );
678
+
679
+ * p_high_water = high_water ;
680
+ }
681
+
682
+ return aheap ;
683
+ }
655
684
656
685
static ERTS_INLINE void
657
686
check_for_possibly_long_gc (Process * p , Uint ygen_usage )
@@ -1383,12 +1412,32 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
1383
1412
Uint ygen_usage , Uint * recl )
1384
1413
{
1385
1414
Eterm * mature = p -> abandoned_heap ? p -> abandoned_heap : p -> heap ;
1386
- Uint mature_size = p -> high_water - mature ;
1415
+ Eterm * high_water ;
1416
+ Uint mature_size ;
1387
1417
Uint size_before = ygen_usage ;
1388
1418
#ifdef DEBUG
1389
1419
Uint debug_tmp = 0 ;
1390
1420
#endif
1391
1421
1422
+ if (p -> abandoned_heap ) {
1423
+ /* See delay_garbage_collection(). */
1424
+ high_water = (Eterm * )(p -> hend [0 ]);
1425
+ } else {
1426
+ high_water = p -> high_water ;
1427
+ }
1428
+
1429
+ #ifdef DEBUG
1430
+ if (p -> abandoned_heap ) {
1431
+ ASSERT (p -> abandoned_heap <= high_water );
1432
+ ASSERT (high_water - p -> abandoned_heap <= size_before );
1433
+
1434
+ /* The high water pointer must be aligned to a word boundary. */
1435
+ ASSERT (((UWord ) high_water ) % sizeof (UWord ) == 0 );
1436
+ }
1437
+ #endif
1438
+
1439
+ mature_size = high_water - mature ;
1440
+
1392
1441
need += S_RESERVED ;
1393
1442
1394
1443
/*
@@ -3659,9 +3708,11 @@ erts_process_gc_info(Process *p, Uint *sizep, Eterm **hpp,
3659
3708
ERTS_CT_ASSERT (sizeof (values )/sizeof (* values ) == ERTS_PROCESS_GC_INFO_MAX_TERMS );
3660
3709
3661
3710
if (p -> abandoned_heap ) {
3662
- Eterm * htop , * heap ;
3663
- ERTS_GET_ORIG_HEAP (p , heap , htop );
3664
- values [3 ] = HIGH_WATER (p ) - heap ;
3711
+ Eterm * htop , * heap , * high_water ;
3712
+
3713
+ heap = get_orig_heap (p , & htop , & high_water );
3714
+
3715
+ values [3 ] = high_water - heap ;
3665
3716
values [6 ] = htop - heap ;
3666
3717
}
3667
3718
@@ -3906,7 +3957,7 @@ erts_dbg_within_proc(Eterm *ptr, Process *p, Eterm *real_htop)
3906
3957
Eterm * htop , * heap ;
3907
3958
3908
3959
if (p -> abandoned_heap ) {
3909
- ERTS_GET_ORIG_HEAP (p , heap , htop );
3960
+ heap = get_orig_heap (p , & htop , NULL );
3910
3961
if (heap <= ptr && ptr < htop )
3911
3962
return 1 ;
3912
3963
}
@@ -4017,7 +4068,7 @@ erts_dbg_check_heap_terms(int (*check_eterm)(Eterm),
4017
4068
Eterm * htop , * heap ;
4018
4069
4019
4070
if (p -> abandoned_heap ) {
4020
- ERTS_GET_ORIG_HEAP (p , heap , htop );
4071
+ heap = get_orig_heap (p , & htop , NULL );
4021
4072
if (!check_all_heap_terms_in_range (check_eterm ,
4022
4073
heap , htop ))
4023
4074
return 0 ;
0 commit comments