@agoric/xsnap 0.14.3-u14.0 → 0.14.3-u16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +3 -3
  2. package/api.js +4 -2
  3. package/build.env +1 -1
  4. package/moddable/modules/data/base64/base64.js +28 -0
  5. package/moddable/modules/data/base64/manifest.json +11 -0
  6. package/moddable/modules/data/base64/modBase64.c +188 -0
  7. package/moddable/modules/data/binaryMessage/BinaryMessage.js +106 -0
  8. package/moddable/modules/data/crc/crc.c +205 -0
  9. package/moddable/modules/data/crc/crc.js +36 -0
  10. package/moddable/modules/data/crc/manifest.json +8 -0
  11. package/moddable/modules/data/hex/hex.js +28 -0
  12. package/moddable/modules/data/hex/manifest.json +11 -0
  13. package/moddable/modules/data/hex/modHex.c +139 -0
  14. package/moddable/modules/data/logical/logical.js +32 -0
  15. package/moddable/modules/data/logical/modLogical.c +98 -0
  16. package/moddable/modules/data/qrcode/manifest.json +9 -0
  17. package/moddable/modules/data/qrcode/qrcode.c +93 -0
  18. package/moddable/modules/data/qrcode/qrcode.js +23 -0
  19. package/moddable/modules/data/qrcode/qrcodegen.c +1025 -0
  20. package/moddable/modules/data/qrcode/qrcodegen.h +267 -0
  21. package/moddable/modules/data/text/decoder/manifest.json +8 -0
  22. package/moddable/modules/data/text/decoder/textdecoder.c +480 -0
  23. package/moddable/modules/data/text/decoder/textdecoder.js +27 -0
  24. package/moddable/modules/data/text/encoder/manifest.json +8 -0
  25. package/moddable/modules/data/text/encoder/textencoder.c +232 -0
  26. package/moddable/modules/data/text/encoder/textencoder.js +24 -0
  27. package/moddable/modules/data/tinyint/tinyint.c +150 -0
  28. package/moddable/modules/data/tinyint/tinyint.js +53 -0
  29. package/moddable/modules/data/url/manifest.json +17 -0
  30. package/moddable/modules/data/url/url.c +1959 -0
  31. package/moddable/modules/data/url/url.js +210 -0
  32. package/moddable/modules/data/wavreader/manifest.json +8 -0
  33. package/moddable/modules/data/wavreader/wavreader.js +128 -0
  34. package/moddable/modules/data/zlib/deflate.c +161 -0
  35. package/moddable/modules/data/zlib/deflate.js +63 -0
  36. package/moddable/modules/data/zlib/inflate.c +145 -0
  37. package/moddable/modules/data/zlib/inflate.js +66 -0
  38. package/moddable/modules/data/zlib/manifest_deflate.json +9 -0
  39. package/moddable/modules/data/zlib/manifest_inflate.json +9 -0
  40. package/moddable/modules/data/zlib/miniz.c +4924 -0
  41. package/moddable/xs/includes/xs.d.ts +73 -0
  42. package/moddable/xs/includes/xs.h +1533 -0
  43. package/moddable/xs/includes/xsmc.h +206 -0
  44. package/moddable/xs/makefiles/lin/makefile +33 -0
  45. package/moddable/xs/makefiles/lin/xsc.mk +118 -0
  46. package/moddable/xs/makefiles/lin/xsid.mk +90 -0
  47. package/moddable/xs/makefiles/lin/xsl.mk +168 -0
  48. package/moddable/xs/makefiles/lin/xst.mk +201 -0
  49. package/moddable/xs/makefiles/mac/makefile +33 -0
  50. package/moddable/xs/makefiles/mac/xsc.mk +130 -0
  51. package/moddable/xs/makefiles/mac/xsid.mk +102 -0
  52. package/moddable/xs/makefiles/mac/xsl.mk +177 -0
  53. package/moddable/xs/makefiles/mac/xst.mk +203 -0
  54. package/moddable/xs/makefiles/mac/xst_no_asan.txt +52 -0
  55. package/moddable/xs/makefiles/win/build.bat +26 -0
  56. package/moddable/xs/makefiles/win/xsc.mak +142 -0
  57. package/moddable/xs/makefiles/win/xsid.mak +113 -0
  58. package/moddable/xs/makefiles/win/xsl.mak +186 -0
  59. package/moddable/xs/makefiles/win/xst.mak +195 -0
  60. package/moddable/xs/platforms/lin_xs.h +99 -0
  61. package/moddable/xs/platforms/mac_xs.h +97 -0
  62. package/moddable/xs/platforms/wasm_xs.h +79 -0
  63. package/moddable/xs/platforms/win_xs.h +104 -0
  64. package/moddable/xs/platforms/xsHost.h +63 -0
  65. package/moddable/xs/platforms/xsPlatform.h +618 -0
  66. package/moddable/xs/sources/xsAPI.c +2555 -0
  67. package/moddable/xs/sources/xsAll.c +294 -0
  68. package/moddable/xs/sources/xsAll.h +2741 -0
  69. package/moddable/xs/sources/xsArguments.c +222 -0
  70. package/moddable/xs/sources/xsArray.c +2657 -0
  71. package/moddable/xs/sources/xsAtomics.c +844 -0
  72. package/moddable/xs/sources/xsBigInt.c +1859 -0
  73. package/moddable/xs/sources/xsBoolean.c +109 -0
  74. package/moddable/xs/sources/xsCode.c +4493 -0
  75. package/moddable/xs/sources/xsCommon.c +1710 -0
  76. package/moddable/xs/sources/xsCommon.h +1142 -0
  77. package/moddable/xs/sources/xsDataView.c +2890 -0
  78. package/moddable/xs/sources/xsDate.c +1541 -0
  79. package/moddable/xs/sources/xsDebug.c +2710 -0
  80. package/moddable/xs/sources/xsDefaults.c +134 -0
  81. package/moddable/xs/sources/xsError.c +353 -0
  82. package/moddable/xs/sources/xsFunction.c +776 -0
  83. package/moddable/xs/sources/xsGenerator.c +865 -0
  84. package/moddable/xs/sources/xsGlobal.c +839 -0
  85. package/moddable/xs/sources/xsJSON.c +1091 -0
  86. package/moddable/xs/sources/xsLexical.c +1969 -0
  87. package/moddable/xs/sources/xsLockdown.c +933 -0
  88. package/moddable/xs/sources/xsMapSet.c +1649 -0
  89. package/moddable/xs/sources/xsMarshall.c +1020 -0
  90. package/moddable/xs/sources/xsMath.c +624 -0
  91. package/moddable/xs/sources/xsMemory.c +1941 -0
  92. package/moddable/xs/sources/xsModule.c +3101 -0
  93. package/moddable/xs/sources/xsNumber.c +560 -0
  94. package/moddable/xs/sources/xsObject.c +1102 -0
  95. package/moddable/xs/sources/xsPlatforms.c +480 -0
  96. package/moddable/xs/sources/xsProfile.c +577 -0
  97. package/moddable/xs/sources/xsPromise.c +1199 -0
  98. package/moddable/xs/sources/xsProperty.c +636 -0
  99. package/moddable/xs/sources/xsProxy.c +1014 -0
  100. package/moddable/xs/sources/xsRegExp.c +1168 -0
  101. package/moddable/xs/sources/xsRun.c +4889 -0
  102. package/moddable/xs/sources/xsScope.c +1293 -0
  103. package/moddable/xs/sources/xsScript.c +288 -0
  104. package/moddable/xs/sources/xsScript.h +1186 -0
  105. package/moddable/xs/sources/xsSnapshot.c +2161 -0
  106. package/moddable/xs/sources/xsSnapshot.h +51 -0
  107. package/moddable/xs/sources/xsSourceMap.c +218 -0
  108. package/moddable/xs/sources/xsString.c +3332 -0
  109. package/moddable/xs/sources/xsSymbol.c +503 -0
  110. package/moddable/xs/sources/xsSyntaxical.c +4193 -0
  111. package/moddable/xs/sources/xsTree.c +1893 -0
  112. package/moddable/xs/sources/xsType.c +1488 -0
  113. package/moddable/xs/sources/xsdtoa.c +6672 -0
  114. package/moddable/xs/sources/xsmc.c +340 -0
  115. package/moddable/xs/sources/xsre.c +7578 -0
  116. package/package.json +37 -20
  117. package/scripts/get_xsnap_version.sh +14 -0
  118. package/scripts/test-package.sh +21 -0
  119. package/src/avaAssertXS.js +6 -2
  120. package/src/avaHandler.cjs +2 -5
  121. package/src/avaXS.js +7 -8
  122. package/src/build.js +161 -28
  123. package/src/replay.js +0 -3
  124. package/src/xsnap.js +105 -91
  125. package/src/xsrepl.js +2 -3
  126. package/xsnap-native/xsnap/makefiles/lin/makefile +10 -0
  127. package/xsnap-native/xsnap/makefiles/lin/xsnap-worker.mk +156 -0
  128. package/xsnap-native/xsnap/makefiles/lin/xsnap.mk +144 -0
  129. package/xsnap-native/xsnap/makefiles/mac/makefile +10 -0
  130. package/xsnap-native/xsnap/makefiles/mac/xsnap-worker.mk +165 -0
  131. package/xsnap-native/xsnap/makefiles/mac/xsnap.mk +153 -0
  132. package/xsnap-native/xsnap/sources/xsnap-worker.c +1008 -0
  133. package/xsnap-native/xsnap/sources/xsnap.c +717 -0
  134. package/xsnap-native/xsnap/sources/xsnap.h +142 -0
  135. package/xsnap-native/xsnap/sources/xsnapPlatform.c +1501 -0
  136. package/xsnap-native/xsnap/sources/xsnapPlatform.h +105 -0
  137. package/CHANGELOG.md +0 -654
