source: tests/collections/string-gc.cfa @ b59c21a

Last change on this file since b59c21a was 7b0e8b7, checked in by Michael Brooks <mlbrooks@…>, 3 years ago

String heap growth implemented

  • Property mode set to 100644
File size: 4.2 KB
Line 
1#include <string_res.hfa>
2
3size_t bytesRemaining() {
4    return DEBUG_string_bytes_avail_until_gc( DEBUG_string_heap() );
5}
6
7size_t heapOffsetStart( string_res & s ) {
8    const char * startByte = DEBUG_string_heap_start( DEBUG_string_heap() );
9    assert( s.Handle.s >= startByte );
10    return s.Handle.s - startByte;
11}
12
13void prtStrRep(const char * label, string_res & s) {
14    sout | label | "from" | heapOffsetStart(s) | "to" | (heapOffsetStart(s) + size(s));
15}
16#define PRT_STR_REP(s) prtStrRep( #s, s )
17
18void basicFillCompact() {
19    sout | "======================== basicFillCompact";
20    string_res xinit = "hello!";
21    string_res x = {xinit, COPY_VALUE};
22    string_res padder = "----|";
23    sout | x;
24    for( 3 ) {
25        x += padder;
26        sout | x;
27    }
28
29    // x and padder overlap
30    sout | "--A";
31    sout | "length of x:" | size(x);
32    PRT_STR_REP(padder);
33    PRT_STR_REP(x);
34
35    while ( bytesRemaining() + 1 > 5 ) { // until room for "q" but not another "----|" thereafter
36        x += padder;
37    }
38
39    // x and padder still overlap; now x is huge
40    sout | "--B";
41    sout | "length of x:" | size(x);
42    PRT_STR_REP(padder);
43    PRT_STR_REP(x);
44
45    assert( bytesRemaining() >= 1 );
46    x = "q";
47
48    // x and padder no longer overlap; baseline xinit
49    sout | "--C";
50    PRT_STR_REP(xinit);
51    PRT_STR_REP(padder);
52    PRT_STR_REP(x);
53
54    // want the next edit to straddle the bound
55    assert( bytesRemaining() < size(padder) );
56
57    sout | "--D";
58    sout | "before append, x = " | x;     // q
59    x += padder;                         // trigger compaction
60    sout | "after append, x = " | x;      // q----|
61
62    // x and padder moved to the start
63    sout | "--E";
64    PRT_STR_REP(xinit);
65    PRT_STR_REP(padder);
66    PRT_STR_REP(x);
67
68    // plenty of room now
69    sout | "--F";
70    sout | bytesRemaining() | "bytes available before re-fill";
71
72    // fill it again
73    string_res z = "zzz";
74    while ( bytesRemaining() > 1 ) {
75        z += ".";
76    }
77
78    sout | bytesRemaining() | "bytes available after re-fill";
79
80    // ensure not affected (shows it's not referencing an invalid location that hadn't been overwritten from the original value yet)
81    // black-box criterion that matches earlier "saw it move"
82    sout | "--G";
83    sout | "after re-fill, x = " | x;      // q----|
84
85    // leave the heap basically empty, for the next test
86    z = "";                        // turn used space into gargbage
87    string_res whatever = "asdf";  // trigger compaction
88    assert( bytesRemaining() > 100 );
89}
90
91void fillCompact_withSharedEdits() {
92    // do an assignment that causes a collection to happen, while there are edits shared (substrings)
93
94    sout | "======================== fillCompact_withSharedEdits";
95
96    // mostly fill the pad
97    string_res z = "zzz";
98    while ( bytesRemaining() > 10 ) {
99        z += ".";
100    }
101    z = "";  // leave compaction possible
102
103    // setup
104    string_res x = "hello";
105    string_res y = { x, SHARE_EDITS, 0, 5 };
106    PRT_STR_REP(x);
107    PRT_STR_REP(y);
108    sout | "-";
109
110    sout | "before reassign, x = " | x;     // hello
111    sout | "before reassign, y = " | y;     // hello
112
113    x = "0123456789"; // compact here
114
115    sout | "after reassign, x = " | x;      // 0123456789
116    sout | "after reassign, y = " | y;      // 0123456789
117
118    PRT_STR_REP(x);
119    PRT_STR_REP(y);
120}
121
122void fillNoCompact() {
123    // show that allocating in a heap filled with mostly live strings (no collectable garbage) causes heap growth
124
125    sout | "======================== fillNoCompact";
126
127    size_t lastTimeBytesAvail = bytesRemaining();
128    assert( lastTimeBytesAvail >= 200 ); // starting this test with nontrivial room
129
130    // mostly fill the pad
131    string_res a = "aaa";  // will have to be moved
132    string_res z = "zzz";
133    for (i; 5) {
134        while ( bytesRemaining() > 10 ) {
135            z += ".";
136        }
137        sout | "about to expand, a = " | a;
138        while ( bytesRemaining() <= 10 ) {
139            z += ".";
140        }
141        sout | "expanded, a = " | a;
142
143        // each growth gives more usable space than the last
144        assert( bytesRemaining() > lastTimeBytesAvail );
145        lastTimeBytesAvail = bytesRemaining();
146    }
147}
148
149int main() {
150    basicFillCompact();
151    fillCompact_withSharedEdits();
152    fillNoCompact();
153}
Note: See TracBrowser for help on using the repository browser.