27
27
#include " threadHelper.inline.hpp"
28
28
#include " unittest.hpp"
29
29
30
+ // Helper to avoid interference from the cleanup delay queue by draining it
31
+ // immediately after creation.
32
+ TempNewSymbol stable_temp_symbol (Symbol* sym) {
33
+ TempNewSymbol t = sym;
34
+ TempSymbolCleanupDelayer::drain_queue ();
35
+ return t;
36
+ }
37
+
30
38
TEST_VM (SymbolTable, temp_new_symbol) {
31
39
// Assert messages assume these symbols are unique, and the refcounts start at
32
40
// one, but code does not rely on this.
@@ -36,7 +44,7 @@ TEST_VM(SymbolTable, temp_new_symbol) {
36
44
37
45
Symbol* abc = SymbolTable::new_symbol (" abc" );
38
46
int abccount = abc->refcount ();
39
- TempNewSymbol ss = abc;
47
+ TempNewSymbol ss = stable_temp_symbol ( abc) ;
40
48
ASSERT_EQ (ss->refcount (), abccount) << " only one abc" ;
41
49
ASSERT_EQ (ss->refcount (), abc->refcount ()) << " should match TempNewSymbol" ;
42
50
@@ -45,8 +53,8 @@ TEST_VM(SymbolTable, temp_new_symbol) {
45
53
int efgcount = efg->refcount ();
46
54
int hijcount = hij->refcount ();
47
55
48
- TempNewSymbol s1 = efg;
49
- TempNewSymbol s2 = hij;
56
+ TempNewSymbol s1 = stable_temp_symbol ( efg) ;
57
+ TempNewSymbol s2 = stable_temp_symbol ( hij) ;
50
58
ASSERT_EQ (s1->refcount (), efgcount) << " one efg" ;
51
59
ASSERT_EQ (s2->refcount (), hijcount) << " one hij" ;
52
60
@@ -65,13 +73,13 @@ TEST_VM(SymbolTable, temp_new_symbol) {
65
73
TempNewSymbol s3;
66
74
Symbol* klm = SymbolTable::new_symbol (" klm" );
67
75
int klmcount = klm->refcount ();
68
- s3 = klm; // assignment
76
+ s3 = stable_temp_symbol ( klm) ; // assignment
69
77
ASSERT_EQ (s3->refcount (), klmcount) << " only one klm now" ;
70
78
71
79
Symbol* xyz = SymbolTable::new_symbol (" xyz" );
72
80
int xyzcount = xyz->refcount ();
73
81
{ // inner scope
74
- TempNewSymbol s_inner = xyz;
82
+ TempNewSymbol s_inner = stable_temp_symbol ( xyz) ;
75
83
}
76
84
ASSERT_EQ (xyz->refcount (), xyzcount - 1 )
77
85
<< " Should have been decremented by dtor in inner scope" ;
@@ -139,3 +147,50 @@ TEST_VM(SymbolTable, test_cleanup_leak) {
139
147
140
148
ASSERT_EQ (entry2->refcount (), 1 ) << " Symbol refcount just created is 1" ;
141
149
}
150
+
151
+ TEST_VM (SymbolTable, test_cleanup_delay) {
152
+ // Check that new temp symbols have an extra refcount increment, which is then
153
+ // decremented when the queue spills over.
154
+
155
+ TempNewSymbol s1 = SymbolTable::new_symbol (" temp-s1" );
156
+ ASSERT_EQ (s1->refcount (), 2 ) << " TempNewSymbol refcount just created is 2" ;
157
+
158
+ // Fill up the queue
159
+ constexpr int symbol_name_length = 30 ;
160
+ char symbol_name[symbol_name_length];
161
+ for (uint i = 1 ; i < TempSymbolCleanupDelayer::QueueSize; i++) {
162
+ os::snprintf (symbol_name, symbol_name_length, " temp-filler-%d" , i);
163
+ TempNewSymbol s = SymbolTable::new_symbol (symbol_name);
164
+ ASSERT_EQ (s->refcount (), 2 ) << " TempNewSymbol refcount just created is 2" ;
165
+ }
166
+
167
+ // Add one more
168
+ TempNewSymbol spillover = SymbolTable::new_symbol (" temp-spillover" );
169
+ ASSERT_EQ (spillover->refcount (), 2 ) << " TempNewSymbol refcount just created is 2" ;
170
+
171
+ // The first symbol should have been removed from the queue and decremented
172
+ ASSERT_EQ (s1->refcount (), 1 ) << " TempNewSymbol off queue refcount is 1" ;
173
+ }
174
+
175
+ TEST_VM (SymbolTable, test_cleanup_delay_drain) {
176
+ // Fill up the queue
177
+ constexpr int symbol_name_length = 30 ;
178
+ char symbol_name[symbol_name_length];
179
+ TempNewSymbol symbols[TempSymbolCleanupDelayer::QueueSize] = {};
180
+ for (uint i = 0 ; i < TempSymbolCleanupDelayer::QueueSize; i++) {
181
+ os::snprintf (symbol_name, symbol_name_length, " temp-%d" , i);
182
+ TempNewSymbol s = SymbolTable::new_symbol (symbol_name);
183
+ symbols[i] = s;
184
+ }
185
+
186
+ // While in the queue refcounts are incremented
187
+ for (uint i = 0 ; i < TempSymbolCleanupDelayer::QueueSize; i++) {
188
+ ASSERT_EQ (symbols[i]->refcount (), 2 ) << " TempNewSymbol refcount in queue is 2" ;
189
+ }
190
+
191
+ // Draining the queue should decrement the refcounts
192
+ TempSymbolCleanupDelayer::drain_queue ();
193
+ for (uint i = 0 ; i < TempSymbolCleanupDelayer::QueueSize; i++) {
194
+ ASSERT_EQ (symbols[i]->refcount (), 1 ) << " TempNewSymbol refcount after drain is 1" ;
195
+ }
196
+ }
0 commit comments