75
80
*HTOP++ = *PTR++; \
78
#define UPDATE_SSB(p,HDR,HTOP) \
80
if (((HDR) & _HEADER_SUBTAG_MASK) == VECTOR_SUBTAG) { \
81
Uint n = header_arity(HDR); \
86
if (is_not_immed(*hp)) { \
87
ERTS_SSB_PUT(p, hp); \
93
83
#define in_area(ptr,start,nbytes) \
94
84
((unsigned long)((char*)(ptr) - (char*)(start)) < (nbytes))
97
# define STACK_SZ_ON_HEAP(p) 0
98
# define OverRunCheck() \
99
if (HEAP_END(p) < HEAP_TOP(p)) { \
100
erl_exit(1, "%s: Overrun heap at line %d\n", print_pid(p),__LINE__); \
103
86
# define STACK_SZ_ON_HEAP(p) ((p)->hend - (p)->stop)
104
87
# define OverRunCheck() \
105
88
if (p->stop < p->htop) { \
106
erl_exit(1, "%s: Overrun stack and heap at line %d\n", print_pid(p),__LINE__); \
89
erl_exit(1, "%T: Overrun stack and heap at line %d\n", p->id,__LINE__); \
111
93
* This structure describes the rootset for the GC.
126
108
static Uint setup_rootset(Process*, Eterm*, int, Rootset*);
127
109
static void cleanup_rootset(Rootset *rootset);
128
110
static void remove_message_buffers(Process* p);
129
static int major_collection(Process* p, int need, Eterm* objv, int nobj);
130
static int minor_collection(Process* p, int need, Eterm* objv, int nobj);
111
static int major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
112
static int minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl);
131
113
static void do_minor(Process *p, int new_sz, Eterm* objv, int nobj);
132
114
static Eterm* sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size);
133
115
static Eterm* sweep_old_heap(Process* p, Eterm* n_hp, Eterm* n_htop,
134
116
char* src, Uint src_size);
135
117
static Eterm* collect_heap_frags(Process* p, Eterm* heap,
136
118
Eterm* htop, Eterm* objv, int nobj);
137
static void adjust_after_fullsweep(Process *p, int size_before,
119
static Uint adjust_after_fullsweep(Process *p, int size_before,
138
120
int need, Eterm *objv, int nobj);
139
121
static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj);
140
static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj);
141
122
static void sweep_proc_bins(Process *p, int fullsweep);
143
123
static void sweep_proc_funs(Process *p, int fullsweep);
145
124
static void sweep_proc_externals(Process *p, int fullsweep);
146
125
static void offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
147
126
static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
148
static void offset_rootset(Process *p, int offs, char* area, Uint area_size,
127
static void offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
149
128
Eterm* objv, int nobj);
150
static void offset_off_heap(Process* p, int offs, char* area, Uint area_size);
129
static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_size);
151
130
static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_size);
152
static char* print_pid(Process *p);
154
132
static int within(Eterm *ptr, Process *p);
155
void verify_old_heap(Process* p);
157
static void ssb_filter(Process* p);
158
134
#endif /* HEAP_FRAG_ELIM_TEST */
160
static int heap_sizes[64]; /* Suitable heap sizes. */
137
static void disallow_heap_frag_ref_in_heap(Process* p);
138
static void disallow_heap_frag_ref_in_old_heap(Process* p);
139
static void disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj);
143
# define MAX_HEAP_SIZES 154
145
# define MAX_HEAP_SIZES 55
148
static Sint heap_sizes[MAX_HEAP_SIZES]; /* Suitable heap sizes. */
161
149
static int num_heap_sizes; /* Number of heap sizes. */
152
#ifndef HEAP_FRAG_ELIM_TEST
153
extern void erts_init_ggc(void);
164
157
* Initialize GC global data.
171
switch (heap_series) {
175
for (i = 2; i < ALENGTH(heap_sizes) && heap_sizes[i-1] < MAX_SMALL; i++) {
176
heap_sizes[i] = heap_sizes[i-1] + heap_sizes[i-2];
180
case HS_FIBONACCI_SLOW:
183
* Fib growth is not really ok for really large heaps, for
184
* example is fib(35) == 14meg, whereas fib(36) == 24meg,
185
* we really don't want that growth when the heaps are that big.
188
double grow_factor = 1.25; /* instead of fib */
192
for (i = 2; i < 23; i++) {
193
heap_sizes[i] = heap_sizes[i-1] + heap_sizes[i-2];
196
/* At 1.3 mega words heap, we start to slow down */
197
for (i = 23; i < ALENGTH(heap_sizes) && heap_sizes[i-1] < MAX_SMALL; i++) {
198
heap_sizes[i] = (int) (grow_factor * heap_sizes[i-1]);
204
for (i = 1; i < ALENGTH(heap_sizes) && heap_sizes[i-1] < MAX_SMALL; i++) {
205
heap_sizes[i] = 2 * heap_sizes[i-1];
208
case HS_POWER_TWO_MINUS_ONE:
210
for (i = 1; i < ALENGTH(heap_sizes) && heap_sizes[i-1] < MAX_SMALL; i++) {
211
heap_sizes[i] = 2 * (heap_sizes[i-1]+1) - 1;
164
#ifdef HEAP_FRAG_ELIM_TEST
165
erts_smp_spinlock_init(&info_lck, "gc_info");
173
* Heap sizes start growing in a Fibonacci sequence.
175
* Fib growth is not really ok for really large heaps, for
176
* example is fib(35) == 14meg, whereas fib(36) == 24meg;
177
* we really don't want that growth when the heaps are that big.
182
for (i = 2; i < 23; i++) {
183
heap_sizes[i] = heap_sizes[i-1] + heap_sizes[i-2];
186
/* At 1.3 mega words heap, we start to slow down. */
187
for (i = 23; i < ALENGTH(heap_sizes); i++) {
188
heap_sizes[i] = 5*(heap_sizes[i-1]/4);
189
if (heap_sizes[i] < 0) {
190
/* Size turned negative. Discard this last size. */
215
195
num_heap_sizes = i;
254
234
erts_heap_sizes(Process* p)
258
Eterm* hp = HAlloc(p, num_heap_sizes * 2);
260
for (i = num_heap_sizes-1; i >= 0; i--) {
261
res = CONS(hp, make_small(heap_sizes[i]), res);
243
for (i = num_heap_sizes-1; i >= 0; i--) {
245
if (!MY_IS_SSMALL(heap_sizes[i])) {
246
big += BIG_UINT_HEAP_SIZE;
251
* We store all big numbers first on the heap, followed
252
* by all the cons cells.
254
bigp = HAlloc(p, n+big);
256
for (i = num_heap_sizes-1; i >= 0; i--) {
258
Sint sz = heap_sizes[i];
260
if (MY_IS_SSMALL(sz)) {
261
num = make_small(sz);
263
num = uint_to_big(sz, bigp);
264
bigp += BIG_UINT_HEAP_SIZE;
266
res = CONS(hp, num, res);
267
272
#ifdef HEAP_FRAG_ELIM_TEST
275
erts_gc_info(ErtsGCInfo *gcip)
278
erts_smp_spin_lock(&info_lck);
279
gcip->garbage_collections = garbage_cols;
280
gcip->reclaimed = reclaimed;
281
erts_smp_spin_unlock(&info_lck);
286
erts_offset_heap(Eterm* hp, Uint sz, Sint offs, Eterm* low, Eterm* high)
288
return offset_heap(hp, sz, offs, (char*) low, high-low);
292
erts_offset_heap_ptr(Eterm* hp, Uint sz, Sint offs,
293
Eterm* low, Eterm* high)
295
return offset_heap_ptr(hp, sz, offs, (char *) low, high-low);
298
#define ptr_within(ptr, low, high) ((ptr) < (high) && (ptr) >= (low))
301
erts_offset_off_heap(ErlOffHeap *ohp, Sint offs, Eterm* low, Eterm* high)
303
if (ohp->mso && ptr_within((Eterm *)ohp->mso, low, high)) {
304
Eterm** uptr = (Eterm**) &ohp->mso;
308
#ifndef HYBRID /* FIND ME! */
309
if (ohp->funs && ptr_within((Eterm *)ohp->funs, low, high)) {
310
Eterm** uptr = (Eterm**) &ohp->funs;
315
if (ohp->externals && ptr_within((Eterm *)ohp->externals, low, high)) {
316
Eterm** uptr = (Eterm**) &ohp->externals;
322
#if defined(HEAP_FRAG_ELIM_TEST)
324
erts_gc_after_bif_call(Process* p, Eterm result)
328
if (is_non_value(result)) {
329
if (p->freason == TRAP) {
330
cost = erts_garbage_collect(p, 0, p->def_arg_reg, p->arity);
331
} else if (p->freason == RESCHEDULE) {
334
cost = erts_garbage_collect(p, 0, NULL, 0);
340
cost = erts_garbage_collect(p, 0, val, 1);
270
349
* Garbage collect a process.
318
394
t = t*1000000 + s2 - s1;
319
395
t = t*1000 + (us2 - us1)/1000;
320
396
if (t > 0 && (Uint)t > erts_system_monitor_long_gc) {
397
monitor_long_gc(p, t);
402
erts_smp_spin_lock(&info_lck);
326
ARITH_LOWEST_HTOP(p) = (Eterm *) 0;
328
ARITH_HEAP(p) = NULL;
404
reclaimed += reclaimed_now;
405
erts_smp_spin_unlock(&info_lck);
329
407
MSO(p).overhead = 0;
331
ARITH_CHECK_ME(p) = NULL;
409
#ifdef CHECK_FOR_HOLES
411
* We intentionally do not rescan the areas copied by the GC.
412
* We trust the GC not to leave any holes.
415
Eterm* start = p->htop;
416
Eterm* stop = p->stop;
417
p->last_htop = p->htop;
419
while (start < stop) {
420
*start++ = ERTS_HOLE_MARKER;
333
425
return ((int) (HEAP_TOP(p) - HEAP_START(p)) / 10);
337
minor_collection(Process* p, int need, Eterm* objv, int nobj)
429
minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl)
340
432
* Allocate an old heap if we don't have one and if we'll need one.
435
527
n_htop = n_heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP,
436
528
sizeof(Eterm)*new_sz);
438
if (p->ssb != NULL) {
441
530
if (MBUF(p) != NULL) {
442
531
n_htop = collect_heap_frags(p, n_heap, n_htop, objv, nobj);
446
* If vectors have been used in this process, there could be
447
* pointers from the oldest generation to the youngest.
450
if (p->ssb != NULL) {
451
Eterm** ssb_p = p->ssb->buf;
452
Eterm** limit = p->ssb->next;
454
while (ssb_p < limit) {
457
Eterm* g_ptr = *ssb_p++;
460
switch (primary_tag(gval)) {
461
case TAG_PRIMARY_BOXED:
462
ptr = boxed_val(gval);
465
ASSERT(is_boxed(val));
467
} else if (in_area(ptr, heap, mature_size)) {
468
MOVE_BOXED(ptr,val,old_htop,g_ptr);
469
if ((val & _HEADER_SUBTAG_MASK) == VECTOR_SUBTAG) {
470
Eterm** old_buf = p->ssb->buf;
471
Uint n = header_arity(val);
472
Eterm* hp = old_htop;
475
if (is_not_immed(*hp)) {
479
ssb_p = p->ssb->buf + (ssb_p - old_buf);
480
limit = p->ssb->next;
482
} else if (in_area(ptr, heap, heap_size)) {
483
MOVE_BOXED(ptr,val,n_htop,g_ptr);
486
case TAG_PRIMARY_LIST:
487
ptr = list_val(gval);
489
if (is_non_value(val)) {
491
} else if (in_area(ptr, heap, mature_size)) {
492
MOVE_CONS(ptr,val,old_htop,g_ptr);
493
} else if (in_area(ptr, heap, heap_size)) {
494
MOVE_CONS(ptr,val,n_htop,g_ptr);
501
534
n = setup_rootset(p, objv, nobj, &rootset);
502
535
roots = rootset.roots;
605
636
case TAG_PRIMARY_HEADER: {
606
if (header_is_thing(gval))
637
if (!header_is_thing(gval))
640
if (header_is_bin_matchstate(gval)) {
641
ErlBinMatchState *ms = (ErlBinMatchState*) n_hp;
642
ErlBinMatchBuffer *mb = &(ms->mb);
643
Eterm* origptr = &(mb->orig);
644
ptr = boxed_val(*origptr);
648
mb->base = binary_bytes(val);
649
} else if (in_area(ptr, heap, mature_size)) {
650
MOVE_BOXED(ptr,val,old_htop,origptr);
651
mb->base = binary_bytes(mb->orig);
652
} else if (in_area(ptr, heap, heap_size)) {
653
MOVE_BOXED(ptr,val,n_htop,origptr);
654
mb->base = binary_bytes(mb->orig);
607
657
n_hp += (thing_arityval(gval)+1);
834
875
case TAG_PRIMARY_HEADER: {
835
if (header_is_thing(gval))
876
if (!header_is_thing(gval))
879
if (header_is_bin_matchstate(gval)) {
880
ErlBinMatchState *ms = (ErlBinMatchState*) n_hp;
881
ErlBinMatchBuffer *mb = &(ms->mb);
883
origptr = &(mb->orig);
884
ptr = boxed_val(*origptr);
888
mb->base = binary_bytes(*origptr);
889
} else if (in_area(ptr, src, src_size)) {
890
ASSERT(within(ptr, p));
891
MOVE_BOXED(ptr,val,n_htop,origptr);
892
mb->base = binary_bytes(*origptr);
893
ptr = boxed_val(*origptr);
895
} else if (in_area(ptr, oh, oh_size)) {
896
ASSERT(within(ptr, p));
897
MOVE_BOXED(ptr,val,old_htop,origptr);
898
mb->base = binary_bytes(*origptr);
899
ptr = boxed_val(*origptr);
903
ASSERT(within(ptr, p));
904
MOVE_BOXED(ptr,val,n_htop,origptr);
905
mb->base = binary_bytes(*origptr);
906
ptr = boxed_val(*origptr);
836
911
n_hp += (thing_arityval(gval)+1);
849
923
old_htop = sweep_one_area(old_heap, old_htop, oh, oh_size);
853
* If vectors have been used in this process, there could be
854
* pointers from the oldest generation to the youngest.
855
* Sweep the new old_heap and update them.
858
if (p->ssb != NULL) {
859
Eterm* o_hp = old_heap;
860
char* nh = (char *) n_heap;
861
Uint nh_size = (char *) n_htop - nh;
863
p->ssb->next = p->ssb->buf; /* Empty SSB; it will be re-built */
864
while (o_hp != old_htop) {
869
switch (primary_tag(gval)) {
870
case TAG_PRIMARY_BOXED: {
871
ptr = boxed_val(gval);
874
ASSERT(is_boxed(val));
875
if (in_area(boxed_val(val),nh,nh_size)) {
876
ERTS_SSB_PUT(p, o_hp);
879
} else if (in_area(ptr, nh, nh_size)) {
880
ERTS_SSB_PUT(p, o_hp);
882
} else if (in_area(ptr, src, src_size)) {
883
MOVE_BOXED(ptr,val,old_htop,o_hp++);
884
} else if (in_area(ptr, oh, oh_size)) {
885
MOVE_BOXED(ptr,val,old_htop,o_hp++);
891
case TAG_PRIMARY_LIST: {
892
ptr = list_val(gval);
894
if (is_non_value(val)) {
896
if (in_area(list_val(val),nh,nh_size)) {
897
ERTS_SSB_PUT(p, o_hp);
900
} else if (in_area(ptr, nh, nh_size)) {
901
ERTS_SSB_PUT(p, o_hp);
903
} else if (in_area(ptr, src, src_size)) {
904
MOVE_CONS(ptr,val,old_htop,o_hp++);
905
} else if (in_area(ptr, oh, oh_size)) {
906
MOVE_CONS(ptr,val,old_htop,o_hp++);
912
case TAG_PRIMARY_HEADER:
913
if (header_is_thing(gval))
914
o_hp += (thing_arityval(gval)+1);
925
* If no pointers left from old to young, delete the SSB.
927
if (p->ssb->next == p->ssb->buf) {
928
erts_free(ERTS_ALC_T_SSB, p->ssb);
933
926
if (MSO(p).mso) {
934
927
sweep_proc_bins(p, 1);
937
929
if (MSO(p).funs) {
938
930
sweep_proc_funs(p, 1);
941
932
if (MSO(p).externals) {
942
933
sweep_proc_externals(p, 1);
944
remove_message_buffers(p);
946
936
if (OLD_HEAP(p) != NULL) {
979
967
HIGH_WATER(p) = HEAP_TOP(p);
981
adjust_after_fullsweep(p, size_before, need, objv, nobj);
969
*recl += adjust_after_fullsweep(p, size_before, need, objv, nobj);
972
disallow_heap_frag_ref_in_heap(p);
973
disallow_heap_frag_ref_in_old_heap(p);
975
remove_message_buffers(p);
987
978
return 1; /* We are done. */
991
982
adjust_after_fullsweep(Process *p, int size_before, int need, Eterm *objv, int nobj)
993
984
int wanted, sz, size_after, need_after;
994
985
int stack_size = STACK_SZ_ON_HEAP(p);
996
988
size_after = (HEAP_TOP(p) - HEAP_START(p));
997
reclaimed += (size_before - size_after);
989
reclaimed_now = (size_before - size_after);
1000
992
* Resize the heap if needed.
1083
1064
ASSERT(is_boxed(val));
1086
if (in_area(ptr, heap_part, heap_part_size)) {
1087
MOVE_BOXED(ptr,val,n_htop,objv);
1089
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1090
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1091
MOVE_BOXED(ptr,val,n_htop,objv);
1067
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1068
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1069
MOVE_BOXED(ptr,val,n_htop,objv);
1104
1081
if (is_non_value(val)) {
1105
1082
*objv++ = ptr[1];
1107
if (in_area(ptr, heap_part, heap_part_size)) {
1108
MOVE_CONS(ptr,val,n_htop,objv);
1110
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1111
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1112
MOVE_CONS(ptr,val,n_htop,objv);
1084
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1085
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1086
MOVE_CONS(ptr,val,n_htop,objv);
1106
disallow_heap_frag_ref(Process* p, Eterm* n_htop, Eterm* objv, int nobj)
1108
ErlHeapFragment* mbuf;
1109
ErlHeapFragment* qb;
1114
ASSERT(p->htop != NULL);
1120
switch (primary_tag(gval)) {
1122
case TAG_PRIMARY_BOXED: {
1123
ptr = boxed_val(gval);
1125
if (IS_MOVED(val)) {
1126
ASSERT(is_boxed(val));
1129
for (qb = mbuf; qb != NULL; qb = qb->next) {
1130
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1139
case TAG_PRIMARY_LIST: {
1140
ptr = list_val(gval);
1142
if (is_non_value(val)) {
1145
for (qb = mbuf; qb != NULL; qb = qb->next) {
1146
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1164
disallow_heap_frag_ref_in_heap(Process* p)
1177
heap_size = (htop - heap)*sizeof(Eterm);
1181
ErlHeapFragment* qb;
1186
switch (primary_tag(val)) {
1187
case TAG_PRIMARY_BOXED:
1188
ptr = boxed_val(val);
1189
if (!in_area(ptr, heap, heap_size)) {
1190
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1191
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1197
case TAG_PRIMARY_LIST:
1198
ptr = list_val(val);
1199
if (!in_area(ptr, heap, heap_size)) {
1200
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1201
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1207
case TAG_PRIMARY_HEADER:
1208
if (header_is_thing(val)) {
1209
hp += thing_arityval(val);
1217
disallow_heap_frag_ref_in_old_heap(Process* p)
1227
old_heap = p->old_heap;
1228
old_heap_size = (htop - old_heap)*sizeof(Eterm);
1230
new_heap_size = (p->htop - new_heap)*sizeof(Eterm);
1234
ErlHeapFragment* qb;
1239
switch (primary_tag(val)) {
1240
case TAG_PRIMARY_BOXED:
1241
ptr = boxed_val(val);
1242
if (in_area(ptr, new_heap, new_heap_size)) {
1245
if (!in_area(ptr, old_heap, old_heap_size)) {
1246
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1247
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1253
case TAG_PRIMARY_LIST:
1254
ptr = list_val(val);
1255
if (in_area(ptr, new_heap, new_heap_size)) {
1258
if (!in_area(ptr, old_heap, old_heap_size)) {
1259
for (qb = MBUF(p); qb != NULL; qb = qb->next) {
1260
if (in_area(ptr, qb->mem, qb->size*sizeof(Eterm))) {
1266
case TAG_PRIMARY_HEADER:
1267
if (header_is_thing(val)) {
1268
hp += thing_arityval(val);
1269
if (!in_area(hp, old_heap, old_heap_size+1)) {
1132
1280
sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size)
1165
1313
case TAG_PRIMARY_HEADER: {
1166
if (header_is_thing(gval))
1314
if (!header_is_thing(gval)) {
1317
if (header_is_bin_matchstate(gval)) {
1318
ErlBinMatchState *ms = (ErlBinMatchState*) n_hp;
1319
ErlBinMatchBuffer *mb = &(ms->mb);
1321
origptr = &(mb->orig);
1322
ptr = boxed_val(*origptr);
1324
if (IS_MOVED(val)) {
1326
mb->base = binary_bytes(*origptr);
1327
} else if (in_area(ptr, src, src_size)) {
1328
MOVE_BOXED(ptr,val,n_htop,origptr);
1329
mb->base = binary_bytes(*origptr);
1167
1332
n_hp += (thing_arityval(gval)+1);
1215
1378
case TAG_PRIMARY_HEADER: {
1216
if (header_is_thing(gval))
1379
if (!header_is_thing(gval)) {
1382
if (header_is_bin_matchstate(gval)) {
1383
ErlBinMatchState *ms = (ErlBinMatchState*) o_hp;
1384
ErlBinMatchBuffer *mb = &(ms->mb);
1385
Eterm* origptr = &(mb->orig);
1386
Eterm* ptr = boxed_val(*origptr);
1388
if (IS_MOVED(val)) {
1390
mb->base = binary_bytes(val);
1391
} else if (in_area(ptr, src, src_size)) {
1392
MOVE_BOXED(ptr,val,o_htop,origptr);
1393
mb->base = binary_bytes(mb->orig);
1217
1396
o_hp += (thing_arityval(gval)+1);
1263
1452
p->dictionary->data,
1264
1453
p->dictionary->used);
1266
1456
if (p->debug_dictionary != NULL) {
1267
n_htop = collect_root_array(p, n_htop,
1268
p->debug_dictionary->data,
1269
p->debug_dictionary->used);
1272
n_htop = collect_root_array(p, n_htop, p->stop, STACK_START(p) - p->stop);
1276
* Go through the message queues for all active processes.
1281
Uint limit = erts_num_active_procs;
1284
for (i = 0; i < limit; i++) {
1285
tp = erts_active_procs[i];
1289
if (is_not_immed(tp->fvalue)) {
1290
n_htop = collect_root_array(p, n_htop, &tp->fvalue, 1);
1292
if (is_not_immed(tp->group_leader)) {
1293
n_htop = collect_root_array(p, n_htop, &tp->group_leader, 1);
1295
for (mp = tp->msg.first; mp != NULL; mp = mp->next) {
1296
if (is_not_immed(ERL_MESSAGE_TERM(mp)) ||
1297
is_not_immed(ERL_MESSAGE_TOKEN(mp))) {
1298
n_htop = collect_root_array(p, n_htop, mp->m, 2);
1305
* Go through the message queue, move everything that it is in one of the
1457
disallow_heap_frag_ref(p, n_htop,
1458
p->debug_dictionary->data,
1459
p->debug_dictionary->used);
1464
* Go through the message queue, move everything that is in one of the
1306
1465
* heap fragments to our new heap.
1311
1470
n_htop = collect_root_array(p, n_htop, mp->m, 2);
1317
1475
* Now all references in the root set point to the new heap. However,
1318
* many references on the new heap point to other heap fragments.
1319
* So the next stage is to scan through the new heap evacuating data
1320
* from the old heap until everything is copied.
1322
* We must scan the heap once for every heap framgent. Order:
1324
* 1. All heap fragments allocated by HAlloc().
1325
* 2. The part of the heap that may contain pointers into ArithAlloc'ed
1327
* 3. All heap fragments allocated by ArithAlloc().
1476
* many references on the new heap point to heap fragments.
1330
ASSERT(ARITH_LOWEST_HTOP(p) <= p->htop);
1332
if ((halloc_mbuf = HALLOC_MBUF(p)) != NULL) {
1334
* Sweep using all heap fragments allocated by HAlloc().
1337
frag_begin = (char *) qb->mem;
1338
frag_size = qb->size * sizeof(Eterm);
1339
n_htop = sweep_one_area(n_hstart, n_htop, frag_begin, frag_size);
1340
if (qb == halloc_mbuf) {
1349
* Sweep using part of the heap as source.
1352
frag_begin = (char *) ARITH_LOWEST_HTOP(p);
1353
if (frag_begin == NULL) {
1356
frag_size = (char *)p->htop - frag_begin;
1358
if (frag_size != 0) {
1359
n_htop = sweep_one_area(n_hstart, n_htop, frag_begin, frag_size);
1363
* Sweep using the remaining heap fragments (allocated by ArithAlloc()).
1366
1480
while (qb != NULL) {
1367
1481
frag_begin = (char *) qb->mem;
1368
1482
frag_size = qb->size * sizeof(Eterm);
1477
setup_rootset(Process *current, Eterm *objv, int nobj, Rootset *rootset)
1484
rootset->roots = rootset->def;
1485
rootset->size = ALENGTH(rootset->def);
1486
limit = erts_num_active_procs;
1487
for (i = 0; i < limit; i++) {
1488
p = erts_active_procs[i];
1491
n = add_to_rootset(p, objv, nobj, rootset, n);
1493
n = add_to_rootset(p, p->arg_reg, p->arity, rootset, n);
1501
1595
setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
1533
1624
if ((offs = new_heap - HEAP_START(p)) == 0) { /* No move. */
1534
1625
HEAP_END(p) = new_heap + new_sz;
1536
1626
sys_memmove(p->hend - stack_size, p->stop, stack_size * sizeof(Eterm));
1537
1627
p->stop = p->hend - stack_size;
1540
1629
char* area = (char *) HEAP_START(p);
1541
1630
Uint area_size = (char *) HEAP_TOP(p) - area;
1543
1631
Eterm* prev_stop = p->stop;
1546
1633
offset_heap(new_heap, heap_size, offs, area, area_size);
1547
1634
HIGH_WATER(p) = new_heap + (HIGH_WATER(p) - HEAP_START(p));
1549
1636
HEAP_END(p) = new_heap + new_sz;
1551
1637
prev_stop = new_heap + (p->stop - p->heap);
1552
1638
p->stop = p->hend - stack_size;
1553
1639
sys_memmove(p->stop, prev_stop, stack_size * sizeof(Eterm));
1555
1641
offset_rootset(p, offs, area, area_size, objv, nobj);
1556
1642
HEAP_TOP(p) = new_heap + heap_size;
1557
1643
HEAP_START(p) = new_heap;
1559
1645
HEAP_SIZE(p) = new_sz;
1563
shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
1649
erts_shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
1565
1651
Eterm* new_heap;
1566
1652
int heap_size = HEAP_TOP(p) - HEAP_START(p);
1570
ASSERT(new_sz < HEAP_SIZE(p));
1572
new_heap = (Eterm *) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP,
1573
(void*)HEAP_START(p),
1574
sizeof(Eterm)*(HEAP_SIZE(p)),
1575
sizeof(Eterm)*new_sz);
1576
HEAP_END(p) = new_heap + new_sz;
1578
1655
int stack_size = p->hend - p->stop;
1580
1657
ASSERT(new_sz < p->heap_sz);
1858
offset_off_heap(Process* p, int offs, char* area, Uint area_size)
1941
offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
1860
1943
if (MSO(p).mso && in_area((Eterm *)MSO(p).mso, area, area_size)) {
1861
1944
Eterm** uptr = (Eterm**) &MSO(p).mso;
1866
1948
if (MSO(p).funs && in_area((Eterm *)MSO(p).funs, area, area_size)) {
1867
1949
Eterm** uptr = (Eterm**) &MSO(p).funs;
1872
1953
if (MSO(p).externals && in_area((Eterm *)MSO(p).externals, area, area_size)) {
1873
1954
Eterm** uptr = (Eterm**) &MSO(p).externals;
1919
2000
p->debug_dictionary->used,
1920
2001
offs, area, area_size);
1922
offset_heap(&p->fvalue, 1, offs, area, area_size);
1923
offset_heap(&p->seq_trace_token, 1, offs, area, area_size);
1924
offset_heap(&p->group_leader, 1, offs, area, area_size);
2003
offset_heap_ptr(&p->fvalue, 1, offs, area, area_size);
2004
offset_heap_ptr(&p->ftrace, 1, offs, area, area_size);
2005
offset_heap_ptr(&p->seq_trace_token, 1, offs, area, area_size);
2006
offset_heap_ptr(&p->group_leader, 1, offs, area, area_size);
1925
2007
offset_mqueue(p, offs, area, area_size);
1926
2008
offset_heap_ptr(p->stop, (STACK_START(p) - p->stop), offs, area, area_size);
1927
2009
if (nobj > 0) {
1928
offset_heap(objv, nobj, offs, area, area_size);
2010
offset_heap_ptr(objv, nobj, offs, area, area_size);
1930
2012
offset_off_heap(p, offs, area, area_size);
1934
offset_rootset(Process *p, int offs, char* area, Uint area_size,
2016
offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
1935
2017
Eterm* objv, int nobj)
1938
2019
offset_one_rootset(p, offs, area, area_size, objv, nobj);
1941
Uint limit = erts_num_active_procs;
1942
Process* current = p;
1944
for (i = 0; i < limit; i++) {
1945
p = erts_active_procs[i];
1948
offset_one_rootset(p, offs, area, area_size, objv, nobj);
1950
offset_one_rootset(p, offs, area, area_size, p->arg_reg, p->arity);
1956
if (p->ssb != NULL) {
1957
Eterm** ssb_p = p->ssb->buf;
1958
Eterm** limit = p->ssb->next;
1960
while (ssb_p < limit) {
1961
offset_heap(*ssb_p++, 1, offs, area, area_size);
1968
print_pid(Process *p)
1970
char static buf[64];
1975
internal_pid_channel_no(obj),
1976
internal_pid_number(obj),
1977
internal_pid_serial(obj));
2005
verify_old_heap(Process* p)
2007
Eterm* o_hp = OLD_HEAP(p);
2008
Eterm* o_htop = OLD_HTOP(p);
2009
char* nh = (char *) HEAP_START(p);
2010
Uint nh_size = (char *) HEAP_TOP(p) - nh;
2011
char* oh = (char *) OLD_HEAP(p);
2012
Uint oh_size = (char *) OLD_HTOP(p) - oh;
2013
Eterm** ssb_start = NULL;
2014
Eterm** limit = NULL;
2016
if (p->ssb != NULL) {
2017
ssb_start = p->ssb->buf;
2018
limit = p->ssb->next;
2021
while (o_hp != o_htop) {
2026
switch (primary_tag(gval)) {
2027
case TAG_PRIMARY_BOXED: {
2028
ptr = boxed_val(gval);
2029
if (!in_area(ptr,oh,oh_size)) {
2030
Eterm** ssb_p = ssb_start;
2031
if (in_area(ptr,nh,nh_size)) {
2032
while (ssb_p < limit) {
2033
if (o_hp == *ssb_p) {
2038
ASSERT(ssb_p < limit);
2042
ASSERT(is_header(val));
2046
case TAG_PRIMARY_LIST: {
2047
ptr = list_val(gval);
2048
if (!in_area(ptr,oh,oh_size)) {
2049
Eterm** ssb_p = ssb_start;
2050
if (in_area(ptr,nh,nh_size)) {
2051
while (ssb_p < limit) {
2052
if (o_hp == *ssb_p) {
2057
ASSERT(ssb_p < limit);
2061
ASSERT(is_value(val));
2065
case TAG_PRIMARY_HEADER: {
2066
if (header_is_thing(gval))
2067
o_hp += (thing_arityval(gval)+1);
2073
ASSERT(is_value(gval));
2082
* Sequential Store Buffer (write barrier) stuff.
2086
erts_ensure_ssb(Process* p)
2091
if (p->ssb == NULL) {
2092
ssb = (ErlSSB *) erts_alloc(ERTS_ALC_T_SSB,
2093
sizeof(ErlSSB) + sizeof(Eterm)*avail);
2094
ssb->next = ssb->buf;
2095
ssb->end = ssb->buf + avail;
2101
erts_ssb_expand_put(Process* p, Eterm* addr)
2106
old_sz = (p->ssb->end - p->ssb->buf);
2108
p->ssb = (ErlSSB *) erts_realloc(ERTS_ALC_T_SSB,
2110
sizeof(ErlSSB)+new_sz*sizeof(Eterm *));
2111
p->ssb->next = p->ssb->buf + old_sz;
2112
p->ssb->end = p->ssb->buf + new_sz;
2113
*(p)->ssb->next++ = addr;
2117
* Get rid from the SSB all pointers that don't point into the old_heap.
2120
ssb_filter(Process* p)
2122
char* oh = (char *) OLD_HEAP(p);
2123
Uint oh_size = (char *) OLD_HTOP(p) - oh;
2124
Eterm** limit = p->ssb->next;
2125
Eterm** ssb_p = p->ssb->buf;
2127
while (ssb_p < limit) {
2128
Eterm* ptr = *ssb_p;
2129
if (!in_area(ptr, oh, oh_size)) {
2136
p->ssb->next = limit;
2139
2044
#endif /* HEAP_FRAG_ELIM_TEST */