Chez Scheme: repair to code vs. non-code chunk handling

The daily build plot showed much higher peak memory use due to some
missing pieces for the split.
This commit is contained in:
Matthew Flatt 2020-11-29 06:03:04 -07:00
parent 1bf4086dae
commit 3085780849
3 changed files with 254 additions and 242 deletions

View File

@ -1651,7 +1651,7 @@ ptr GCENTRY(ptr tc, ptr count_roots_ls) {
si->forwarded_flonums = 0;
#endif
} else {
chunkinfo *chunk = si->chunk;
chunkinfo *chunk = si->chunk, **chunks = ((si->space == space_code) ? S_code_chunks : S_chunks);
S_G.number_of_nonstatic_segments -= 1;
S_G.number_of_empty_segments += 1;
si->space = space_empty;
@ -1666,10 +1666,10 @@ ptr GCENTRY(ptr tc, ptr count_roots_ls) {
* small stuff into them and thereby invite fragmentation */
S_free_chunk(chunk);
} else {
S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS]);
S_move_to_chunk_list(chunk, &chunks[PARTIAL_CHUNK_POOLS]);
}
} else {
S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS-1]);
S_move_to_chunk_list(chunk, &chunks[PARTIAL_CHUNK_POOLS-1]);
}
}
}

View File