@@ -0,0 +1,1941 @@
1
+ /*
2
+ * Copyright (c) 2016-2017 Moddable Tech, Inc.
3
+ *
4
+ * This file is part of the Moddable SDK Runtime.
5
+ *
6
+ * The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU Lesser General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ * This file incorporates work covered by the following copyright and
20
+ * permission notice:
21
+ *
22
+ * Copyright (C) 2010-2016 Marvell International Ltd.
23
+ * Copyright (C) 2002-2010 Kinoma, Inc.
24
+ *
25
+ * Licensed under the Apache License, Version 2.0 (the "License");
26
+ * you may not use this file except in compliance with the License.
27
+ * You may obtain a copy of the License at
28
+ *
29
+ * http://www.apache.org/licenses/LICENSE-2.0
30
+ *
31
+ * Unless required by applicable law or agreed to in writing, software
32
+ * distributed under the License is distributed on an "AS IS" BASIS,
33
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+ * See the License for the specific language governing permissions and
35
+ * limitations under the License.
36
+ */
37
+
38
+ #include "xsAll.h"
39
+
40
+ #ifndef mxReport
41
+ #define mxReport 0
42
+ #endif
43
+ #ifndef mxStress
44
+ #define mxStress 0
45
+ #endif
46
+ #ifndef mxNoChunks
47
+ #define mxNoChunks 0
48
+ #endif
49
+ #ifndef mxPoisonSlots
50
+ #define mxPoisonSlots 0
51
+ #endif
52
+
53
+ #if mxPoisonSlots
54
+ #include <sanitizer/asan_interface.h>
55
+ #endif
56
+
57
+ #if mxStress
58
+ int gxStress = 0;
59
+
60
+ static int fxShouldStress()
61
+ {
62
+ if (!gxStress)
63
+ return 0;
64
+
65
+ if (gxStress > 0)
66
+ return 1;
67
+
68
+ gxStress += 1;
69
+ return 0 == gxStress;
70
+ }
71
+ #endif
72
+
73
+ #define mxChunkFlag 0x80000000
74
+
75
+ static txSize fxAdjustChunkSize(txMachine* the, txSize size);
76
+ static void* fxCheckChunk(txMachine* the, txChunk* chunk, txSize size, txSize offset);
77
+ static void* fxFindChunk(txMachine* the, txSize size, txBoolean *once);
78
+ static void* fxGrowChunk(txMachine* the, txSize size);
79
+ static void* fxGrowChunks(txMachine* the, txSize theSize);
80
+ /* static */ void fxGrowSlots(txMachine* the, txSize theCount);
81
+ static void fxMark(txMachine* the, void (*theMarker)(txMachine*, txSlot*));
82
+ static void fxMarkFinalizationRegistry(txMachine* the, txSlot* registry);
83
+ static void fxMarkInstance(txMachine* the, txSlot* theCurrent, void (*theMarker)(txMachine*, txSlot*));
84
+ static void fxMarkReference(txMachine* the, txSlot* theSlot);
85
+ static void fxMarkValue(txMachine* the, txSlot* theSlot);
86
+ static void fxMarkWeakStuff(txMachine* the);
87
+ static void fxSweep(txMachine* the);
88
+ static void fxSweepValue(txMachine* the, txSlot* theSlot);
89
+
90
+ #ifdef mxNever
91
+
92
+ long gxRenewChunkCases[4] = { 0, 0, 0, 0 };
93
+
94
+ typedef struct sxSample txSample;
95
+ struct sxSample {
96
+ txNumber time;
97
+ txNumber duration;
98
+ long count;
99
+ char* label;
100
+ };
101
+
102
+ void reportTime(txSample* theSample)
103
+ {
104
+ txNumber duration = theSample->duration;
105
+ txNumber minutes;
106
+ txNumber seconds;
107
+
108
+ minutes = c_floor(duration / 60000000);
109
+ duration -= minutes * 60000000;
110
+ seconds = c_floor(duration / 1000000);
111
+ duration -= seconds * 1000000;
112
+ duration = c_floor(duration / 1000);
113
+ fprintf(stderr, "%s * %ld = %ld:%02ld.%03ld\n", theSample->label, theSample->count,
114
+ (long)minutes, (long)seconds, (long)duration);
115
+ }
116
+
117
+ void startTime(txSample* theSample)
118
+ {
119
+ c_timeval tv;
120
+ c_gettimeofday(&tv, NULL);
121
+ theSample->time = ((txNumber)(tv.tv_sec) * 1000000.0) + ((txNumber)tv.tv_usec);
122
+ }
123
+
124
+ void stopTime(txSample* theSample)
125
+ {
126
+ c_timeval tv;
127
+ txNumber time;
128
+ c_gettimeofday(&tv, NULL);
129
+ time = ((txNumber)(tv.tv_sec) * 1000000.0) + ((txNumber)tv.tv_usec);
130
+ theSample->duration += time - theSample->time;
131
+ theSample->count++;
132
+ }
133
+
134
+ txSample gxLifeTime = { 0, 0, 0, "life" };
135
+ txSample gxMarkTime = { 0, 0, 0, "mark" };
136
+ txSample gxSweepChunkTime = { 0, 0, 0, "sweep chunk" };
137
+ txSample gxSweepSlotTime = { 0, 0, 0, "sweep slot" };
138
+ txSample gxCompactChunkTime = { 0, 0, 0, "compact chunk" };
139
+
140
+ #endif
141
+
142
+ txSize fxAddChunkSizes(txMachine* the, txSize a, txSize b)
143
+ {
144
+ txSize c;
145
+ #if __has_builtin(__builtin_add_overflow)
146
+ if (__builtin_add_overflow(a, b, &c)) {
147
+ #else
148
+ c = a + b;
149
+ if (((a ^ c) & (b ^ c)) < 0) {
150
+ #endif
151
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
152
+ }
153
+ return c;
154
+ }
155
+
156
+ txSize fxAdjustChunkSize(txMachine* the, txSize size)
157
+ {
158
+ txSize adjust = sizeof(txChunk);
159
+ txSize modulo = size & (sizeof(size_t) - 1);
160
+ if (modulo)
161
+ adjust += sizeof(size_t) - modulo;
162
+ return fxAddChunkSizes(the, size, adjust);
163
+ }
164
+
165
+ void fxAllocate(txMachine* the, txCreation* theCreation)
166
+ {
167
+ #ifdef mxNever
168
+ startTime(&gxLifeTime);
169
+ #endif
170
+ #if mxStress
171
+ gxStress = 0;
172
+ #endif
173
+
174
+ the->currentChunksSize = 0;
175
+ the->peakChunksSize = 0;
176
+ the->maximumChunksSize = 0;
177
+ the->minimumChunksSize = theCreation->incrementalChunkSize;
178
+
179
+ the->currentHeapCount = 0;
180
+ the->peakHeapCount = 0;
181
+ the->maximumHeapCount = 0;
182
+ the->minimumHeapCount = theCreation->incrementalHeapCount;
183
+
184
+ the->firstBlock = C_NULL;
185
+ the->firstHeap = C_NULL;
186
+
187
+ #if mxNoChunks
188
+ #else
189
+ fxGrowChunks(the, theCreation->initialChunkSize);
190
+ #endif
191
+
192
+ the->stackBottom = fxAllocateSlots(the, theCreation->stackCount);
193
+ the->stackTop = the->stackBottom + theCreation->stackCount;
194
+ the->stackPrototypes = the->stackTop;
195
+ the->stack = the->stackTop;
196
+ #ifdef mxInstrument
197
+ the->stackPeak = the->stackTop;
198
+ #endif
199
+
200
+ fxGrowSlots(the, theCreation->initialHeapCount);
201
+
202
+ the->keyCount = (txID)theCreation->initialKeyCount;
203
+ the->keyDelta = (txID)theCreation->incrementalKeyCount;
204
+ the->keyIndex = 0;
205
+ the->keyArray = (txSlot **)c_malloc_uint32(theCreation->initialKeyCount * sizeof(txSlot*));
206
+ if (!the->keyArray)
207
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
208
+
209
+ the->nameModulo = theCreation->nameModulo;
210
+ the->nameTable = (txSlot **)c_malloc_uint32(theCreation->nameModulo * sizeof(txSlot*));
211
+ if (!the->nameTable)
212
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
213
+
214
+ the->symbolModulo = theCreation->symbolModulo;
215
+ the->symbolTable = (txSlot **)c_malloc_uint32(theCreation->symbolModulo * sizeof(txSlot*));
216
+ if (!the->symbolTable)
217
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
218
+
219
+ the->stackLimit = fxCStackLimit();
220
+
221
+ the->cRoot = C_NULL;
222
+ the->parserBufferSize = theCreation->parserBufferSize;
223
+ the->parserTableModulo = theCreation->parserTableModulo;
224
+ }
225
+
226
+ void* fxCheckChunk(txMachine* the, txChunk* chunk, txSize size, txSize offset)
227
+ {
228
+ if (chunk) {
229
+ txByte* data = (txByte*)chunk;
230
+ #if mxNoChunks
231
+ chunk->size = size;
232
+ the->currentChunksSize += size;
233
+ #else
234
+ txSize capacity = (txSize)(chunk->temporary - data);
235
+ #ifdef mxSnapshot
236
+ #if INTPTR_MAX == INT64_MAX
237
+ chunk->dummy = 0;
238
+ #endif
239
+ #ifdef mxSnapshotRandomInit
240
+ arc4random_buf(data + sizeof(txChunk), offset);
241
+ #endif
242
+ offset += sizeof(txChunk);
243
+ c_memset(data + offset, 0, capacity - offset);
244
+ #endif
245
+ chunk->size = size;
246
+ the->currentChunksSize += capacity;
247
+ #endif
248
+ if (the->peakChunksSize < the->currentChunksSize)
249
+ the->peakChunksSize = the->currentChunksSize;
250
+ return data + sizeof(txChunk);
251
+ }
252
+ fxReport(the, "# Chunk allocation: failed for %ld bytes\n", (long)size);
253
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
254
+ return C_NULL;
255
+ }
256
+
257
+ void fxCheckCStack(txMachine* the)
258
+ {
259
+ char x;
260
+ char *stack = &x;
261
+ if (stack <= the->stackLimit) {
262
+ fxAbort(the, XS_STACK_OVERFLOW_EXIT);
263
+ }
264
+ }
265
+
266
+ void fxCollect(txMachine* the, txFlag theFlag)
267
+ {
268
+ txSize aCount;
269
+ txSlot* freeSlot;
270
+ txSlot* aSlot;
271
+ txSlot* bSlot;
272
+ txSlot* cSlot;
273
+
274
+ if ((the->collectFlag & XS_COLLECTING_FLAG) == 0) {
275
+ the->collectFlag |= XS_SKIPPED_COLLECT_FLAG;
276
+ return;
277
+ }
278
+ the->collectFlag |= theFlag & XS_ORGANIC_FLAG;
279
+
280
+ if (theFlag & XS_COMPACT_FLAG) {
281
+ fxMark(the, fxMarkValue);
282
+ fxMarkWeakStuff(the);
283
+ fxSweep(the);
284
+ }
285
+ else {
286
+ fxMark(the, fxMarkReference);
287
+ fxMarkWeakStuff(the);
288
+ #ifdef mxNever
289
+ startTime(&gxSweepSlotTime);
290
+ #endif
291
+ aCount = 0;
292
+ freeSlot = C_NULL;
293
+ aSlot = the->firstHeap;
294
+ while (aSlot) {
295
+ bSlot = aSlot + 1;
296
+ cSlot = aSlot->value.reference;
297
+ while (bSlot < cSlot) {
298
+ if (bSlot->flag & XS_MARK_FLAG) {
299
+ bSlot->flag &= ~XS_MARK_FLAG;
300
+
301
+ if (bSlot->kind == XS_REFERENCE_KIND)
302
+ mxCheck(the, bSlot->value.reference->kind == XS_INSTANCE_KIND);
303
+
304
+ aCount++;
305
+ }
306
+ else {
307
+ if (bSlot->kind == XS_HOST_KIND) {
308
+ if (bSlot->flag & XS_HOST_HOOKS_FLAG) {
309
+ if (bSlot->value.host.variant.hooks->destructor)
310
+ (*(bSlot->value.host.variant.hooks->destructor))(bSlot->value.host.data);
311
+ }
312
+ else if (bSlot->value.host.variant.destructor)
313
+ (*(bSlot->value.host.variant.destructor))(bSlot->value.host.data);
314
+ }
315
+ #if mxInstrument
316
+ if (bSlot->kind == XS_MODULE_KIND)
317
+ the->loadedModulesCount--;
318
+ #endif
319
+ bSlot->kind = XS_UNDEFINED_KIND;
320
+ bSlot->next = freeSlot;
321
+ #if mxPoisonSlots
322
+ ASAN_POISON_MEMORY_REGION(&bSlot->value, sizeof(bSlot->value));
323
+ #endif
324
+ freeSlot = bSlot;
325
+ }
326
+ bSlot++;
327
+ }
328
+ aSlot = aSlot->next;
329
+ }
330
+ the->currentHeapCount = aCount;
331
+ the->freeHeap = freeSlot;
332
+ #ifdef mxNever
333
+ stopTime(&gxSweepSlotTime);
334
+ #endif
335
+ }
336
+
337
+ aSlot = the->stack;
338
+ while (aSlot < the->stackTop) {
339
+ aSlot->flag &= ~XS_MARK_FLAG;
340
+ aSlot++;
341
+ }
342
+
343
+ if (theFlag)
344
+ the->collectFlag &= ~XS_TRASHING_FLAG;
345
+ else {
346
+ if ((the->maximumHeapCount - the->currentHeapCount) < the->minimumHeapCount)
347
+ the->collectFlag |= XS_TRASHING_FLAG;
348
+ else
349
+ the->collectFlag &= ~XS_TRASHING_FLAG;
350
+ }
351
+ the->collectFlag &= ~XS_ORGANIC_FLAG;
352
+
353
+ #if mxReport
354
+ if (theFlag)
355
+ fxReport(the, "# Chunk collection: reserved %ld used %ld peak %ld bytes\n",
356
+ (long)the->maximumChunksSize, (long)the->currentChunksSize, (long)the->peakChunksSize);
357
+ aCount = 0;
358
+ aSlot = the->firstHeap;
359
+ while (aSlot) {
360
+ aCount++;
361
+ aSlot = aSlot->next;
362
+ }
363
+ fxReport(the, "# Slot collection: reserved %ld used %ld peak %ld bytes %d\n",
364
+ (long)((the->maximumHeapCount - aCount) * sizeof(txSlot)),
365
+ (long)(the->currentHeapCount * sizeof(txSlot)),
366
+ (long)(the->peakHeapCount * sizeof(txSlot)),
367
+ the->collectFlag & XS_TRASHING_FLAG);
368
+ #endif
369
+ #ifdef mxInstrument
370
+ the->garbageCollectionCount++;
371
+ #endif
372
+ #if defined(mxInstrument) || defined(mxProfile)
373
+ fxCheckProfiler(the, C_NULL);
374
+ #endif
375
+ }
376
+
377
+ txSlot* fxDuplicateSlot(txMachine* the, txSlot* theSlot)
378
+ {
379
+ txSlot* result;
380
+
381
+ result = fxNewSlot(the);
382
+ result->ID = theSlot->ID;
383
+ result->kind = theSlot->kind;
384
+ result->flag = theSlot->flag & ~XS_MARK_FLAG;
385
+ result->value = theSlot->value;
386
+ return result;
387
+ }
388
+
389
+ void* fxFindChunk(txMachine* the, txSize size, txBoolean *once)
390
+ {
391
+ txBlock* block;
392
+ txChunk* chunk;
393
+ #if mxStress
394
+ if (fxShouldStress()) {
395
+ if (*once) {
396
+ fxCollect(the, XS_COMPACT_FLAG | XS_ORGANIC_FLAG);
397
+ *once = 0;
398
+ }
399
+ }
400
+ #endif
401
+ #if mxNoChunks
402
+ chunk = c_malloc(size);
403
+ chunk->size = size;
404
+ chunk->temporary = (txByte*)the->firstBlock;
405
+ the->firstBlock = (txBlock*)chunk;
406
+ return chunk;
407
+ #endif
408
+ again:
409
+ block = the->firstBlock;
410
+ while (block) {
411
+ if ((block->current + size) <= block->limit) {
412
+ chunk = (txChunk*)(block->current);
413
+ block->current += size;
414
+ chunk->temporary = block->current;
415
+ return chunk;
416
+ }
417
+ block = block->nextBlock;
418
+ }
419
+ if (*once) {
420
+ fxCollect(the, XS_COMPACT_FLAG | XS_ORGANIC_FLAG);
421
+ *once = 0;
422
+ goto again;
423
+ }
424
+ return C_NULL;
425
+ }
426
+
427
+ void fxFree(txMachine* the)
428
+ {
429
+ txSlot* aHeap;
430
+
431
+ if (the->aliasArray)
432
+ c_free_uint32(the->aliasArray);
433
+ the->aliasArray = C_NULL;
434
+
435
+ if (the->symbolTable)
436
+ c_free_uint32(the->symbolTable);
437
+ the->symbolTable = C_NULL;
438
+ if (the->nameTable)
439
+ c_free_uint32(the->nameTable);
440
+ the->nameTable = C_NULL;
441
+ if (the->keyArray)
442
+ c_free_uint32(the->keyArray);
443
+ the->keyArray = C_NULL;
444
+
445
+ while (the->firstHeap) {
446
+ aHeap = the->firstHeap;
447
+ the->firstHeap = aHeap->next;
448
+ fxFreeSlots(the, aHeap);
449
+ }
450
+ the->firstHeap = C_NULL;
451
+
452
+ if (the->stackBottom)
453
+ fxFreeSlots(the, the->stackBottom);
454
+ the->stackBottom = C_NULL;
455
+ the->stackTop = C_NULL;
456
+ the->stackPrototypes = C_NULL;
457
+ the->stack = C_NULL;
458
+
459
+ #if mxNoChunks
460
+ {
461
+ txChunk** address;
462
+ txChunk* chunk;
463
+ address = (txChunk**)&(the->firstBlock);
464
+ while ((chunk = *address)) {
465
+ *address = (txChunk*)(chunk->temporary);
466
+ c_free(chunk);
467
+ }
468
+ }
469
+ #else
470
+ {
471
+ txBlock* aBlock;
472
+ while (the->firstBlock) {
473
+ aBlock = the->firstBlock;
474
+ the->firstBlock = aBlock->nextBlock;
475
+ fxFreeChunks(the, aBlock);
476
+ }
477
+ the->firstBlock = C_NULL;
478
+ }
479
+ #endif
480
+
481
+ #ifdef mxNever
482
+ stopTime(&gxLifeTime);
483
+ reportTime(&gxLifeTime);
484
+ fprintf(stderr, "chunk: %d bytes\n", the->maximumChunksSize);
485
+ fprintf(stderr, "slot: %ld bytes\n", the->maximumHeapCount * sizeof(txSlot));
486
+ reportTime(&gxMarkTime);
487
+ reportTime(&gxSweepChunkTime);
488
+ reportTime(&gxSweepSlotTime);
489
+ reportTime(&gxCompactChunkTime);
490
+ fprintf(stderr, "renew: %ld %ld %ld %ld\n",
491
+ gxRenewChunkCases[0],
492
+ gxRenewChunkCases[1],
493
+ gxRenewChunkCases[2],
494
+ gxRenewChunkCases[3]);
495
+ #endif
496
+ }
497
+
498
+ void* fxGrowChunk(txMachine* the, txSize size)
499
+ {
500
+ txBlock* block = fxGrowChunks(the, size);
501
+ txChunk* chunk = C_NULL;
502
+ if (block) {
503
+ chunk = (txChunk*)(block->current);
504
+ block->current += size;
505
+ chunk->temporary = block->current;
506
+ }
507
+ return chunk;
508
+ }
509
+
510
+ void* fxGrowChunks(txMachine* the, txSize size)
511
+ {
512
+ txByte* buffer;
513
+ txBlock* block = C_NULL;
514
+
515
+ if (!the->minimumChunksSize && the->firstBlock) {
516
+ fxReport(the, "# Chunk allocation: %d bytes failed in fixed size heap\n", size);
517
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
518
+ }
519
+
520
+ if ((the->firstBlock != C_NULL) && (!(the->collectFlag & XS_SKIPPED_COLLECT_FLAG))) {
521
+ txSize modulo = size % (the->minimumChunksSize ? the->minimumChunksSize : 16);
522
+ if (modulo)
523
+ size = fxAddChunkSizes(the, size, the->minimumChunksSize - modulo);
524
+ }
525
+ size = fxAddChunkSizes(the, size, sizeof(txBlock));
526
+ buffer = fxAllocateChunks(the, size);
527
+ if (buffer) {
528
+ #ifdef mxSnapshot
529
+ c_memset(buffer, 0, size);
530
+ #endif
531
+ if ((the->firstBlock != C_NULL) && (the->firstBlock->limit == buffer)) {
532
+ the->firstBlock->limit += size;
533
+ block = the->firstBlock;
534
+ }
535
+ else {
536
+ block = (txBlock*)buffer;
537
+ block->nextBlock = the->firstBlock;
538
+ block->current = buffer + sizeof(txBlock);
539
+ block->limit = buffer + size;
540
+ block->temporary = C_NULL;
541
+ the->firstBlock = block;
542
+ size -= sizeof(txBlock);
543
+ }
544
+ the->maximumChunksSize += size;
545
+ #if mxReport
546
+ fxReport(the, "# Chunk allocation: reserved %ld used %ld peak %ld bytes\n",
547
+ (long)the->maximumChunksSize, (long)the->currentChunksSize, (long)the->peakChunksSize);
548
+ #endif
549
+ }
550
+ return block;
551
+ }
552
+
553
+ void fxGrowKeys(txMachine* the, txID theCount)
554
+ {
555
+ if (the->keyDelta > 0) {
556
+ txID keyDelta = (theCount > the->keyDelta) ? theCount : the->keyDelta;
557
+ txID keyCount = (the->keyCount + keyDelta) - the->keyOffset;
558
+ txSlot** keyArray = c_realloc(the->keyArray, keyCount * sizeof(txSlot*));
559
+ if (keyArray == C_NULL)
560
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
561
+ the->keyArray = keyArray;
562
+ the->keyCount = keyCount + the->keyOffset;
563
+ }
564
+ else
565
+ fxAbort(the, XS_NO_MORE_KEYS_EXIT);
566
+ }
567
+
568
+ void fxGrowSlots(txMachine* the, txSize theCount)
569
+ {
570
+ txSlot* aHeap;
571
+ txSlot* aSlot;
572
+
573
+ aHeap = fxAllocateSlots(the, theCount);
574
+ if (!aHeap) {
575
+ fxReport(the, "# Slot allocation: failed for %ld bytes\n", theCount * sizeof(txSlot));
576
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
577
+ }
578
+ if ((void *)-1 == aHeap)
579
+ return;
580
+
581
+ if (the->firstHeap && (the->firstHeap->value.reference == aHeap)) {
582
+ the->firstHeap->value.reference = aHeap + theCount;
583
+ the->maximumHeapCount += theCount;
584
+ theCount -= 1;
585
+ aSlot = aHeap;
586
+ }
587
+ else if ((aHeap + theCount) == the->firstHeap) {
588
+ *aHeap = *(the->firstHeap);
589
+ the->maximumHeapCount += theCount;
590
+ theCount -= 1;
591
+ the->firstHeap = aHeap;
592
+ aSlot = aHeap + 1;
593
+ }
594
+ else {
595
+ the->maximumHeapCount += theCount - 1;
596
+ aHeap->next = the->firstHeap;
597
+ aHeap->ID = 0;
598
+ aHeap->flag = 0;
599
+ aHeap->kind = 0;
600
+ aHeap->value.reference = aHeap + theCount;
601
+ theCount -= 2;
602
+ the->firstHeap = aHeap;
603
+ aSlot = aHeap + 1;
604
+ }
605
+ while (theCount--) {
606
+ txSlot* next = aSlot + 1;
607
+ aSlot->next = next;
608
+ aSlot->flag = XS_NO_FLAG;
609
+ aSlot->kind = XS_UNDEFINED_KIND;
610
+ #if mxPoisonSlots
611
+ ASAN_POISON_MEMORY_REGION(&aSlot->value, sizeof(aSlot->value));
612
+ #endif
613
+ aSlot = next;
614
+ }
615
+ aSlot->next = the->freeHeap;
616
+ aSlot->flag = XS_NO_FLAG;
617
+ aSlot->kind = XS_UNDEFINED_KIND;
618
+ #if mxPoisonSlots
619
+ ASAN_POISON_MEMORY_REGION(&aSlot->value, sizeof(aSlot->value));
620
+ #endif
621
+ the->freeHeap = aHeap + 1;
622
+ the->collectFlag &= ~XS_TRASHING_FLAG;
623
+ #if mxReport
624
+ fxReport(the, "# Slot allocation: reserved %ld used %ld peak %ld bytes\n",
625
+ (long)(the->maximumHeapCount * sizeof(txSlot)),
626
+ (long)(the->currentHeapCount * sizeof(txSlot)),
627
+ (long)(the->peakHeapCount * sizeof(txSlot)));
628
+ #endif
629
+ }
630
+
631
+ void fxMark(txMachine* the, void (*theMarker)(txMachine*, txSlot*))
632
+ {
633
+ txInteger anIndex;
634
+ txSlot** anArray;
635
+ txSlot* aSlot;
636
+
637
+ #ifdef mxNever
638
+ startTime(&gxMarkTime);
639
+ #endif
640
+ anArray = the->keyArray;
641
+ anIndex = the->keyIndex;
642
+ //#if mxOptimize
643
+ // anArray += the->keyOffset;
644
+ anIndex -= the->keyOffset;
645
+ //#endif
646
+ while (anIndex) {
647
+ if ((aSlot = *anArray)) {
648
+ aSlot->flag |= XS_MARK_FLAG;
649
+ (*theMarker)(the, aSlot);
650
+ }
651
+ anArray++;
652
+ anIndex--;
653
+ }
654
+
655
+ anArray = the->aliasArray;
656
+ anIndex = the->aliasCount;
657
+ while (anIndex) {
658
+ if ((aSlot = *anArray)) {
659
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
660
+ (*theMarker)(the, aSlot);
661
+ aSlot->flag |= XS_MARK_FLAG;
662
+ }
663
+ }
664
+ anArray++;
665
+ anIndex--;
666
+ }
667
+
668
+ aSlot = the->stackTop;
669
+ while (aSlot > the->stack) {
670
+ aSlot--;
671
+ (*theMarker)(the, aSlot);
672
+ }
673
+ aSlot = the->cRoot;
674
+ while (aSlot) {
675
+ (*theMarker)(the, aSlot);
676
+ aSlot = aSlot->next;
677
+ }
678
+ #ifdef mxNever
679
+ stopTime(&gxMarkTime);
680
+ #endif
681
+ }
682
+
683
+ void fxMarkFinalizationRegistry(txMachine* the, txSlot* registry)
684
+ {
685
+ txSlot* slot = registry->value.finalizationRegistry.callback->next;
686
+ txSlot* instance;
687
+ while (slot) {
688
+ slot = slot->next;
689
+ if (slot) {
690
+ instance = slot->value.finalizationCell.target;
691
+ if (instance && !(instance->flag & XS_MARK_FLAG)) {
692
+ slot->value.finalizationCell.target = C_NULL;
693
+ registry->value.finalizationRegistry.flags |= XS_FINALIZATION_REGISTRY_CHANGED;
694
+ }
695
+ instance = slot->value.finalizationCell.token;
696
+ if (instance && !(instance->flag & XS_MARK_FLAG))
697
+ slot->value.finalizationCell.token = C_NULL;
698
+ slot = slot->next;
699
+ }
700
+ }
701
+ }
702
+
703
+ void fxMarkInstance(txMachine* the, txSlot* theCurrent, void (*theMarker)(txMachine*, txSlot*))
704
+ {
705
+ txSlot* aProperty;
706
+ txSlot* aTemporary;
707
+
708
+ mxCheck(the, theCurrent->kind == XS_INSTANCE_KIND);
709
+ aProperty = theCurrent;
710
+ theCurrent->value.instance.garbage = C_NULL;
711
+ for (;;) {
712
+ if (aProperty) {
713
+ if (!(aProperty->flag & XS_MARK_FLAG)) {
714
+ aProperty->flag |= XS_MARK_FLAG;
715
+ switch (aProperty->kind) {
716
+ case XS_INSTANCE_KIND:
717
+ aTemporary = aProperty->value.instance.prototype;
718
+ if (aTemporary && !(aTemporary->flag & XS_MARK_FLAG)) {
719
+ aProperty->value.instance.prototype = theCurrent;
720
+ theCurrent = aTemporary;
721
+ theCurrent->value.instance.garbage = aProperty;
722
+ aProperty = theCurrent;
723
+ }
724
+ else
725
+ aProperty = aProperty->next;
726
+ break;
727
+ case XS_REFERENCE_KIND:
728
+ aTemporary = aProperty->value.reference;
729
+ if (!(aTemporary->flag & XS_MARK_FLAG)) {
730
+ aProperty->value.reference = theCurrent;
731
+ theCurrent = aTemporary;
732
+ theCurrent->value.instance.garbage = aProperty;
733
+ aProperty = theCurrent;
734
+ }
735
+ else
736
+ aProperty = aProperty->next;
737
+ break;
738
+
739
+ case XS_PROXY_KIND:
740
+ aTemporary = aProperty->value.proxy.handler;
741
+ if (aTemporary && !(aTemporary->flag & XS_MARK_FLAG)) {
742
+ aProperty->flag |= XS_INSPECTOR_FLAG;
743
+ aProperty->value.proxy.handler = theCurrent;
744
+ theCurrent = aTemporary;
745
+ theCurrent->value.instance.garbage = aProperty;
746
+ aProperty = theCurrent;
747
+ }
748
+ else {
749
+ aTemporary = aProperty->value.proxy.target;
750
+ if (aTemporary && !(aTemporary->flag & XS_MARK_FLAG)) {
751
+ aProperty->value.proxy.target = theCurrent;
752
+ theCurrent = aTemporary;
753
+ theCurrent->value.instance.garbage = aProperty;
754
+ aProperty = theCurrent;
755
+ }
756
+ else
757
+ aProperty = aProperty->next;
758
+ }
759
+ break;
760
+
761
+ case XS_CLOSURE_KIND:
762
+ aTemporary = aProperty->value.closure;
763
+ if (aTemporary && !(aTemporary->flag & XS_MARK_FLAG)) {
764
+ aTemporary->flag |= XS_MARK_FLAG;
765
+ if (aTemporary->kind == XS_REFERENCE_KIND) {
766
+ aTemporary = aTemporary->value.reference;
767
+ if (!(aTemporary->flag & XS_MARK_FLAG)) {
768
+ aProperty->value.closure->value.reference = theCurrent;
769
+ theCurrent = aTemporary;
770
+ theCurrent->value.instance.garbage = aProperty;
771
+ aProperty = theCurrent;
772
+
773
+ }
774
+ }
775
+ else {
776
+ (*theMarker)(the, aTemporary);
777
+ aProperty = aProperty->next;
778
+ }
779
+ }
780
+ else
781
+ aProperty = aProperty->next;
782
+ break;
783
+
784
+ default:
785
+ (*theMarker)(the, aProperty);
786
+ aProperty = aProperty->next;
787
+ break;
788
+ }
789
+ }
790
+ else
791
+ aProperty = aProperty->next;
792
+ }
793
+ else if (theCurrent->value.instance.garbage) {
794
+ aProperty = theCurrent->value.instance.garbage;
795
+ theCurrent->value.instance.garbage = C_NULL;
796
+ switch (aProperty->kind) {
797
+ case XS_INSTANCE_KIND:
798
+ aTemporary = aProperty->value.instance.prototype;
799
+ aProperty->value.instance.prototype = theCurrent;
800
+ theCurrent = aTemporary;
801
+ aProperty = aProperty->next;
802
+ break;
803
+ case XS_REFERENCE_KIND:
804
+ aTemporary = aProperty->value.reference;
805
+ aProperty->value.reference = theCurrent;
806
+ theCurrent = aTemporary;
807
+ aProperty = aProperty->next;
808
+ break;
809
+ case XS_PROXY_KIND:
810
+ if (aProperty->flag & XS_INSPECTOR_FLAG) {
811
+ aProperty->flag &= ~XS_INSPECTOR_FLAG;
812
+ aTemporary = aProperty->value.proxy.handler;
813
+ aProperty->value.proxy.handler = theCurrent;
814
+ theCurrent = aTemporary;
815
+
816
+ aTemporary = aProperty->value.proxy.target;
817
+ if (aTemporary && !(aTemporary->flag & XS_MARK_FLAG)) {
818
+ aProperty->value.proxy.target = theCurrent;
819
+ theCurrent = aTemporary;
820
+ theCurrent->value.instance.garbage = aProperty;
821
+ aProperty = theCurrent;
822
+ }
823
+ else {
824
+ aProperty = aProperty->next;
825
+ }
826
+ }
827
+ else {
828
+ aTemporary = aProperty->value.proxy.target;
829
+ aProperty->value.proxy.target = theCurrent;
830
+ theCurrent = aTemporary;
831
+ aProperty = aProperty->next;
832
+ }
833
+ break;
834
+ case XS_CLOSURE_KIND:
835
+ aTemporary = aProperty->value.closure->value.reference;
836
+ aProperty->value.closure->value.reference = theCurrent;
837
+ theCurrent = aTemporary;
838
+ aProperty = aProperty->next;
839
+ break;
840
+ }
841
+ }
842
+ else
843
+ break;
844
+ }
845
+ }
846
+
847
+ void fxMarkReference(txMachine* the, txSlot* theSlot)
848
+ {
849
+ txSlot* aSlot;
850
+ switch (theSlot->kind) {
851
+ case XS_REFERENCE_KIND:
852
+ aSlot = theSlot->value.reference;
853
+ if (!(aSlot->flag & XS_MARK_FLAG))
854
+ fxMarkInstance(the, aSlot, fxMarkReference);
855
+ break;
856
+ case XS_CLOSURE_KIND:
857
+ aSlot = theSlot->value.closure;
858
+ if (aSlot && (!(aSlot->flag & XS_MARK_FLAG))) {
859
+ aSlot->flag |= XS_MARK_FLAG;
860
+ fxMarkReference(the, aSlot);
861
+ }
862
+ break;
863
+ case XS_INSTANCE_KIND:
864
+ if (!(theSlot->flag & XS_MARK_FLAG))
865
+ fxMarkInstance(the, theSlot, fxMarkReference);
866
+ break;
867
+ case XS_ACCESSOR_KIND:
868
+ aSlot = theSlot->value.accessor.getter;
869
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
870
+ fxCheckCStack(the);
871
+ fxMarkInstance(the, aSlot, fxMarkReference);
872
+ }
873
+ aSlot = theSlot->value.accessor.setter;
874
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
875
+ fxCheckCStack(the);
876
+ fxMarkInstance(the, aSlot, fxMarkReference);
877
+ }
878
+ break;
879
+ case XS_ARGUMENTS_SLOPPY_KIND:
880
+ case XS_ARGUMENTS_STRICT_KIND:
881
+ case XS_ARRAY_KIND:
882
+ case XS_STACK_KIND:
883
+ fxCheckCStack(the);
884
+ if ((aSlot = theSlot->value.array.address)) {
885
+ txIndex aLength = (((txChunk*)(((txByte*)aSlot) - sizeof(txChunk)))->size) / sizeof(txSlot);
886
+ if (aLength > theSlot->value.array.length)
887
+ aLength = theSlot->value.array.length;
888
+ while (aLength) {
889
+ fxMarkReference(the, aSlot);
890
+ aSlot++;
891
+ aLength--;
892
+ }
893
+ }
894
+ break;
895
+ case XS_CALLBACK_KIND:
896
+ aSlot = theSlot->value.callback.closures;
897
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
898
+ fxCheckCStack(the);
899
+ fxMarkInstance(the, aSlot, fxMarkValue);
900
+ }
901
+ break;
902
+ case XS_CODE_KIND:
903
+ case XS_CODE_X_KIND:
904
+ aSlot = theSlot->value.code.closures;
905
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
906
+ fxCheckCStack(the);
907
+ fxMarkInstance(the, aSlot, fxMarkReference);
908
+ }
909
+ break;
910
+ case XS_HOME_KIND:
911
+ aSlot = theSlot->value.home.object;
912
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
913
+ fxCheckCStack(the);
914
+ fxMarkInstance(the, aSlot, fxMarkReference);
915
+ }
916
+ aSlot = theSlot->value.home.module;
917
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
918
+ fxCheckCStack(the);
919
+ fxMarkInstance(the, aSlot, fxMarkReference);
920
+ }
921
+ break;
922
+ case XS_MODULE_KIND:
923
+ case XS_PROGRAM_KIND:
924
+ fxCheckCStack(the);
925
+ aSlot = theSlot->value.module.realm;
926
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
927
+ fxMarkInstance(the, aSlot, fxMarkReference);
928
+ break;
929
+ case XS_EXPORT_KIND:
930
+ aSlot = theSlot->value.export.closure;
931
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
932
+ aSlot->flag |= XS_MARK_FLAG;
933
+ fxMarkReference(the, aSlot);
934
+ }
935
+ aSlot = theSlot->value.export.module;
936
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
937
+ fxMarkInstance(the, aSlot, fxMarkReference);
938
+ break;
939
+ case XS_HOST_KIND:
940
+ if (theSlot->value.host.data) {
941
+ if ((theSlot->flag & XS_HOST_HOOKS_FLAG) && (theSlot->value.host.variant.hooks->marker))
942
+ (*theSlot->value.host.variant.hooks->marker)(the, theSlot->value.host.data, fxMarkReference);
943
+ }
944
+ break;
945
+ case XS_PROXY_KIND:
946
+ aSlot = theSlot->value.proxy.handler;
947
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
948
+ fxMarkInstance(the, aSlot, fxMarkReference);
949
+ aSlot = theSlot->value.proxy.target;
950
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
951
+ fxMarkInstance(the, aSlot, fxMarkReference);
952
+ break;
953
+
954
+ case XS_ERROR_KIND:
955
+ aSlot = theSlot->value.error.info;
956
+ if (aSlot && (!(aSlot->flag & XS_MARK_FLAG)))
957
+ fxMarkInstance(the, aSlot, fxMarkReference);
958
+ break;
959
+ case XS_LIST_KIND:
960
+ fxCheckCStack(the);
961
+ aSlot = theSlot->value.list.first;
962
+ while (aSlot) {
963
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
964
+ aSlot->flag |= XS_MARK_FLAG;
965
+ fxMarkReference(the, aSlot);
966
+ }
967
+ aSlot = aSlot->next;
968
+ }
969
+ break;
970
+
971
+ case XS_PRIVATE_KIND:
972
+ aSlot = theSlot->value.private.check;
973
+ if (!(aSlot->flag & XS_MARK_FLAG))
974
+ fxMarkInstance(the, aSlot, fxMarkReference);
975
+ aSlot = theSlot->value.private.first;
976
+ while (aSlot) {
977
+ aSlot->flag |= XS_MARK_FLAG;
978
+ fxMarkReference(the, aSlot);
979
+ aSlot = aSlot->next;
980
+ }
981
+ break;
982
+
983
+ case XS_MAP_KIND:
984
+ case XS_SET_KIND:
985
+ {
986
+ txSlot** anAddress = theSlot->value.table.address;
987
+ txInteger aLength = theSlot->value.table.length;
988
+ while (aLength) {
989
+ aSlot = *anAddress;
990
+ while (aSlot) {
991
+ aSlot->flag |= XS_MARK_FLAG;
992
+ aSlot = aSlot->next;
993
+ }
994
+ anAddress++;
995
+ aLength--;
996
+ }
997
+ }
998
+ break;
999
+ case XS_WEAK_MAP_KIND:
1000
+ case XS_WEAK_SET_KIND:
1001
+ aSlot = theSlot->value.weakList.first;
1002
+ while (aSlot) {
1003
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
1004
+ aSlot->flag |= XS_MARK_FLAG;
1005
+ fxMarkReference(the, aSlot);
1006
+ }
1007
+ aSlot = aSlot->next;
1008
+ }
1009
+ break;
1010
+ case XS_WEAK_ENTRY_KIND:
1011
+ aSlot = theSlot->value.weakEntry.check;
1012
+ if (aSlot->flag & XS_MARK_FLAG) {
1013
+ aSlot = theSlot->value.weakEntry.value;
1014
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
1015
+ aSlot->flag |= XS_MARK_FLAG;
1016
+ fxMarkReference(the, aSlot);
1017
+ }
1018
+ }
1019
+ break;
1020
+ case XS_WEAK_REF_KIND:
1021
+ aSlot = theSlot->value.weakRef.target;
1022
+ if (aSlot) {
1023
+ #ifdef mxSnapshot
1024
+ if (the->collectFlag & XS_ORGANIC_FLAG) {
1025
+ fxMarkReference(the, aSlot);
1026
+ }
1027
+ else {
1028
+ theSlot->value.weakRef.link = the->firstWeakRefLink;
1029
+ the->firstWeakRefLink = theSlot;
1030
+ }
1031
+ #else
1032
+ theSlot->value.weakRef.link = the->firstWeakRefLink;
1033
+ the->firstWeakRefLink = theSlot;
1034
+ #endif
1035
+ }
1036
+ break;
1037
+ case XS_FINALIZATION_REGISTRY_KIND:
1038
+ aSlot = theSlot->value.finalizationRegistry.callback;
1039
+ if (aSlot) {
1040
+ fxCheckCStack(the);
1041
+ aSlot->flag |= XS_MARK_FLAG;
1042
+ fxMarkReference(the, aSlot);
1043
+ aSlot = aSlot->next;
1044
+ while (aSlot) {
1045
+ aSlot->flag |= XS_MARK_FLAG;
1046
+ fxMarkReference(the, aSlot); // holdings
1047
+ aSlot = aSlot->next;
1048
+ if (aSlot) {
1049
+ aSlot->flag |= XS_MARK_FLAG;
1050
+ // weak target and token
1051
+ aSlot = aSlot->next;
1052
+ }
1053
+ }
1054
+ }
1055
+ break;
1056
+
1057
+ case XS_HOST_INSPECTOR_KIND:
1058
+ aSlot = theSlot->value.hostInspector.cache;
1059
+ if (!(aSlot->flag & XS_MARK_FLAG))
1060
+ fxMarkInstance(the, aSlot, fxMarkReference);
1061
+ break;
1062
+ }
1063
+ }
1064
+
1065
+ void fxMarkValue(txMachine* the, txSlot* theSlot)
1066
+ {
1067
+ #define mxMarkChunk(_THE_DATA) \
1068
+ ((txChunk*)(((txByte*)_THE_DATA) - sizeof(txChunk)))->size |= mxChunkFlag
1069
+
1070
+ txSlot* aSlot;
1071
+ switch (theSlot->kind) {
1072
+ case XS_STRING_KIND:
1073
+ mxMarkChunk(theSlot->value.string);
1074
+ break;
1075
+ case XS_BIGINT_KIND:
1076
+ mxMarkChunk(theSlot->value.bigint.data);
1077
+ break;
1078
+ case XS_REFERENCE_KIND:
1079
+ aSlot = theSlot->value.reference;
1080
+ if (!(aSlot->flag & XS_MARK_FLAG))
1081
+ fxMarkInstance(the, aSlot, fxMarkValue);
1082
+ break;
1083
+ case XS_CLOSURE_KIND:
1084
+ aSlot = theSlot->value.closure;
1085
+ if (aSlot && (!(aSlot->flag & XS_MARK_FLAG))) {
1086
+ aSlot->flag |= XS_MARK_FLAG;
1087
+ fxMarkValue(the, aSlot);
1088
+ }
1089
+ break;
1090
+ case XS_INSTANCE_KIND:
1091
+ if (!(theSlot->flag & XS_MARK_FLAG))
1092
+ fxMarkInstance(the, theSlot, fxMarkValue);
1093
+ break;
1094
+
1095
+ case XS_ARGUMENTS_SLOPPY_KIND:
1096
+ case XS_ARGUMENTS_STRICT_KIND:
1097
+ case XS_ARRAY_KIND:
1098
+ case XS_STACK_KIND:
1099
+ fxCheckCStack(the);
1100
+ if ((aSlot = theSlot->value.array.address)) {
1101
+ txChunk* chunk = (txChunk*)(((txByte*)aSlot) - sizeof(txChunk));
1102
+ if (!(chunk->size & mxChunkFlag)) {
1103
+ txIndex aLength = chunk->size / sizeof(txSlot);
1104
+ if (aLength > theSlot->value.array.length)
1105
+ aLength = theSlot->value.array.length;
1106
+ while (aLength) {
1107
+ fxMarkValue(the, aSlot);
1108
+ aSlot++;
1109
+ aLength--;
1110
+ }
1111
+ mxMarkChunk(theSlot->value.array.address);
1112
+ }
1113
+ }
1114
+ break;
1115
+ case XS_ARRAY_BUFFER_KIND:
1116
+ if (theSlot->value.arrayBuffer.address)
1117
+ mxMarkChunk(theSlot->value.arrayBuffer.address);
1118
+ break;
1119
+ case XS_CALLBACK_KIND:
1120
+ aSlot = theSlot->value.callback.closures;
1121
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1122
+ fxCheckCStack(the);
1123
+ fxMarkInstance(the, aSlot, fxMarkValue);
1124
+ }
1125
+ break;
1126
+ case XS_CODE_KIND:
1127
+ mxMarkChunk(theSlot->value.code.address);
1128
+ /* continue */
1129
+ case XS_CODE_X_KIND:
1130
+ aSlot = theSlot->value.code.closures;
1131
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1132
+ fxCheckCStack(the);
1133
+ fxMarkInstance(the, aSlot, fxMarkValue);
1134
+ }
1135
+ break;
1136
+ case XS_GLOBAL_KIND:
1137
+ mxMarkChunk(theSlot->value.table.address);
1138
+ break;
1139
+ case XS_HOST_KIND:
1140
+ if (theSlot->value.host.data) {
1141
+ if ((theSlot->flag & XS_HOST_HOOKS_FLAG) && (theSlot->value.host.variant.hooks->marker))
1142
+ (*theSlot->value.host.variant.hooks->marker)(the, theSlot->value.host.data, fxMarkValue);
1143
+ if (theSlot->flag & XS_HOST_CHUNK_FLAG)
1144
+ mxMarkChunk(theSlot->value.host.data);
1145
+ }
1146
+ break;
1147
+ case XS_IDS_KIND:
1148
+ if (theSlot->value.IDs)
1149
+ mxMarkChunk(theSlot->value.IDs);
1150
+ break;
1151
+ case XS_PROXY_KIND:
1152
+ aSlot = theSlot->value.proxy.handler;
1153
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
1154
+ fxMarkInstance(the, aSlot, fxMarkValue);
1155
+ aSlot = theSlot->value.proxy.target;
1156
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
1157
+ fxMarkInstance(the, aSlot, fxMarkValue);
1158
+ break;
1159
+ case XS_REGEXP_KIND:
1160
+ if (theSlot->value.regexp.code)
1161
+ mxMarkChunk(theSlot->value.regexp.code);
1162
+ if (theSlot->value.regexp.data)
1163
+ mxMarkChunk(theSlot->value.regexp.data);
1164
+ break;
1165
+
1166
+ case XS_ACCESSOR_KIND:
1167
+ aSlot = theSlot->value.accessor.getter;
1168
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1169
+ fxCheckCStack(the);
1170
+ fxMarkInstance(the, aSlot, fxMarkValue);
1171
+ }
1172
+ aSlot = theSlot->value.accessor.setter;
1173
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1174
+ fxCheckCStack(the);
1175
+ fxMarkInstance(the, aSlot, fxMarkValue);
1176
+ }
1177
+ break;
1178
+ case XS_HOME_KIND:
1179
+ aSlot = theSlot->value.home.object;
1180
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1181
+ fxCheckCStack(the);
1182
+ fxMarkInstance(the, aSlot, fxMarkValue);
1183
+ }
1184
+ aSlot = theSlot->value.home.module;
1185
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1186
+ fxCheckCStack(the);
1187
+ fxMarkInstance(the, aSlot, fxMarkValue);
1188
+ }
1189
+ break;
1190
+ case XS_MODULE_KIND:
1191
+ case XS_PROGRAM_KIND:
1192
+ aSlot = theSlot->value.module.realm;
1193
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1194
+ fxCheckCStack(the);
1195
+ fxMarkInstance(the, aSlot, fxMarkValue);
1196
+ }
1197
+ break;
1198
+ case XS_EXPORT_KIND:
1199
+ aSlot = theSlot->value.export.closure;
1200
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG)) {
1201
+ aSlot->flag |= XS_MARK_FLAG;
1202
+ fxMarkValue(the, aSlot);
1203
+ }
1204
+ aSlot = theSlot->value.export.module;
1205
+ if (aSlot && !(aSlot->flag & XS_MARK_FLAG))
1206
+ fxMarkInstance(the, aSlot, fxMarkValue);
1207
+ break;
1208
+ case XS_KEY_KIND:
1209
+ if (theSlot->value.key.string)
1210
+ mxMarkChunk(theSlot->value.key.string);
1211
+ break;
1212
+
1213
+ case XS_ERROR_KIND:
1214
+ aSlot = theSlot->value.error.info;
1215
+ if (aSlot && (!(aSlot->flag & XS_MARK_FLAG)))
1216
+ fxMarkInstance(the, aSlot, fxMarkValue);
1217
+ break;
1218
+ case XS_LIST_KIND:
1219
+ aSlot = theSlot->value.list.first;
1220
+ while (aSlot) {
1221
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
1222
+ aSlot->flag |= XS_MARK_FLAG;
1223
+ fxMarkValue(the, aSlot);
1224
+ }
1225
+ aSlot = aSlot->next;
1226
+ }
1227
+ break;
1228
+
1229
+ case XS_PRIVATE_KIND:
1230
+ aSlot = theSlot->value.private.check;
1231
+ if (!(aSlot->flag & XS_MARK_FLAG))
1232
+ fxMarkInstance(the, aSlot, fxMarkValue);
1233
+ aSlot = theSlot->value.private.first;
1234
+ while (aSlot) {
1235
+ aSlot->flag |= XS_MARK_FLAG;
1236
+ fxMarkValue(the, aSlot);
1237
+ aSlot = aSlot->next;
1238
+ }
1239
+ break;
1240
+
1241
+ case XS_MAP_KIND:
1242
+ case XS_SET_KIND:
1243
+ {
1244
+ txSlot** anAddress = theSlot->value.table.address;
1245
+ txInteger aLength = theSlot->value.table.length;
1246
+ while (aLength) {
1247
+ aSlot = *anAddress;
1248
+ while (aSlot) {
1249
+ aSlot->flag |= XS_MARK_FLAG;
1250
+ aSlot = aSlot->next;
1251
+ }
1252
+ anAddress++;
1253
+ aLength--;
1254
+ }
1255
+ }
1256
+ mxMarkChunk(theSlot->value.table.address);
1257
+ break;
1258
+
1259
+ case XS_WEAK_MAP_KIND:
1260
+ case XS_WEAK_SET_KIND:
1261
+ aSlot = theSlot->value.weakList.first;
1262
+ while (aSlot) {
1263
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
1264
+ aSlot->flag |= XS_MARK_FLAG;
1265
+ fxMarkValue(the, aSlot);
1266
+ }
1267
+ aSlot = aSlot->next;
1268
+ }
1269
+ break;
1270
+ case XS_WEAK_ENTRY_KIND:
1271
+ aSlot = theSlot->value.weakEntry.check;
1272
+ if (aSlot->flag & XS_MARK_FLAG) {
1273
+ aSlot = theSlot->value.weakEntry.value;
1274
+ if (!(aSlot->flag & XS_MARK_FLAG)) {
1275
+ aSlot->flag |= XS_MARK_FLAG;
1276
+ fxMarkValue(the, aSlot);
1277
+ }
1278
+ }
1279
+ break;
1280
+ case XS_WEAK_REF_KIND:
1281
+ aSlot = theSlot->value.weakRef.target;
1282
+ if (aSlot) {
1283
+ #ifdef mxSnapshot
1284
+ if (the->collectFlag & XS_ORGANIC_FLAG) {
1285
+ fxMarkValue(the, aSlot);
1286
+ }
1287
+ else {
1288
+ theSlot->value.weakRef.link = the->firstWeakRefLink;
1289
+ the->firstWeakRefLink = theSlot;
1290
+ }
1291
+ #else
1292
+ theSlot->value.weakRef.link = the->firstWeakRefLink;
1293
+ the->firstWeakRefLink = theSlot;
1294
+ #endif
1295
+ }
1296
+ break;
1297
+ case XS_FINALIZATION_REGISTRY_KIND:
1298
+ aSlot = theSlot->value.finalizationRegistry.callback;
1299
+ if (aSlot) {
1300
+ aSlot->flag |= XS_MARK_FLAG;
1301
+ fxMarkValue(the, aSlot);
1302
+ aSlot = aSlot->next;
1303
+ while (aSlot) {
1304
+ aSlot->flag |= XS_MARK_FLAG;
1305
+ fxCheckCStack(the);
1306
+ fxMarkValue(the, aSlot); // holdings
1307
+ aSlot = aSlot->next;
1308
+ if (aSlot) {
1309
+ aSlot->flag |= XS_MARK_FLAG;
1310
+ // weak target and token
1311
+ aSlot = aSlot->next;
1312
+ }
1313
+ }
1314
+ }
1315
+ break;
1316
+
1317
+ case XS_HOST_INSPECTOR_KIND:
1318
+ aSlot = theSlot->value.hostInspector.cache;
1319
+ if (!(aSlot->flag & XS_MARK_FLAG))
1320
+ fxMarkInstance(the, aSlot, fxMarkValue);
1321
+ break;
1322
+ }
1323
+ }
1324
+
1325
+ void fxMarkWeakStuff(txMachine* the)
1326
+ {
1327
+ txSlot* slot;
1328
+ txSlot** address;
1329
+
1330
+ {
1331
+ txSlot* list;
1332
+ txSlot** listAddress = &the->firstWeakListLink;
1333
+ while ((list = *listAddress)) {
1334
+ if (list->flag & XS_MARK_FLAG) {
1335
+ txSlot* listEntry;
1336
+ txSlot** listEntryAddress = &list->value.weakList.first;
1337
+ while ((listEntry = *listEntryAddress)) {
1338
+ txSlot* value = listEntry->value.weakEntry.value;
1339
+ if ((value->flag & XS_MARK_FLAG) && (value->kind != XS_UNINITIALIZED_KIND)) {
1340
+ listEntryAddress = &listEntry->next;
1341
+ }
1342
+ else {
1343
+ listEntry->flag &= ~XS_MARK_FLAG;
1344
+ *listEntryAddress = listEntry->next;
1345
+ }
1346
+ }
1347
+ listAddress = &list->value.weakList.link;
1348
+ }
1349
+ else {
1350
+ txSlot* listEntry = list->value.weakList.first;
1351
+ while (listEntry) {
1352
+ txSlot* key = listEntry->value.weakEntry.check;
1353
+ if (key->flag & XS_MARK_FLAG) {
1354
+ txSlot* keyEntry;
1355
+ txSlot** keyEntryAddress = &key->next;
1356
+ while ((keyEntry = *keyEntryAddress)) {
1357
+ if (!(keyEntry->flag & XS_INTERNAL_FLAG))
1358
+ break;
1359
+ if ((keyEntry->kind == XS_WEAK_ENTRY_KIND) && (keyEntry->value.weakEntry.check == list)) {
1360
+ keyEntry->flag &= ~XS_MARK_FLAG;
1361
+ *keyEntryAddress = keyEntry->next;
1362
+ break;
1363
+ }
1364
+ keyEntryAddress = &keyEntry->next;
1365
+ }
1366
+ }
1367
+ listEntry = listEntry->next;
1368
+ }
1369
+ *listAddress = list->value.weakList.link;
1370
+ }
1371
+ }
1372
+ }
1373
+ address = &the->firstWeakRefLink;
1374
+ while ((slot = *address)) {
1375
+ if (!(slot->value.weakRef.target->flag & XS_MARK_FLAG))
1376
+ slot->value.weakRef.target = C_NULL;
1377
+ *address = C_NULL;
1378
+ address = &(slot->value.weakRef.link);
1379
+ }
1380
+
1381
+ if (mxFinalizationRegistries.kind == XS_REFERENCE_KIND) {
1382
+ slot = mxFinalizationRegistries.value.reference->next;
1383
+ while (slot) {
1384
+ fxMarkFinalizationRegistry(the, slot->value.closure);
1385
+ slot = slot->next;
1386
+ }
1387
+ }
1388
+ }
1389
+
1390
+ txSize fxMultiplyChunkSizes(txMachine* the, txSize a, txSize b)
1391
+ {
1392
+ txSize c;
1393
+ #if __has_builtin(__builtin_mul_overflow)
1394
+ if (__builtin_mul_overflow(a, b, &c) || (c < 0)) {
1395
+ #else
1396
+ txNumber C = (txNumber)a * (txNumber)b;
1397
+ c = (txSize)C;
1398
+ if ((C > (txNumber)0x7FFFFFFF) || (C < (txNumber)0)) {
1399
+ #endif
1400
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
1401
+ }
1402
+ return c;
1403
+ }
1404
+
1405
+ void* fxNewChunk(txMachine* the, txSize size)
1406
+ {
1407
+ txSize offset = size;
1408
+ txChunk* chunk;
1409
+ txBoolean once = 1;
1410
+ size = fxAdjustChunkSize(the, size);
1411
+ chunk = fxFindChunk(the, size, &once);
1412
+ if (!chunk) {
1413
+ chunk = fxGrowChunk(the, size);
1414
+ }
1415
+ return fxCheckChunk(the, chunk, size, offset);
1416
+ }
1417
+
1418
+ void* fxNewGrowableChunk(txMachine* the, txSize size, txSize capacity)
1419
+ {
1420
+ #if mxNoChunks
1421
+ return fxNewChunk(the, size);
1422
+ #else
1423
+ txSize offset = size;
1424
+ txChunk* chunk;
1425
+ txBoolean once = 1;
1426
+ size = fxAdjustChunkSize(the, size);
1427
+ capacity = fxAdjustChunkSize(the, capacity);
1428
+ chunk = fxFindChunk(the, capacity, &once);
1429
+ if (!chunk) {
1430
+ chunk = fxGrowChunk(the, capacity);
1431
+ if (!chunk) {
1432
+ chunk = fxFindChunk(the, size, &once);
1433
+ if (!chunk) {
1434
+ chunk = fxGrowChunk(the, size);
1435
+ }
1436
+ }
1437
+ }
1438
+ return fxCheckChunk(the, chunk, size, offset);
1439
+ #endif
1440
+ }
1441
+
1442
+ txSlot* fxNewSlot(txMachine* the)
1443
+ {
1444
+ txSlot* aSlot;
1445
+ txBoolean once = 1, allocate;
1446
+
1447
+ #if mxStress
1448
+ if (fxShouldStress()) {
1449
+ fxCollect(the, XS_COMPACT_FLAG | XS_ORGANIC_FLAG);
1450
+ once = 0;
1451
+ }
1452
+ #endif
1453
+ again:
1454
+ aSlot = the->freeHeap;
1455
+ if (aSlot) {
1456
+ the->freeHeap = aSlot->next;
1457
+ aSlot->next = C_NULL;
1458
+ aSlot->ID = XS_NO_ID;
1459
+ aSlot->flag = XS_NO_FLAG;
1460
+ #ifdef mxSnapshot
1461
+ #if mx32bitID
1462
+ aSlot->dummy = 0;
1463
+ #elif INTPTR_MAX == INT64_MAX
1464
+ aSlot->dummy = 0;
1465
+ #endif
1466
+ #endif
1467
+ #if mxPoisonSlots
1468
+ ASAN_UNPOISON_MEMORY_REGION(&aSlot->value, sizeof(aSlot->value));
1469
+ #endif
1470
+ the->currentHeapCount++;
1471
+ if (the->peakHeapCount < the->currentHeapCount)
1472
+ the->peakHeapCount = the->currentHeapCount;
1473
+ return aSlot;
1474
+ }
1475
+ if (once) {
1476
+ txBoolean wasThrashing = ((the->collectFlag & XS_TRASHING_FLAG) != 0), isThrashing;
1477
+
1478
+ fxCollect(the, XS_ORGANIC_FLAG);
1479
+
1480
+ isThrashing = ((the->collectFlag & XS_TRASHING_FLAG) != 0);
1481
+ allocate = wasThrashing && isThrashing;
1482
+
1483
+ once = 0;
1484
+ }
1485
+ else
1486
+ allocate = 1;
1487
+ if (allocate) {
1488
+ if (!the->minimumHeapCount) {
1489
+ fxReport(the, "# Slot allocation: failed in fixed size heap\n");
1490
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
1491
+ }
1492
+ fxGrowSlots(the, !(the->collectFlag & XS_SKIPPED_COLLECT_FLAG) ? the->minimumHeapCount : 64);
1493
+ }
1494
+ goto again;
1495
+ return C_NULL;
1496
+ }
1497
+
1498
+ void* fxRenewChunk(txMachine* the, void* theData, txSize size)
1499
+ {
1500
+ #if mxNoChunks
1501
+ txByte* aData = ((txByte*)theData) - sizeof(txChunk);
1502
+ txChunk* aChunk = (txChunk*)aData;
1503
+ size = fxAdjustChunkSize(the, size);
1504
+ if (size <= aChunk->size) {
1505
+ aChunk->size = size;
1506
+ return theData;
1507
+ }
1508
+ return C_NULL;
1509
+ #else
1510
+ txByte* aData = ((txByte*)theData) - sizeof(txChunk);
1511
+ txChunk* aChunk = (txChunk*)aData;
1512
+ txSize capacity = (txSize)(aChunk->temporary - aData);
1513
+ txBlock* aBlock = the->firstBlock;
1514
+ size = fxAdjustChunkSize(the, size);
1515
+ if (size <= capacity) {
1516
+ the->currentChunksSize += size - aChunk->size;
1517
+ if (the->peakChunksSize < the->currentChunksSize)
1518
+ the->peakChunksSize = the->currentChunksSize;
1519
+ aChunk->size = size;
1520
+ #ifdef mxNever
1521
+ gxRenewChunkCases[0]++;
1522
+ #endif
1523
+ return theData;
1524
+ }
1525
+ while (aBlock) {
1526
+ if (aChunk->temporary == aBlock->current) {
1527
+ txSize delta = size - capacity;
1528
+ if (aBlock->current + delta <= aBlock->limit) {
1529
+ the->currentChunksSize += size - aChunk->size;
1530
+ if (the->peakChunksSize < the->currentChunksSize)
1531
+ the->peakChunksSize = the->currentChunksSize;
1532
+ aBlock->current += delta;
1533
+ aChunk->temporary = aBlock->current;
1534
+ aChunk->size = size;
1535
+ #ifdef mxSnapshot
1536
+ c_memset(aData + capacity, 0, delta);
1537
+ #endif
1538
+ #ifdef mxNever
1539
+ gxRenewChunkCases[1]++;
1540
+ #endif
1541
+ return theData;
1542
+ }
1543
+ else {
1544
+ #ifdef mxNever
1545
+ gxRenewChunkCases[2]++;
1546
+ #endif
1547
+ return C_NULL;
1548
+ }
1549
+ }
1550
+ aBlock = aBlock->nextBlock;
1551
+ }
1552
+ #ifdef mxNever
1553
+ gxRenewChunkCases[3]++;
1554
+ #endif
1555
+ return C_NULL;
1556
+ #endif
1557
+ }
1558
+
1559
+ void fxShare(txMachine* the)
1560
+ {
1561
+ txID aliasCount = 0;
1562
+ txSlot *heap, *slot, *limit;
1563
+
1564
+ heap = the->firstHeap;
1565
+ while (heap) {
1566
+ slot = heap + 1;
1567
+ limit = heap->value.reference;
1568
+ while (slot < limit) {
1569
+ if (slot->kind == XS_INSTANCE_KIND) {
1570
+ txBoolean frozen = (slot->flag & XS_DONT_PATCH_FLAG) ? 1 : 0;
1571
+ if (frozen) {
1572
+ txSlot *property = slot->next;
1573
+ while (property) {
1574
+ if (property->kind == XS_ARRAY_KIND) {
1575
+ txSlot* item = property->value.array.address;
1576
+ txInteger length = (txInteger)fxGetIndexSize(the, property);
1577
+ while (length > 0) {
1578
+ if (item->kind != XS_ACCESSOR_KIND)
1579
+ if (!(item->flag & XS_DONT_SET_FLAG))
1580
+ frozen = 0;
1581
+ if (!(item->flag & XS_DONT_DELETE_FLAG))
1582
+ frozen = 0;
1583
+ item++;
1584
+ length--;
1585
+ }
1586
+ }
1587
+ else {
1588
+ if (property->kind != XS_ACCESSOR_KIND)
1589
+ if (!(property->flag & XS_DONT_SET_FLAG))
1590
+ frozen = 0;
1591
+ if (!(property->flag & XS_DONT_DELETE_FLAG))
1592
+ frozen = 0;
1593
+ }
1594
+ property = property->next;
1595
+ }
1596
+ }
1597
+ if (frozen)
1598
+ slot->ID = XS_NO_ID;
1599
+ else
1600
+ slot->ID = aliasCount++;
1601
+ }
1602
+ else if (slot->kind == XS_CLOSURE_KIND) {
1603
+ txSlot* closure = slot->value.closure;
1604
+ if (closure->flag & XS_DONT_SET_FLAG)
1605
+ closure->flag |= XS_DONT_DELETE_FLAG;
1606
+ else {
1607
+ if (closure->ID == XS_NO_ID)
1608
+ closure->ID = aliasCount++;
1609
+ slot->flag &= ~XS_DONT_SET_FLAG;
1610
+ }
1611
+ }
1612
+ slot->flag |= XS_MARK_FLAG;
1613
+ slot++;
1614
+ }
1615
+ heap = heap->next;
1616
+ }
1617
+ the->aliasCount = aliasCount;
1618
+ /*
1619
+ fxReport(the, "# Share\n");
1620
+ fxReport(the, "# \tSlots: %ld\n", the->currentHeapCount);
1621
+ fxReport(the, "# \t\tSymbols: %ld\n", the->keyIndex);
1622
+ fxReport(the, "# \t\tInstances: %ld\n", aliasCount);
1623
+ fxReport(the, "# \tChunks: %ld bytes\n", the->currentChunksSize);
1624
+ */
1625
+ }
1626
+
1627
+ void fxSweep(txMachine* the)
1628
+ {
1629
+ txSize aTotal;
1630
+ #if mxNoChunks
1631
+ txChunk** address;
1632
+ txChunk* chunk;
1633
+ #else
1634
+ txBlock* aBlock;
1635
+ txByte* limit;
1636
+ txByte* next;
1637
+ #endif
1638
+ txByte* current;
1639
+ txByte* temporary;
1640
+ txSize aSize;
1641
+ txByte** aCodeAddress;
1642
+ txSlot* aSlot;
1643
+ txSlot* bSlot;
1644
+ txSlot* cSlot;
1645
+ txSlot* freeSlot;
1646
+ txJump* jump;
1647
+
1648
+ #ifdef mxNever
1649
+ startTime(&gxSweepChunkTime);
1650
+ #endif
1651
+
1652
+ aTotal = 0;
1653
+ #if mxNoChunks
1654
+ address = (txChunk**)&(the->firstBlock);
1655
+ while ((chunk = *address)) {
1656
+ aSize = chunk->size;
1657
+ if (aSize & mxChunkFlag) {
1658
+ aSize &= ~mxChunkFlag;
1659
+ temporary = c_malloc(aSize);
1660
+ c_memcpy(temporary, chunk, aSize);
1661
+ ((txChunk*)temporary)->size = aSize;
1662
+ chunk->temporary = temporary;
1663
+ address = (txChunk**)&(((txChunk*)temporary)->temporary);
1664
+ aTotal += aSize;
1665
+ }
1666
+ else {
1667
+ *address = (txChunk*)(chunk->temporary);
1668
+ c_free(chunk);
1669
+ }
1670
+ }
1671
+ #else
1672
+ aBlock = the->firstBlock;
1673
+ while (aBlock) {
1674
+ current = ((txByte*)aBlock) + sizeof(txBlock);
1675
+ limit = aBlock->current;
1676
+ temporary = current;
1677
+ while (current < limit) {
1678
+ aSize = ((txChunk*)current)->size;
1679
+ next = ((txChunk*)current)->temporary;
1680
+ if (aSize & mxChunkFlag) {
1681
+ aSize &= ~mxChunkFlag;
1682
+ ((txChunk*)current)->temporary = temporary;
1683
+ temporary += aSize;
1684
+ aTotal += aSize;
1685
+ }
1686
+ else {
1687
+ ((txChunk*)current)->temporary = C_NULL;
1688
+ }
1689
+ ((txChunk*)current)->size = (txSize)(next - current);
1690
+ current = next;
1691
+ }
1692
+ aBlock->temporary = temporary;
1693
+ aBlock = aBlock->nextBlock;
1694
+ }
1695
+ #endif
1696
+ the->currentChunksSize = aTotal;
1697
+
1698
+ aCodeAddress = &(the->code);
1699
+ aSlot = the->frame;
1700
+ while (aSlot) {
1701
+ mxCheck(the, aSlot->kind == XS_FRAME_KIND);
1702
+ if ((aSlot->flag & XS_C_FLAG) == 0) {
1703
+ bSlot = (aSlot + 3)->value.reference->next;
1704
+ if (bSlot->kind == XS_CODE_KIND) {
1705
+ current = bSlot->value.code.address;
1706
+ temporary = (txByte*)(((txChunk*)(current - sizeof(txChunk)))->temporary);
1707
+ if (temporary) {
1708
+ temporary += sizeof(txChunk);
1709
+ *aCodeAddress += temporary - current;
1710
+ }
1711
+ }
1712
+ }
1713
+ else {
1714
+ current = *aCodeAddress;
1715
+ if (current) {
1716
+ temporary = (txByte*)(((txChunk*)(current - sizeof(txChunk)))->temporary);
1717
+ if (temporary)
1718
+ *aCodeAddress = temporary + sizeof(txChunk);
1719
+ }
1720
+ }
1721
+ aCodeAddress = &(aSlot->value.frame.code);
1722
+ aSlot = aSlot->next;
1723
+ }
1724
+
1725
+ jump = the->firstJump;
1726
+ while (jump) {
1727
+ if (jump->flag) {
1728
+ aSlot = jump->frame;
1729
+ bSlot = (aSlot + 3)->value.reference->next;
1730
+ if (bSlot->kind == XS_CODE_KIND) {
1731
+ current = bSlot->value.code.address;
1732
+ temporary = (txByte*)(((txChunk*)(current - sizeof(txChunk)))->temporary);
1733
+ if (temporary) {
1734
+ temporary += sizeof(txChunk);
1735
+ jump->code += temporary - current;
1736
+ }
1737
+ }
1738
+ }
1739
+ else {
1740
+ current = jump->code;
1741
+ if (current) {
1742
+ temporary = (txByte*)(((txChunk*)(current - sizeof(txChunk)))->temporary);
1743
+ if (temporary)
1744
+ jump->code = temporary + sizeof(txChunk);
1745
+ }
1746
+ }
1747
+ jump = jump->nextJump;
1748
+ }
1749
+
1750
+ aSlot = the->stack;
1751
+ while (aSlot < the->stackTop) {
1752
+ fxSweepValue(the, aSlot);
1753
+ aSlot++;
1754
+ }
1755
+ aSlot = the->cRoot;
1756
+ while (aSlot) {
1757
+ fxSweepValue(the, aSlot);
1758
+ aSlot = aSlot->next;
1759
+ }
1760
+
1761
+ #ifdef mxNever
1762
+ stopTime(&gxSweepChunkTime);
1763
+ startTime(&gxSweepSlotTime);
1764
+ #endif
1765
+
1766
+ aTotal = 0;
1767
+ freeSlot = C_NULL;
1768
+ aSlot = the->firstHeap;
1769
+ while (aSlot) {
1770
+ bSlot = aSlot + 1;
1771
+ cSlot = aSlot->value.reference;
1772
+ while (bSlot < cSlot) {
1773
+ if (bSlot->flag & XS_MARK_FLAG) {
1774
+ bSlot->flag &= ~XS_MARK_FLAG;
1775
+ fxSweepValue(the, bSlot);
1776
+ aTotal++;
1777
+ }
1778
+ else {
1779
+ #ifndef mxLink
1780
+ if (bSlot->kind == XS_HOST_KIND) {
1781
+ if (bSlot->flag & XS_HOST_HOOKS_FLAG) {
1782
+ if (bSlot->value.host.variant.hooks->destructor)
1783
+ (*(bSlot->value.host.variant.hooks->destructor))(bSlot->value.host.data);
1784
+ }
1785
+ else if (bSlot->value.host.variant.destructor)
1786
+ (*(bSlot->value.host.variant.destructor))(bSlot->value.host.data);
1787
+ }
1788
+ #endif
1789
+ // if (bSlot->kind == XS_MODULE_KIND) {
1790
+ // char* name = fxGetKeyName(the, bSlot->value.module.id);
1791
+ // fprintf(stderr, "gc module %d %s\n", bSlot->value.module.id, name);
1792
+ // }
1793
+ #if mxInstrument
1794
+ if (bSlot->kind == XS_MODULE_KIND)
1795
+ the->loadedModulesCount--;
1796
+ #endif
1797
+ bSlot->kind = XS_UNDEFINED_KIND;
1798
+ bSlot->next = freeSlot;
1799
+ #if mxPoisonSlots
1800
+ ASAN_POISON_MEMORY_REGION(&bSlot->value, sizeof(bSlot->value));
1801
+ #endif
1802
+ freeSlot = bSlot;
1803
+ }
1804
+ bSlot++;
1805
+ }
1806
+ aSlot = aSlot->next;
1807
+ }
1808
+ the->currentHeapCount = aTotal;
1809
+ the->freeHeap = freeSlot;
1810
+
1811
+ #ifdef mxNever
1812
+ stopTime(&gxSweepSlotTime);
1813
+ startTime(&gxCompactChunkTime);
1814
+ #endif
1815
+
1816
+ #if mxNoChunks
1817
+ address = (txChunk**)&(the->firstBlock);
1818
+ while ((chunk = *address)) {
1819
+ aSize = chunk->size;
1820
+ if (aSize & mxChunkFlag) {
1821
+ *address = (txChunk*)(chunk->temporary);
1822
+ c_free(chunk);
1823
+ }
1824
+ else {
1825
+ address = (txChunk**)&(chunk->temporary);
1826
+ }
1827
+ }
1828
+ #else
1829
+ aBlock = the->firstBlock;
1830
+ while (aBlock) {
1831
+ txByte* former = C_NULL;
1832
+ current = ((txByte*)aBlock) + sizeof(txBlock);
1833
+ limit = aBlock->current;
1834
+ while (current < limit) {
1835
+ aSize = ((txChunk*)current)->size;
1836
+ next = current + aSize;
1837
+ if ((temporary = ((txChunk*)current)->temporary)) {
1838
+ if (former) {
1839
+ ((txChunk*)former)->temporary = temporary;
1840
+ ((txChunk*)former)->size = (txSize)(temporary - former);
1841
+ }
1842
+ if (temporary != current)
1843
+ c_memmove(temporary, current, aSize);
1844
+ former = temporary;
1845
+ }
1846
+ current = next;
1847
+ }
1848
+ if (former) {
1849
+ ((txChunk*)former)->temporary = aBlock->temporary;
1850
+ ((txChunk*)former)->size = (txSize)(aBlock->temporary - former);
1851
+ }
1852
+ aBlock->current = aBlock->temporary;
1853
+ aBlock->temporary = C_NULL;
1854
+ aBlock = aBlock->nextBlock;
1855
+ }
1856
+ #endif
1857
+
1858
+ #ifdef mxNever
1859
+ stopTime(&gxCompactChunkTime);
1860
+ #endif
1861
+ }
1862
+
1863
+ void fxSweepValue(txMachine* the, txSlot* theSlot)
1864
+ {
1865
+ txSlot* aSlot;
1866
+ txByte* data;
1867
+
1868
+ #define mxSweepChunk(_THE_DATA, _THE_DATA_TYPE) \
1869
+ if ((data = (txByte*)(((txChunk*)(((txByte*)(_THE_DATA)) - sizeof(txChunk)))->temporary))) \
1870
+ ((_THE_DATA)) = (_THE_DATA_TYPE)(data + sizeof(txChunk))
1871
+
1872
+ switch (theSlot->kind) {
1873
+ case XS_STRING_KIND:
1874
+ mxSweepChunk(theSlot->value.string, txString);
1875
+ break;
1876
+ case XS_BIGINT_KIND:
1877
+ mxSweepChunk(theSlot->value.bigint.data, txU4*);
1878
+ break;
1879
+
1880
+ case XS_ARGUMENTS_SLOPPY_KIND:
1881
+ case XS_ARGUMENTS_STRICT_KIND:
1882
+ case XS_ARRAY_KIND:
1883
+ case XS_STACK_KIND:
1884
+ if ((aSlot = theSlot->value.array.address)) {
1885
+ #if mxNoChunks
1886
+ mxSweepChunk(theSlot->value.array.address, txSlot*);
1887
+ aSlot = theSlot->value.array.address;
1888
+ #endif
1889
+ txChunk* chunk = (txChunk*)(((txByte*)aSlot) - sizeof(txChunk));
1890
+ txIndex aLength = chunk->size / sizeof(txSlot);
1891
+ if (aLength > theSlot->value.array.length)
1892
+ aLength = theSlot->value.array.length;
1893
+ while (aLength) {
1894
+ fxSweepValue(the, aSlot);
1895
+ aSlot++;
1896
+ aLength--;
1897
+ }
1898
+ #if mxNoChunks
1899
+ #else
1900
+ mxSweepChunk(theSlot->value.array.address, txSlot*);
1901
+ #endif
1902
+ }
1903
+ break;
1904
+ case XS_ARRAY_BUFFER_KIND:
1905
+ if (theSlot->value.arrayBuffer.address)
1906
+ mxSweepChunk(theSlot->value.arrayBuffer.address, txByte*);
1907
+ break;
1908
+ case XS_CODE_KIND:
1909
+ mxSweepChunk(theSlot->value.code.address, txByte*);
1910
+ break;
1911
+ case XS_GLOBAL_KIND:
1912
+ mxSweepChunk(theSlot->value.table.address, txSlot**);
1913
+ break;
1914
+ case XS_HOST_KIND:
1915
+ if (theSlot->value.host.data) {
1916
+ if ((theSlot->flag & XS_HOST_HOOKS_FLAG) && (theSlot->value.host.variant.hooks->sweeper))
1917
+ (*theSlot->value.host.variant.hooks->sweeper)(the, theSlot->value.host.data, fxSweepValue);
1918
+ if (theSlot->flag & XS_HOST_CHUNK_FLAG)
1919
+ mxSweepChunk(theSlot->value.host.data, void*);
1920
+ }
1921
+ break;
1922
+ case XS_IDS_KIND:
1923
+ if (theSlot->value.IDs)
1924
+ mxSweepChunk(theSlot->value.IDs, txID*);
1925
+ break;
1926
+ case XS_REGEXP_KIND:
1927
+ if (theSlot->value.regexp.code)
1928
+ mxSweepChunk(theSlot->value.regexp.code, void*);
1929
+ if (theSlot->value.regexp.data)
1930
+ mxSweepChunk(theSlot->value.regexp.data, void*);
1931
+ break;
1932
+ case XS_KEY_KIND:
1933
+ if (theSlot->value.key.string)
1934
+ mxSweepChunk(theSlot->value.key.string, txString);
1935
+ break;
1936
+ case XS_MAP_KIND:
1937
+ case XS_SET_KIND:
1938
+ mxSweepChunk(theSlot->value.table.address, txSlot**);
1939
+ break;
1940
+ }
1941
+ }