@ -648,7 +648,7 @@ static void check_heap_dirty_msg(msg, x) char *msg; ptr *x; {
void S_check_heap(aftergc, mcg) IBOOL aftergc; IGEN mcg; {
uptr seg; INT d; ISPC s; IGEN g; IDIRTYBYTE dirty; IBOOL found_eos; IGEN pg;
ptr p, *pp1, *pp2, *nl;
iptr i;
iptr i, for_code;
uptr empty_segments = 0;
uptr used_segments = 0;
uptr static_segments = 0;
@ -673,27 +673,31 @@ void S_check_heap(aftergc, mcg) IBOOL aftergc; IGEN mcg; {
}
}
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i];
while (chunk != NULL) {
seginfo *si = chunk->unused_segs;
iptr count = 0;
while(si) {
count += 1;
if (si->space != space_empty) {
S_checkheap_errors += 1;
printf("!!! unused segment has unexpected space\n");
for (for_code = 0; for_code < 2; for_code++) {
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
chunkinfo *chunk = (i == -1
? (for_code ? S_code_chunks_full : S_chunks_full)
: (for_code ? S_code_chunks[i] : S_chunks[i]));
while (chunk != NULL) {
seginfo *si = chunk->unused_segs;
iptr count = 0;
while(si) {
count += 1;
if (si->space != space_empty) {
S_checkheap_errors += 1;
printf("!!! unused segment has unexpected space\n");
}
si = si->next;
}
si = si->next;
if ((chunk->segs - count) != chunk->nused_segs) {
S_checkheap_errors += 1;
printf("!!! unexpected used segs count "Ptd" with "Ptd" total segs and "Ptd" segs on the unused list\n",
(ptrdiff_t)chunk->nused_segs, (ptrdiff_t)chunk->segs, (ptrdiff_t)count);
}
used_segments += chunk->nused_segs;
empty_segments += count;
chunk = chunk->next;
}
if ((chunk->segs - count) != chunk->nused_segs) {
S_checkheap_errors += 1;
printf("!!! unexpected used segs count "Ptd" with "Ptd" total segs and "Ptd" segs on the unused list\n",
(ptrdiff_t)chunk->nused_segs, (ptrdiff_t)chunk->segs, (ptrdiff_t)count);
}
used_segments += chunk->nused_segs;
empty_segments += count;
chunk = chunk->next;
}
}
@ -734,274 +738,278 @@ void S_check_heap(aftergc, mcg) IBOOL aftergc; IGEN mcg; {
(ptrdiff_t)empty_segments);
}
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i];
while (chunk != NULL) {
uptr nsegs; seginfo *si;
for (si = &chunk->sis[0], nsegs = chunk->segs; nsegs != 0; nsegs -= 1, si += 1) {
seginfo *recorded_si; uptr recorded_seg;
if ((seg = si->number) != (recorded_seg = (chunk->base + chunk->segs - nsegs))) {
S_checkheap_errors += 1;
printf("!!! recorded segment number "PHtx" differs from actual segment number "PHtx"", (ptrdiff_t)seg, (ptrdiff_t)recorded_seg);
}
if ((recorded_si = SegInfo(seg)) != si) {
S_checkheap_errors += 1;
printf("!!! recorded segment "PHtx" seginfo "PHtx" differs from actual seginfo "PHtx"", (ptrdiff_t)seg, (ptrdiff_t)recorded_si, (ptrdiff_t)si);
}
s = si->space;
g = si->generation;
if (si->use_marks)
printf("!!! use_marks set on generation %d segment "PHtx"\n", g, (ptrdiff_t)seg);
if (s == space_new) {
if (g != 0 && !si->marked_mask) {
for (for_code = 0; for_code < 2; for_code++) {
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
chunkinfo *chunk = (i == -1
? (for_code ? S_code_chunks_full : S_chunks_full)
: (for_code ? S_code_chunks[i] : S_chunks[i]));
while (chunk != NULL) {
uptr nsegs; seginfo *si;
for (si = &chunk->sis[0], nsegs = chunk->segs; nsegs != 0; nsegs -= 1, si += 1) {
seginfo *recorded_si; uptr recorded_seg;
if ((seg = si->number) != (recorded_seg = (chunk->base + chunk->segs - nsegs))) {
S_checkheap_errors += 1;
printf("!!! unexpected generation %d segment "PHtx" in space_new\n", g, (ptrdiff_t)seg);
printf("!!! recorded segment number "PHtx" differs from actual segment number "PHtx"", (ptrdiff_t)seg, (ptrdiff_t)recorded_seg);
}
} else if (s == space_impure || s == space_symbol || s == space_pure || s == space_weakpair || s == space_ephemeron
|| s == space_immobile_impure || s == space_count_pure || s == space_count_impure || s == space_closure
|| s == space_pure_typed_object || s == space_continuation || s == space_port || s == space_code
|| s == space_impure_record || s == space_impure_typed_object) {
ptr start;
/* check for dangling references */
pp1 = TO_VOIDP(build_ptr(seg, 0));
pp2 = TO_VOIDP(build_ptr(seg + 1, 0));
if ((recorded_si = SegInfo(seg)) != si) {
S_checkheap_errors += 1;
printf("!!! recorded segment "PHtx" seginfo "PHtx" differs from actual seginfo "PHtx"", (ptrdiff_t)seg, (ptrdiff_t)recorded_si, (ptrdiff_t)si);
}
s = si->space;
g = si->generation;
nl = FIND_NL(pp1, pp2, s, g);
if (pp1 <= nl && nl < pp2) pp2 = nl;
if (si->use_marks)
printf("!!! use_marks set on generation %d segment "PHtx"\n", g, (ptrdiff_t)seg);
if (s == space_pure_typed_object || s == space_port || s == space_code
|| s == space_impure_record || s == space_impure_typed_object) {
/* only check this segment for objects that start on it */
uptr before_seg = seg;
/* Back up over segments for the same space and generation: */
while (1) {
seginfo *before_si = MaybeSegInfo(before_seg-1);
if (!before_si
|| (before_si->space != si->space)
|| (before_si->generation != si->generation)
|| ((before_si->marked_mask == NULL) != (si->marked_mask == NULL)))
break;
before_seg--;
if (s == space_new) {
if (g != 0 && !si->marked_mask) {
S_checkheap_errors += 1;
printf("!!! unexpected generation %d segment "PHtx" in space_new\n", g, (ptrdiff_t)seg);
}
} else if (s == space_impure || s == space_symbol || s == space_pure || s == space_weakpair || s == space_ephemeron
|| s == space_immobile_impure || s == space_count_pure || s == space_count_impure || s == space_closure
|| s == space_pure_typed_object || s == space_continuation || s == space_port || s == space_code
|| s == space_impure_record || s == space_impure_typed_object) {
ptr start;
/* check for dangling references */
pp1 = TO_VOIDP(build_ptr(seg, 0));
pp2 = TO_VOIDP(build_ptr(seg + 1, 0));
/* Move forward to reach `seg` again: */
start = build_ptr(before_seg, 0);
while (before_seg != seg) {
ptr *before_pp2, *before_nl;
nl = FIND_NL(pp1, pp2, s, g);
if (pp1 <= nl && nl < pp2) pp2 = nl;
before_pp2 = TO_VOIDP(build_ptr(before_seg + 1, 0));
if ((ptr *)TO_VOIDP(start) > before_pp2) {
/* skipped to a further segment */
before_seg++;
} else {
before_nl = FIND_NL(TO_VOIDP(start), before_pp2, s, g);
if (((ptr*)TO_VOIDP(start)) <= before_nl && before_nl < before_pp2) {
/* this segment ends, so move to next segment */
if (s == space_pure_typed_object || s == space_port || s == space_code
|| s == space_impure_record || s == space_impure_typed_object) {
/* only check this segment for objects that start on it */
uptr before_seg = seg;
/* Back up over segments for the same space and generation: */
while (1) {
seginfo *before_si = MaybeSegInfo(before_seg-1);
if (!before_si
|| (before_si->space != si->space)
|| (before_si->generation != si->generation)
|| ((before_si->marked_mask == NULL) != (si->marked_mask == NULL)))
break;
before_seg--;
}
/* Move forward to reach `seg` again: */
start = build_ptr(before_seg, 0);
while (before_seg != seg) {
ptr *before_pp2, *before_nl;
before_pp2 = TO_VOIDP(build_ptr(before_seg + 1, 0));
if ((ptr *)TO_VOIDP(start) > before_pp2) {
/* skipped to a further segment */
before_seg++;
if (s == space_code) {
/* in the case of code, it's possible for a whole segment to
go unused if a large code object didn't fit; give up, just in case */
start = build_ptr(seg+1, 0);
} else {
start = build_ptr(before_seg, 0);
}
} else {
seginfo *before_si = MaybeSegInfo(before_seg);
while (((ptr *)TO_VOIDP(start)) < before_pp2) {
if (before_si->marked_mask) {
if (before_si->marked_mask[segment_bitmap_byte(start)] & segment_bitmap_bit(start)) {
start = (ptr)((uptr)start + size_object(TYPE(start, type_typed_object)));
} else {
/* skip past unmarked */
start = (ptr)((uptr)start + byte_alignment);
}
before_nl = FIND_NL(TO_VOIDP(start), before_pp2, s, g);
if (((ptr*)TO_VOIDP(start)) <= before_nl && before_nl < before_pp2) {
/* this segment ends, so move to next segment */
before_seg++;
if (s == space_code) {
/* in the case of code, it's possible for a whole segment to
go unused if a large code object didn't fit; give up, just in case */
start = build_ptr(seg+1, 0);
} else {
if (*(ptr *)TO_VOIDP(start) == forward_marker) {
/* this segment ends, so move to next segment */
if (s == space_code) {
start = build_ptr(seg+1, 0);
start = build_ptr(before_seg, 0);
}
} else {
seginfo *before_si = MaybeSegInfo(before_seg);
while (((ptr *)TO_VOIDP(start)) < before_pp2) {
if (before_si->marked_mask) {
if (before_si->marked_mask[segment_bitmap_byte(start)] & segment_bitmap_bit(start)) {
start = (ptr)((uptr)start + size_object(TYPE(start, type_typed_object)));
} else {
start = build_ptr(before_seg+1, 0);
/* skip past unmarked */
start = (ptr)((uptr)start + byte_alignment);
}
} else {
start = (ptr)((uptr)start + size_object(TYPE(start, type_typed_object)));
if (*(ptr *)TO_VOIDP(start) == forward_marker) {
/* this segment ends, so move to next segment */
if (s == space_code) {
start = build_ptr(seg+1, 0);
} else {
start = build_ptr(before_seg+1, 0);
}
} else {
start = (ptr)((uptr)start + size_object(TYPE(start, type_typed_object)));
}
}
}
before_seg++;
}
before_seg++;
}
}
}
if (((ptr *)TO_VOIDP(start)) >= pp2) {
/* previous object extended past the segment */
} else {
pp1 = TO_VOIDP(start);
while (pp1 < pp2) {
if (si->marked_mask) {
if (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1))) {
p = TYPE(TO_PTR(pp1), type_typed_object);
check_object(p, seg, s, aftergc);
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_object(p)));
} else {
/* skip past unmarked */
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + byte_alignment));
}
} else {
if (*pp1 == forward_marker)
break;
else {
p = TYPE(TO_PTR(pp1), type_typed_object);
check_object(p, seg, s, aftergc);
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_object(p)));
}
}
}
}
} else if (s == space_continuation) {
while (pp1 < pp2) {
if (*pp1 == forward_marker)
break;
if (!si->marked_mask || (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1)))) {
p = TYPE(TO_PTR(pp1), type_closure);
check_object(p, seg, s, aftergc);
}
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_continuation));
}
} else {
while (pp1 < pp2) {
if (!si->marked_mask || (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1)))) {
int a;
for (a = 0; (a < ptr_alignment) && (pp1 < pp2); a++) {
#define in_ephemeron_pair_part(pp1, seg) ((((uptr)TO_PTR(pp1) - (uptr)build_ptr(seg, 0)) % size_ephemeron) < size_pair)
if ((s == space_ephemeron) && !in_ephemeron_pair_part(pp1, seg)) {
/* skip non-pair part of ephemeron */
} else {
p = *pp1;
if (!si->marked_mask && (p == forward_marker)) {
pp1 = pp2; /* break out of outer loop */
break;
if (((ptr *)TO_VOIDP(start)) >= pp2) {
/* previous object extended past the segment */
} else {
pp1 = TO_VOIDP(start);
while (pp1 < pp2) {
if (si->marked_mask) {
if (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1))) {
p = TYPE(TO_PTR(pp1), type_typed_object);
check_object(p, seg, s, aftergc);
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_object(p)));
} else {
check_pointer(pp1, 1, (ptr)0, seg, s, aftergc);
/* skip past unmarked */
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + byte_alignment));
}
} else {
if (*pp1 == forward_marker)
break;
else {
p = TYPE(TO_PTR(pp1), type_typed_object);
check_object(p, seg, s, aftergc);
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_object(p)));
}
}
pp1 += 1;
}
} else
pp1 += ptr_alignment;
}
}
/* further verify that dirty bits are set appropriately; only handles some spaces
to make sure that the dirty byte is not unnecessarily approximate, but we have also
checked dirty bytes alerady via `check_pointer` */
if (s == space_impure || s == space_symbol || s == space_weakpair || s == space_ephemeron
|| s == space_immobile_impure || s == space_closure) {
found_eos = 0;
pp2 = pp1 = TO_VOIDP(build_ptr(seg, 0));
for (d = 0; d < cards_per_segment; d += 1) {
if (found_eos) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Dirty byte set past end-of-segment for segment "PHtx", card %d\n", (ptrdiff_t)seg, d);
segment_tell(seg);
}
} else if (s == space_continuation) {
while (pp1 < pp2) {
if (*pp1 == forward_marker)
break;
if (!si->marked_mask || (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1)))) {
p = TYPE(TO_PTR(pp1), type_closure);
check_object(p, seg, s, aftergc);
}
continue;
pp1 = TO_VOIDP((ptr)((uptr)TO_PTR(pp1) + size_continuation));
}
pp2 += bytes_per_card / sizeof(ptr);
if (pp1 <= nl && nl < pp2) {
found_eos = 1;
pp2 = nl;
}
#ifdef DEBUG
printf("pp1 = "PHtx", pp2 = "PHtx", nl = "PHtx"\n", (ptrdiff_t)pp1, (ptrdiff_t)pp2, (ptrdiff_t)nl);
fflush(stdout);
#endif
dirty = 0xff;
} else {
while (pp1 < pp2) {
if (!si->marked_mask || (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1)))) {
int a;
for (a = 0; (a < ptr_alignment) && (pp1 < pp2); a++) {
#define in_ephemeron_pair_part(pp1, seg) ((((uptr)TO_PTR(pp1) - (uptr)build_ptr(seg, 0)) % size_ephemeron) < size_pair)
if ((s == space_ephemeron) && !in_ephemeron_pair_part(pp1, seg)) {
/* skip non-pair part of ephemeron */
} else {
p = *pp1;
if (p == forward_marker) {
found_eos = 1;
pp1 = pp2;
if (!si->marked_mask && (p == forward_marker)) {
pp1 = pp2; /* break out of outer loop */
break;
} else if (!IMMEDIATE(p)) {
seginfo *psi = MaybeSegInfo(ptr_get_segment(p));
if ((psi != NULL) && ((pg = psi->generation) < g)) {
if (pg < dirty) dirty = pg;
if (si->dirty_bytes[d] > pg) {
S_checkheap_errors += 1;
check_heap_dirty_msg("!!! INVALID", pp1);
} else if (checkheap_noisy)
check_heap_dirty_msg("... ", pp1);
}
} else {
check_pointer(pp1, 1, (ptr)0, seg, s, aftergc);
}
}
pp1 += 1;
}
} else {
} else
pp1 += ptr_alignment;
}
}
if (checkheap_noisy && si->dirty_bytes[d] < dirty) {
/* sweep_dirty won't sweep, and update dirty byte, for
cards with dirty pointers to segments older than the
maximum copyied generation, so we can get legitimate
conservative dirty bytes even after gc */
printf("... Conservative dirty byte %x (%x) %sfor segment "PHtx" card %d ",
si->dirty_bytes[d], dirty,
(aftergc ? "after gc " : ""),
(ptrdiff_t)seg, d);
segment_tell(seg);
}
}
} else {
/* at least check that no dirty bytes are set beyond the end of the segment */
if (pp2 < (ptr *)TO_VOIDP(build_ptr(seg + 1, 0))) {
uptr card = (uptr)TO_PTR(pp2) >> card_offset_bits;
int d = (int)(card & ((1 << segment_card_offset_bits) - 1));
for (d++; d < cards_per_segment; d++) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Dirty byte set past end-of-segment for segment "PHtx", card %d\n", (ptrdiff_t)seg, d);
/* further verify that dirty bits are set appropriately; only handles some spaces
to make sure that the dirty byte is not unnecessarily approximate, but we have also
checked dirty bytes alerady via `check_pointer` */
if (s == space_impure || s == space_symbol || s == space_weakpair || s == space_ephemeron
|| s == space_immobile_impure || s == space_closure) {
found_eos = 0;
pp2 = pp1 = TO_VOIDP(build_ptr(seg, 0));
for (d = 0; d < cards_per_segment; d += 1) {
if (found_eos) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Dirty byte set past end-of-segment for segment "PHtx", card %d\n", (ptrdiff_t)seg, d);
segment_tell(seg);
}
continue;
}
pp2 += bytes_per_card / sizeof(ptr);
if (pp1 <= nl && nl < pp2) {
found_eos = 1;
pp2 = nl;
}
#ifdef DEBUG
printf("pp1 = "PHtx", pp2 = "PHtx", nl = "PHtx"\n", (ptrdiff_t)pp1, (ptrdiff_t)pp2, (ptrdiff_t)nl);
fflush(stdout);
#endif
dirty = 0xff;
while (pp1 < pp2) {
if (!si->marked_mask || (si->marked_mask[segment_bitmap_byte(TO_PTR(pp1))] & segment_bitmap_bit(TO_PTR(pp1)))) {
int a;
for (a = 0; (a < ptr_alignment) && (pp1 < pp2); a++) {
if ((s == space_ephemeron) && !in_ephemeron_pair_part(pp1, seg)) {
/* skip non-pair part of ephemeron */
} else {
p = *pp1;
if (p == forward_marker) {
found_eos = 1;
pp1 = pp2;
break;
} else if (!IMMEDIATE(p)) {
seginfo *psi = MaybeSegInfo(ptr_get_segment(p));
if ((psi != NULL) && ((pg = psi->generation) < g)) {
if (pg < dirty) dirty = pg;
if (si->dirty_bytes[d] > pg) {
S_checkheap_errors += 1;
check_heap_dirty_msg("!!! INVALID", pp1);
} else if (checkheap_noisy)
check_heap_dirty_msg("... ", pp1);
}
}
}
pp1 += 1;
}
} else {
pp1 += ptr_alignment;
}
}
if (checkheap_noisy && si->dirty_bytes[d] < dirty) {
/* sweep_dirty won't sweep, and update dirty byte, for
cards with dirty pointers to segments older than the
maximum copyied generation, so we can get legitimate
conservative dirty bytes even after gc */
printf("... Conservative dirty byte %x (%x) %sfor segment "PHtx" card %d ",
si->dirty_bytes[d], dirty,
(aftergc ? "after gc " : ""),
(ptrdiff_t)seg, d);
segment_tell(seg);
}
}
} else {
/* at least check that no dirty bytes are set beyond the end of the segment */
if (pp2 < (ptr *)TO_VOIDP(build_ptr(seg + 1, 0))) {
uptr card = (uptr)TO_PTR(pp2) >> card_offset_bits;
int d = (int)(card & ((1 << segment_card_offset_bits) - 1));
for (d++; d < cards_per_segment; d++) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Dirty byte set past end-of-segment for segment "PHtx", card %d\n", (ptrdiff_t)seg, d);
segment_tell(seg);
}
}
}
}
}
if (aftergc
&& (s != space_empty)
&& (g == 0
|| (s != space_new && s != space_impure && s != space_symbol && s != space_port && s != space_weakpair && s != space_ephemeron
&& s != space_impure_record && s != space_impure_typed_object
&& s != space_immobile_impure && s != space_count_impure && s != space_closure))) {
for (d = 0; d < cards_per_segment; d += 1) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Unnecessary dirty byte %x (%x) after gc for segment "PHtx" card %d ",
si->dirty_bytes[d], 0xff, (ptrdiff_t)(si->number), d);
segment_tell(seg);
}
}
}
}
if (aftergc
&& (s != space_empty)
&& (g == 0
|| (s != space_new && s != space_impure && s != space_symbol && s != space_port && s != space_weakpair && s != space_ephemeron
&& s != space_impure_record && s != space_impure_typed_object
&& s != space_immobile_impure && s != space_count_impure && s != space_closure))) {
for (d = 0; d < cards_per_segment; d += 1) {
if (si->dirty_bytes[d] != 0xff) {
S_checkheap_errors += 1;
printf("!!! Unnecessary dirty byte %x (%x) after gc for segment "PHtx" card %d ",
si->dirty_bytes[d], 0xff, (ptrdiff_t)(si->number), d);
segment_tell(seg);
}
}
}
chunk = chunk->next;
}
chunk = chunk->next;
}
}

View File

@ -275,6 +275,10 @@ static ptr sorted_chunk_list(void) {
ls = Scons(TO_PTR(chunk), ls);
n += 1;
}
for (chunk = (i == -1) ? S_code_chunks_full : S_code_chunks[i]; chunk != NULL; chunk = chunk->next) {
ls = Scons(TO_PTR(chunk), ls);
n += 1;
}
}
return sort_chunks(ls, n);