@agoric/xsnap 0.14.3-u13.0 → 0.14.3-u16.0

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 +39 -22
  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 -646
@@ -0,0 +1,2555 @@
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
+ #define XS_PROFILE_COUNT (256 * 1024)
41
+
42
+ static txSlot* fxCheckHostObject(txMachine* the, txSlot* it);
43
+
44
+ #ifdef mxFrequency
45
+ static void fxReportFrequency(txMachine* the);
46
+ #endif
47
+
48
+ /* Slot */
49
+
50
+ txKind fxTypeOf(txMachine* the, txSlot* theSlot)
51
+ {
52
+ if (theSlot->kind == XS_STRING_X_KIND)
53
+ return XS_STRING_KIND;
54
+ if (theSlot->kind == XS_BIGINT_X_KIND)
55
+ return XS_BIGINT_KIND;
56
+ #ifdef mxHostFunctionPrimitive
57
+ if (theSlot->kind == XS_HOST_FUNCTION_KIND)
58
+ return XS_REFERENCE_KIND;
59
+ #endif
60
+ return theSlot->kind;
61
+ }
62
+
63
+ /* Primitives */
64
+
65
+ void fxUndefined(txMachine* the, txSlot* theSlot)
66
+ {
67
+ theSlot->kind = XS_UNDEFINED_KIND;
68
+ }
69
+
70
+ void fxNull(txMachine* the, txSlot* theSlot)
71
+ {
72
+ theSlot->kind = XS_NULL_KIND;
73
+ }
74
+
75
+ void fxBoolean(txMachine* the, txSlot* theSlot, txS1 theValue)
76
+ {
77
+ theSlot->value.boolean = theValue;
78
+ theSlot->kind = XS_BOOLEAN_KIND;
79
+ }
80
+
81
+ txBoolean fxToBoolean(txMachine* the, txSlot* theSlot)
82
+ {
83
+ switch (theSlot->kind) {
84
+ case XS_UNDEFINED_KIND:
85
+ case XS_NULL_KIND:
86
+ theSlot->kind = XS_BOOLEAN_KIND;
87
+ theSlot->value.boolean = 0;
88
+ break;
89
+ case XS_BOOLEAN_KIND:
90
+ break;
91
+ case XS_INTEGER_KIND:
92
+ theSlot->kind = XS_BOOLEAN_KIND;
93
+ theSlot->value.boolean = (theSlot->value.integer == 0) ? 0 : 1;
94
+ break;
95
+ case XS_NUMBER_KIND:
96
+ theSlot->kind = XS_BOOLEAN_KIND;
97
+ switch (c_fpclassify(theSlot->value.number)) {
98
+ case FP_NAN:
99
+ case FP_ZERO:
100
+ theSlot->value.boolean = 0;
101
+ break;
102
+ default:
103
+ theSlot->value.boolean = 1;
104
+ break;
105
+ }
106
+ break;
107
+ case XS_BIGINT_KIND:
108
+ case XS_BIGINT_X_KIND:
109
+ if ((theSlot->value.bigint.size == 1) && (theSlot->value.bigint.data[0] == 0))
110
+ theSlot->value.boolean = 0;
111
+ else
112
+ theSlot->value.boolean = 1;
113
+ theSlot->kind = XS_BOOLEAN_KIND;
114
+ break;
115
+ case XS_STRING_KIND:
116
+ case XS_STRING_X_KIND:
117
+ theSlot->kind = XS_BOOLEAN_KIND;
118
+ if (c_isEmpty(theSlot->value.string))
119
+ theSlot->value.boolean = 0;
120
+ else
121
+ theSlot->value.boolean = 1;
122
+ break;
123
+ #ifdef mxHostFunctionPrimitive
124
+ case XS_HOST_FUNCTION_KIND:
125
+ #endif
126
+ case XS_SYMBOL_KIND:
127
+ case XS_REFERENCE_KIND:
128
+ theSlot->kind = XS_BOOLEAN_KIND;
129
+ theSlot->value.boolean = 1;
130
+ break;
131
+ default:
132
+ mxTypeError("Cannot coerce to boolean");
133
+ break;
134
+ }
135
+ return theSlot->value.boolean;
136
+ }
137
+
138
+ void fxInteger(txMachine* the, txSlot* theSlot, txInteger theValue)
139
+ {
140
+ theSlot->value.integer = theValue;
141
+ theSlot->kind = XS_INTEGER_KIND;
142
+ }
143
+
144
+ txInteger fxToInteger(txMachine* the, txSlot* theSlot)
145
+ {
146
+ #if mxOptimize
147
+ if (XS_INTEGER_KIND == theSlot->kind)
148
+ return theSlot->value.integer; // this is the case over 90% of the time, so avoid the switch
149
+ #endif
150
+
151
+ again:
152
+ switch (theSlot->kind) {
153
+ case XS_UNDEFINED_KIND:
154
+ case XS_NULL_KIND:
155
+ theSlot->kind = XS_INTEGER_KIND;
156
+ theSlot->value.integer = 0;
157
+ break;
158
+ case XS_BOOLEAN_KIND:
159
+ theSlot->kind = XS_INTEGER_KIND;
160
+ if (theSlot->value.boolean == 0)
161
+ theSlot->value.integer = 0;
162
+ else
163
+ theSlot->value.integer = 1;
164
+ break;
165
+ case XS_INTEGER_KIND:
166
+ break;
167
+ case XS_NUMBER_KIND:
168
+ theSlot->kind = XS_INTEGER_KIND;
169
+ switch (c_fpclassify(theSlot->value.number)) {
170
+ case C_FP_INFINITE:
171
+ case C_FP_NAN:
172
+ case C_FP_ZERO:
173
+ theSlot->value.integer = 0;
174
+ break;
175
+ default: {
176
+ #define MODULO 4294967296.0
177
+ txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO);
178
+ if (aNumber >= MODULO / 2)
179
+ aNumber -= MODULO;
180
+ else if (aNumber < -MODULO / 2)
181
+ aNumber += MODULO;
182
+ theSlot->value.integer = (txInteger)aNumber;
183
+ } break;
184
+ }
185
+ mxFloatingPointOp("number to integer");
186
+ break;
187
+ case XS_STRING_KIND:
188
+ case XS_STRING_X_KIND:
189
+ theSlot->kind = XS_NUMBER_KIND;
190
+ theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1);
191
+ mxMeterOne();
192
+ goto again;
193
+ case XS_SYMBOL_KIND:
194
+ mxTypeError("Cannot coerce symbol to integer");
195
+ break;
196
+ case XS_REFERENCE_KIND:
197
+ fxToPrimitive(the, theSlot, XS_NUMBER_HINT);
198
+ goto again;
199
+ default:
200
+ mxTypeError("Cannot coerce to integer");
201
+ break;
202
+ }
203
+ return theSlot->value.integer;
204
+ }
205
+
206
+ void fxNumber(txMachine* the, txSlot* theSlot, txNumber theValue)
207
+ {
208
+ theSlot->value.number = theValue;
209
+ theSlot->kind = XS_NUMBER_KIND;
210
+ }
211
+
212
+ txNumber fxToNumber(txMachine* the, txSlot* theSlot)
213
+ {
214
+ again:
215
+ switch (theSlot->kind) {
216
+ case XS_UNDEFINED_KIND:
217
+ theSlot->kind = XS_NUMBER_KIND;
218
+ theSlot->value.number = C_NAN;
219
+ break;
220
+ case XS_NULL_KIND:
221
+ theSlot->kind = XS_NUMBER_KIND;
222
+ theSlot->value.number = 0;
223
+ break;
224
+ case XS_BOOLEAN_KIND:
225
+ theSlot->kind = XS_NUMBER_KIND;
226
+ if (theSlot->value.boolean == 0)
227
+ theSlot->value.number = 0;
228
+ else
229
+ theSlot->value.number = 1;
230
+ break;
231
+ case XS_INTEGER_KIND:
232
+ theSlot->kind = XS_NUMBER_KIND;
233
+ theSlot->value.number = theSlot->value.integer;
234
+ mxFloatingPointOp("integer to number");
235
+ break;
236
+ case XS_NUMBER_KIND:
237
+ break;
238
+ case XS_STRING_KIND:
239
+ case XS_STRING_X_KIND:
240
+ theSlot->kind = XS_NUMBER_KIND;
241
+ theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1);
242
+ mxMeterOne();
243
+ break;
244
+ case XS_SYMBOL_KIND:
245
+ mxTypeError("Cannot coerce symbol to number");
246
+ break;
247
+ case XS_REFERENCE_KIND:
248
+ fxToPrimitive(the, theSlot, XS_NUMBER_HINT);
249
+ goto again;
250
+ default:
251
+ mxTypeError("Cannot coerce to number");
252
+ break;
253
+ }
254
+ return theSlot->value.number;
255
+ }
256
+
257
+ void fxString(txMachine* the, txSlot* theSlot, txString theValue)
258
+ {
259
+ fxCopyStringC(the, theSlot, theValue);
260
+ }
261
+
262
+ void fxStringX(txMachine* the, txSlot* theSlot, txString theValue)
263
+ {
264
+ #ifdef mxSnapshot
265
+ fxCopyStringC(the, theSlot, theValue);
266
+ #else
267
+ theSlot->value.string = theValue;
268
+ theSlot->kind = XS_STRING_X_KIND;
269
+ #endif
270
+ }
271
+
272
+ void fxStringBuffer(txMachine* the, txSlot* theSlot, txString theValue, txSize theSize)
273
+ {
274
+ theSlot->value.string = (txString)fxNewChunk(the, fxAddChunkSizes(the, theSize, 1));
275
+ if (theValue)
276
+ c_memcpy(theSlot->value.string, theValue, theSize);
277
+ else
278
+ theSlot->value.string[0] = 0;
279
+ theSlot->value.string[theSize] = 0;
280
+ theSlot->kind = XS_STRING_KIND;
281
+ }
282
+
283
+ txString fxToString(txMachine* the, txSlot* theSlot)
284
+ {
285
+ char aBuffer[256];
286
+ again:
287
+ switch (theSlot->kind) {
288
+ case XS_UNDEFINED_KIND:
289
+ *theSlot = mxUndefinedString;
290
+ break;
291
+ case XS_NULL_KIND:
292
+ fxStringX(the, theSlot, "null");
293
+ break;
294
+ case XS_BOOLEAN_KIND:
295
+ if (theSlot->value.boolean == 0)
296
+ fxStringX(the, theSlot, "false");
297
+ else
298
+ fxStringX(the, theSlot, "true");
299
+ break;
300
+ case XS_INTEGER_KIND:
301
+ fxCopyStringC(the, theSlot, fxIntegerToString(the->dtoa, theSlot->value.integer, aBuffer, sizeof(aBuffer)));
302
+ mxMeterOne();
303
+ break;
304
+ case XS_NUMBER_KIND:
305
+ fxCopyStringC(the, theSlot, fxNumberToString(the->dtoa, theSlot->value.number, aBuffer, sizeof(aBuffer), 0, 0));
306
+ mxMeterOne();
307
+ break;
308
+ case XS_SYMBOL_KIND:
309
+ mxTypeError("Cannot coerce symbol to string");
310
+ break;
311
+ case XS_BIGINT_KIND:
312
+ case XS_BIGINT_X_KIND:
313
+ gxTypeBigInt.toString(the, theSlot, 0);
314
+ break;
315
+ case XS_STRING_KIND:
316
+ case XS_STRING_X_KIND:
317
+ break;
318
+ case XS_REFERENCE_KIND:
319
+ fxToPrimitive(the, theSlot, XS_STRING_HINT);
320
+ goto again;
321
+ default:
322
+ mxTypeError("Cannot coerce to string");
323
+ break;
324
+ }
325
+ return theSlot->value.string;
326
+ }
327
+
328
+ txString fxToStringBuffer(txMachine* the, txSlot* theSlot, txString theBuffer, txSize theSize)
329
+ {
330
+ char* aString;
331
+ txSize aSize;
332
+
333
+ aString = fxToString(the, theSlot);
334
+ aSize = mxStringLength(aString) + 1;
335
+ if (aSize > theSize)
336
+ mxRangeError("Cannot buffer string");
337
+ c_memcpy(theBuffer, aString, aSize);
338
+ return theBuffer;
339
+ }
340
+
341
+ void fxUnsigned(txMachine* the, txSlot* theSlot, txUnsigned theValue)
342
+ {
343
+ if (((txInteger)theValue) >= 0) {
344
+ theSlot->value.integer = theValue;
345
+ theSlot->kind = XS_INTEGER_KIND;
346
+ }
347
+ else {
348
+ theSlot->value.number = theValue;
349
+ theSlot->kind = XS_NUMBER_KIND;
350
+ }
351
+ }
352
+
353
+ txUnsigned fxToUnsigned(txMachine* the, txSlot* theSlot)
354
+ {
355
+ txUnsigned result;
356
+ again:
357
+ switch (theSlot->kind) {
358
+ case XS_UNDEFINED_KIND:
359
+ case XS_NULL_KIND:
360
+ theSlot->kind = XS_INTEGER_KIND;
361
+ result = theSlot->value.integer = 0;
362
+ break;
363
+ case XS_BOOLEAN_KIND:
364
+ theSlot->kind = XS_INTEGER_KIND;
365
+ if (theSlot->value.boolean == 0)
366
+ result = theSlot->value.integer = 0;
367
+ else
368
+ result = theSlot->value.integer = 1;
369
+ break;
370
+ case XS_INTEGER_KIND:
371
+ if (theSlot->value.integer >= 0)
372
+ return (txUnsigned)theSlot->value.integer;
373
+ theSlot->kind = XS_NUMBER_KIND;
374
+ theSlot->value.number = theSlot->value.integer;
375
+ // continue
376
+ case XS_NUMBER_KIND:
377
+ theSlot->kind = XS_INTEGER_KIND;
378
+ switch (c_fpclassify(theSlot->value.number)) {
379
+ case C_FP_INFINITE:
380
+ case C_FP_NAN:
381
+ case C_FP_ZERO:
382
+ result = theSlot->value.integer = 0;
383
+ break;
384
+ default: {
385
+ #define MODULO 4294967296.0
386
+ txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO);
387
+ if (aNumber < 0)
388
+ aNumber += MODULO;
389
+ result = (txUnsigned)aNumber;
390
+ if (((txInteger)result) >= 0) {
391
+ theSlot->kind = XS_INTEGER_KIND;
392
+ theSlot->value.integer = (txInteger)result;
393
+ }
394
+ else {
395
+ theSlot->kind = XS_NUMBER_KIND;
396
+ theSlot->value.number = aNumber;
397
+ }
398
+ } break;
399
+ }
400
+ mxFloatingPointOp("number to unsigned");
401
+ break;
402
+ case XS_STRING_KIND:
403
+ case XS_STRING_X_KIND:
404
+ theSlot->kind = XS_NUMBER_KIND;
405
+ theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1);
406
+ mxMeterOne();
407
+ goto again;
408
+ case XS_SYMBOL_KIND:
409
+ result = 0;
410
+ mxTypeError("Cannot coerce symbol to unsigned");
411
+ break;
412
+ case XS_REFERENCE_KIND:
413
+ fxToPrimitive(the, theSlot, XS_NUMBER_HINT);
414
+ goto again;
415
+ default:
416
+ result = 0;
417
+ mxTypeError("Cannot coerce to unsigned");
418
+ break;
419
+ }
420
+ return result;
421
+ }
422
+
423
+ /* Closures and References */
424
+
425
+ void fxClosure(txMachine* the, txSlot* theSlot, txSlot* theClosure)
426
+ {
427
+ theSlot->value.closure = theClosure;
428
+ theSlot->kind = XS_CLOSURE_KIND;
429
+ }
430
+
431
+ txSlot* fxToClosure(txMachine* the, txSlot* theSlot)
432
+ {
433
+ if (theSlot->kind == XS_CLOSURE_KIND)
434
+ return theSlot->value.closure;
435
+ return NULL;
436
+ }
437
+
438
+ void fxReference(txMachine* the, txSlot* theSlot, txSlot* theReference)
439
+ {
440
+ if (theReference) {
441
+ theSlot->value.reference = theReference;
442
+ theSlot->kind = XS_REFERENCE_KIND;
443
+ }
444
+ else
445
+ theSlot->kind = XS_NULL_KIND;
446
+ }
447
+
448
+ txSlot* fxToReference(txMachine* the, txSlot* theSlot)
449
+ {
450
+ if (theSlot->kind == XS_REFERENCE_KIND)
451
+ return theSlot->value.reference;
452
+ return NULL;
453
+ }
454
+
455
+ /* Instances and Prototypes */
456
+
457
+ txSlot* fxNewArray(txMachine* the, txInteger size)
458
+ {
459
+ txSlot* instance;
460
+ mxPush(mxArrayPrototype);
461
+ instance = fxNewArrayInstance(the);
462
+ fxSetIndexSize(the, instance->next, size, XS_CHUNK);
463
+ return instance;
464
+ }
465
+
466
+ txSlot* fxNewObject(txMachine* the)
467
+ {
468
+ mxPush(mxObjectPrototype);
469
+ return fxNewObjectInstance(the);
470
+ }
471
+
472
+ txBoolean fxIsInstanceOf(txMachine* the)
473
+ {
474
+ txBoolean result = 0;
475
+ txSlot* theInstance = the->stack++;
476
+ txSlot* thePrototype = the->stack++;
477
+
478
+ if (mxIsReference(theInstance) && mxIsReference(thePrototype)) {
479
+ theInstance = fxGetInstance(the, theInstance);
480
+ thePrototype = fxGetInstance(the, thePrototype);
481
+ while (theInstance) {
482
+ if (theInstance == thePrototype) {
483
+ result = 1;
484
+ break;
485
+ }
486
+ theInstance = fxGetPrototype(the, theInstance);
487
+ }
488
+ }
489
+ return result;
490
+ }
491
+
492
+ void fxArrayCacheBegin(txMachine* the, txSlot* reference)
493
+ {
494
+ txSlot* array = reference->value.reference->next;
495
+ array->value.array.address = C_NULL;
496
+ array->value.array.length = 0;
497
+ }
498
+
499
+ void fxArrayCacheEnd(txMachine* the, txSlot* reference)
500
+ {
501
+ txSlot* array = reference->value.reference->next;
502
+ txIndex length = array->value.array.length;
503
+ if (length) {
504
+ txSlot *srcSlot, *dstSlot;
505
+ array->value.array.address = (txSlot*)fxNewChunk(the, fxMultiplyChunkSizes(the, length, sizeof(txSlot)));
506
+ srcSlot = array->next;
507
+ dstSlot = array->value.array.address + length;
508
+ while (srcSlot) {
509
+ dstSlot--;
510
+ length--;
511
+ dstSlot->next = C_NULL;
512
+ dstSlot->ID = XS_NO_ID;
513
+ dstSlot->flag = XS_NO_FLAG;
514
+ dstSlot->kind = srcSlot->kind;
515
+ dstSlot->value = srcSlot->value;
516
+ *((txIndex*)dstSlot) = length;
517
+ srcSlot = srcSlot->next;
518
+ }
519
+ array->next = C_NULL;
520
+ }
521
+ }
522
+
523
+ void fxArrayCacheItem(txMachine* the, txSlot* reference, txSlot* item)
524
+ {
525
+ txSlot* array = reference->value.reference->next;
526
+ txSlot* slot = fxNewSlot(the);
527
+ slot->next = array->next;
528
+ slot->kind = item->kind;
529
+ slot->value = item->value;
530
+ array->next = slot;
531
+ array->value.array.length++;
532
+ }
533
+
534
+ /* Host Constructors, Functions and Objects */
535
+
536
+ void fxBuildHosts(txMachine* the, txInteger c, const txHostFunctionBuilder* builder)
537
+ {
538
+ mxPushInteger(c);
539
+ mxPushInteger(1);
540
+ mxPush(mxArrayPrototype);
541
+ fxNewArrayInstance(the);
542
+ fxArrayCacheBegin(the, the->stack);
543
+ while (c) {
544
+ if (builder->length >= 0) {
545
+ #ifdef mxHostFunctionPrimitive
546
+ mxPushUndefined();
547
+ the->stack->kind = XS_HOST_FUNCTION_KIND;
548
+ the->stack->value.hostFunction.builder = builder;
549
+ the->stack->value.hostFunction.profileID = the->profileID;
550
+ the->profileID++;
551
+ #else
552
+ fxNewHostFunction(the, builder->callback, builder->length, builder->id, XS_NO_ID);
553
+ #endif
554
+ }
555
+ else
556
+ fxNewHostObject(the, (txDestructor)builder->callback);
557
+ fxArrayCacheItem(the, the->stack + 1, the->stack);
558
+ mxPop();
559
+ c--;
560
+ builder++;
561
+ }
562
+ fxArrayCacheEnd(the, the->stack);
563
+ }
564
+
565
+ txSlot* fxNewHostConstructor(txMachine* the, txCallback theCallback, txInteger theLength, txInteger name)
566
+ {
567
+ txSlot* aStack;
568
+ txSlot* instance;
569
+ txSlot* property;
570
+
571
+ fxToInstance(the, the->stack);
572
+ aStack = the->stack;
573
+ instance = fxNewHostFunction(the, theCallback, theLength, name, XS_NO_ID);
574
+ instance->flag |= XS_CAN_CONSTRUCT_FLAG;
575
+ property = fxLastProperty(the, instance);
576
+ fxNextSlotProperty(the, property, aStack, mxID(_prototype), XS_GET_ONLY);
577
+ property = mxBehaviorSetProperty(the, fxGetInstance(the, aStack), mxID(_constructor), 0, XS_OWN);
578
+ property->flag = XS_DONT_ENUM_FLAG;
579
+ property->kind = the->stack->kind;
580
+ property->value = the->stack->value;
581
+ *aStack = *the->stack;
582
+ mxPop();
583
+ return instance;
584
+ }
585
+
586
+ txSlot* fxNewHostFunction(txMachine* the, txCallback theCallback, txInteger theLength, txInteger name, txInteger profileID)
587
+ {
588
+ txSlot* instance;
589
+ txSlot* property;
590
+
591
+ mxPushUndefined();
592
+ instance = fxNewSlot(the);
593
+ instance->flag |= XS_CAN_CALL_FLAG;
594
+ instance->kind = XS_INSTANCE_KIND;
595
+ instance->value.instance.garbage = C_NULL;
596
+ instance->value.instance.prototype = mxFunctionPrototype.value.reference;
597
+ the->stack->value.reference = instance;
598
+ the->stack->kind = XS_REFERENCE_KIND;
599
+
600
+ /* CALLBACK */
601
+ property = instance->next = fxNewSlot(the);
602
+ property->flag = XS_INTERNAL_FLAG;
603
+ property->kind = XS_CALLBACK_KIND;
604
+ property->value.callback.address = theCallback;
605
+ property->value.callback.closures = C_NULL;
606
+
607
+ /* HOME */
608
+ property = property->next = fxNewSlot(the);
609
+ if (profileID != XS_NO_ID)
610
+ property->ID = profileID;
611
+ else
612
+ property->ID = fxGenerateProfileID(the);
613
+ property->flag = XS_INTERNAL_FLAG;
614
+ property->kind = XS_HOME_KIND;
615
+ property->value.home.object = C_NULL;
616
+ if (the->frame && (mxFunction->kind == XS_REFERENCE_KIND) && (mxIsFunction(mxFunction->value.reference))) {
617
+ txSlot* slot = mxFunctionInstanceHome(mxFunction->value.reference);
618
+ property->value.home.module = slot->value.home.module;
619
+ }
620
+ else
621
+ property->value.home.module = C_NULL;
622
+
623
+ /* LENGTH */
624
+ if (gxDefaults.newFunctionLength)
625
+ gxDefaults.newFunctionLength(the, instance, theLength);
626
+
627
+ /* NAME */
628
+ fxRenameFunction(the, instance, name, 0, XS_NO_ID, C_NULL);
629
+
630
+ return instance;
631
+ }
632
+
633
+ txSlot* fxNewHostInstance(txMachine* the)
634
+ {
635
+ txSlot* prototype = fxGetInstance(the, the->stack);
636
+ txSlot* instance = fxNewSlot(the);
637
+ instance->kind = XS_INSTANCE_KIND;
638
+ instance->value.instance.garbage = C_NULL;
639
+ instance->value.instance.prototype = prototype;
640
+ the->stack->value.reference = instance;
641
+ the->stack->kind = XS_REFERENCE_KIND;
642
+ if (prototype) {
643
+ txSlot* prototypeHost = prototype->next;
644
+ if (prototypeHost && (prototypeHost->kind == XS_HOST_KIND) && (prototypeHost->value.host.variant.destructor != fxReleaseSharedChunk)) {
645
+ txSlot* instanceHost = instance->next = fxNewSlot(the);
646
+ instanceHost->flag = XS_INTERNAL_FLAG;
647
+ instanceHost->kind = XS_HOST_KIND;
648
+ instanceHost->value.host.data = C_NULL;
649
+ if (prototypeHost->flag & XS_HOST_HOOKS_FLAG) {
650
+ instanceHost->flag |= XS_HOST_HOOKS_FLAG;
651
+ instanceHost->value.host.variant.hooks = prototypeHost->value.host.variant.hooks;
652
+ }
653
+ else {
654
+ instanceHost->value.host.variant.destructor = prototypeHost->value.host.variant.destructor;
655
+ }
656
+ }
657
+ }
658
+ return instance;
659
+ }
660
+
661
+
662
+ txSlot* fxCheckHostObject(txMachine* the, txSlot* it)
663
+ {
664
+ txSlot* result = C_NULL;
665
+ if (it->kind == XS_REFERENCE_KIND) {
666
+ it = it->value.reference;
667
+ if (it->next) {
668
+ it = it->next;
669
+ if ((it->flag & XS_INTERNAL_FLAG) && (it->kind == XS_HOST_KIND))
670
+ result = it;
671
+ }
672
+ }
673
+ return result;
674
+ }
675
+
676
+ txSlot* fxNewHostObject(txMachine* the, txDestructor theDestructor)
677
+ {
678
+ txSlot* anInstance;
679
+ txSlot* aProperty;
680
+
681
+ mxPushUndefined();
682
+
683
+ anInstance = fxNewSlot(the);
684
+ anInstance->kind = XS_INSTANCE_KIND;
685
+ anInstance->value.instance.garbage = C_NULL;
686
+ anInstance->value.instance.prototype = mxObjectPrototype.value.reference;
687
+ the->stack->value.reference = anInstance;
688
+ the->stack->kind = XS_REFERENCE_KIND;
689
+
690
+ aProperty = anInstance->next = fxNewSlot(the);
691
+ aProperty->flag = XS_INTERNAL_FLAG;
692
+ aProperty->kind = XS_HOST_KIND;
693
+ aProperty->value.host.data = C_NULL;
694
+ aProperty->value.host.variant.destructor = theDestructor;
695
+
696
+ return anInstance;
697
+ }
698
+
699
+ txInteger fxGetHostBufferLength(txMachine* the, txSlot* slot)
700
+ {
701
+ txSlot* host = fxCheckHostObject(the, slot);
702
+ if (host) {
703
+ txSlot* bufferInfo = host->next;
704
+ if (host->flag & XS_HOST_CHUNK_FLAG)
705
+ mxSyntaxError("C: xsGetHostBufferLength: no host data");
706
+ if (!bufferInfo || (bufferInfo->kind != XS_BUFFER_INFO_KIND))
707
+ mxSyntaxError("C: xsGetHostBufferLength: no host buffer");
708
+ return bufferInfo->value.bufferInfo.length;
709
+ }
710
+ mxSyntaxError("C: xsGetHostData: no host object");
711
+ return 0;
712
+ }
713
+
714
+ void* fxGetHostChunk(txMachine* the, txSlot* slot)
715
+ {
716
+ txSlot* host = fxCheckHostObject(the, slot);
717
+ if (host) {
718
+ if (host->flag & XS_HOST_CHUNK_FLAG)
719
+ return host->value.host.data;
720
+ mxSyntaxError("C: xsGetHostChunk: no host data");
721
+ }
722
+ mxSyntaxError("C: xsGetHostChunk: no host object");
723
+ return NULL;
724
+ }
725
+
726
+ void* fxGetHostChunkValidate(txMachine* the, txSlot* slot, void* validator)
727
+ {
728
+ txSlot* host = fxCheckHostObject(the, slot);
729
+ if (host) {
730
+ if (host->flag & XS_HOST_CHUNK_FLAG) {
731
+ if (validator == host->value.host.variant.destructor)
732
+ return host->value.host.data;
733
+ mxSyntaxError("C: xsGetHostChunk: invalid");
734
+ }
735
+ mxSyntaxError("C: xsGetHostChunk: no host data");
736
+ }
737
+ mxSyntaxError("C: xsGetHostChunk: no host object");
738
+ return NULL;
739
+ }
740
+
741
+ void* fxGetHostChunkIf(txMachine* the, txSlot* slot)
742
+ {
743
+ txSlot* host = fxCheckHostObject(the, slot);
744
+ if (host) {
745
+ if (host->flag & XS_HOST_CHUNK_FLAG)
746
+ return host->value.host.data;
747
+ }
748
+ return NULL;
749
+ }
750
+
751
+ void* fxGetHostData(txMachine* the, txSlot* slot)
752
+ {
753
+ txSlot* host = fxCheckHostObject(the, slot);
754
+ if (host) {
755
+ if (!(host->flag & XS_HOST_CHUNK_FLAG))
756
+ return host->value.host.data;
757
+ mxSyntaxError("C: xsGetHostData: no host data");
758
+ }
759
+ mxSyntaxError("C: xsGetHostData: no host object");
760
+ return NULL;
761
+ }
762
+
763
+ void* fxGetHostDataValidate(txMachine* the, txSlot* slot, void* validator)
764
+ {
765
+ txSlot* host = fxCheckHostObject(the, slot);
766
+ if (host) {
767
+ if (!(host->flag & XS_HOST_CHUNK_FLAG)) {
768
+ if (validator == host->value.host.variant.destructor)
769
+ return host->value.host.data;
770
+ mxSyntaxError("C: xsGetHostData: invalid");
771
+ }
772
+ mxSyntaxError("C: xsGetHostData: no host data");
773
+ }
774
+ mxSyntaxError("C: xsGetHostData: no host object");
775
+ return NULL;
776
+ }
777
+
778
+ void* fxGetHostDataIf(txMachine* the, txSlot* slot)
779
+ {
780
+ txSlot* host = fxCheckHostObject(the, slot);
781
+ if (host) {
782
+ if (!(host->flag & XS_HOST_CHUNK_FLAG))
783
+ return host->value.host.data;
784
+ }
785
+ return NULL;
786
+ }
787
+
788
+ txDestructor fxGetHostDestructor(txMachine* the, txSlot* slot)
789
+ {
790
+ txSlot* host = fxCheckHostObject(the, slot);
791
+ if (host) {
792
+ if (!(host->flag & XS_HOST_HOOKS_FLAG))
793
+ return host->value.host.variant.destructor;
794
+ mxSyntaxError("C: xsGetHostDestructor: no host destructor");
795
+ }
796
+ mxSyntaxError("C: xsGetHostDestructor: no host object");
797
+ return NULL;
798
+ }
799
+
800
+ void* fxGetHostHandle(txMachine* the, txSlot* slot)
801
+ {
802
+ txSlot* host = fxCheckHostObject(the, slot);
803
+ if (host) {
804
+ return &host->value.host.data;
805
+ }
806
+ mxSyntaxError("C: xsGetHostData: no host object");
807
+ return NULL;
808
+ }
809
+
810
+ txHostHooks* fxGetHostHooks(txMachine* the, txSlot* slot)
811
+ {
812
+ txSlot* host = fxCheckHostObject(the, slot);
813
+ if (host) {
814
+ if (host->flag & XS_HOST_HOOKS_FLAG)
815
+ return host->value.host.variant.hooks;
816
+ mxSyntaxError("C: xsGetHostHooks: no host hooks");
817
+ }
818
+ mxSyntaxError("C: xsGetHostHooks: no host object");
819
+ return NULL;
820
+ }
821
+
822
+ void fxPetrifyHostBuffer(txMachine* the, txSlot* slot)
823
+ {
824
+ txSlot* host = fxCheckHostObject(the, slot);
825
+ if (!host)
826
+ mxSyntaxError("C: xsPetrifyHostBuffer: no host object");
827
+ if (host->flag & XS_HOST_CHUNK_FLAG)
828
+ mxSyntaxError("C: xsPetrifyHostBuffer: no host data");
829
+ host->flag |= XS_DONT_SET_FLAG;
830
+ }
831
+
832
+ void fxSetHostBuffer(txMachine* the, txSlot* slot, void* theData, txSize theSize)
833
+ {
834
+ txSlot* host = fxCheckHostObject(the, slot);
835
+ if (host) {
836
+ txSlot* bufferInfo = host->next;
837
+ if (!bufferInfo || (bufferInfo->kind != XS_BUFFER_INFO_KIND)) {
838
+ bufferInfo = fxNewSlot(the);
839
+ bufferInfo->next = host->next;
840
+ bufferInfo->flag = XS_INTERNAL_FLAG;
841
+ bufferInfo->kind = XS_BUFFER_INFO_KIND;
842
+ bufferInfo->value.bufferInfo.length = 0;
843
+ bufferInfo->value.bufferInfo.maxLength = -1;
844
+ host->next = bufferInfo;
845
+ }
846
+ host->flag &= ~XS_HOST_CHUNK_FLAG;
847
+ host->value.host.data = theData;
848
+ bufferInfo->value.bufferInfo.length = theSize;
849
+ }
850
+ else
851
+ mxSyntaxError("C: xsSetHostData: no host object");
852
+ }
853
+
854
+ void *fxSetHostChunk(txMachine* the, txSlot* slot, void* theValue, txSize theSize)
855
+ {
856
+ txSlot* host = fxCheckHostObject(the, slot);
857
+ if (host) {
858
+ host->flag |= XS_HOST_CHUNK_FLAG;
859
+ host->value.host.data = fxNewChunk(the, theSize);
860
+ if (theValue)
861
+ c_memcpy(host->value.host.data, theValue, theSize);
862
+ else
863
+ c_memset(host->value.host.data, 0, theSize);
864
+ return host->value.host.data;
865
+ }
866
+ else
867
+ mxSyntaxError("C: xsSetHostData: no host object");
868
+
869
+ return NULL;
870
+ }
871
+
872
+ void fxSetHostData(txMachine* the, txSlot* slot, void* theData)
873
+ {
874
+ txSlot* host = fxCheckHostObject(the, slot);
875
+ if (host) {
876
+ host->flag &= ~XS_HOST_CHUNK_FLAG;
877
+ host->value.host.data = theData;
878
+ }
879
+ else
880
+ mxSyntaxError("C: xsSetHostData: no host object");
881
+ }
882
+
883
+ void fxSetHostDestructor(txMachine* the, txSlot* slot, txDestructor theDestructor)
884
+ {
885
+ txSlot* host = fxCheckHostObject(the, slot);
886
+ if (host) {
887
+ host->flag &= ~XS_HOST_HOOKS_FLAG;
888
+ host->value.host.variant.destructor = theDestructor;
889
+ }
890
+ else
891
+ mxSyntaxError("C: xsSetHostDestructor: no host object");
892
+ }
893
+
894
+ void fxSetHostHooks(txMachine* the, txSlot* slot, const txHostHooks* theHooks)
895
+ {
896
+ txSlot* host = fxCheckHostObject(the, slot);
897
+ if (host) {
898
+ host->flag |= XS_HOST_HOOKS_FLAG;
899
+ host->value.host.variant.hooks = (txHostHooks *) theHooks;
900
+ }
901
+ else
902
+ mxSyntaxError("C: xsSetHostHooks: no host object");
903
+ }
904
+
905
+ /* Identifiers */
906
+
907
+ txID fxID(txMachine* the, txString theName)
908
+ {
909
+ return fxNewNameC(the, theName);
910
+ }
911
+
912
+ txID fxFindID(txMachine* the, txString theName)
913
+ {
914
+ return fxFindName(the, theName);
915
+ }
916
+
917
+ txS1 fxIsID(txMachine* the, txString theName)
918
+ {
919
+ return fxFindName(the, theName) ? 1 : 0;
920
+ }
921
+
922
+ txID fxToID(txMachine* the, txSlot* theSlot)
923
+ {
924
+ txString string = fxToString(the, theSlot);
925
+ if (theSlot->kind == XS_STRING_KIND)
926
+ return fxNewName(the, theSlot);
927
+ return fxNewNameX(the, string);
928
+ }
929
+
930
+ txString fxName(txMachine* the, txID theID)
931
+ {
932
+ return fxGetKeyName(the, theID);
933
+ }
934
+
935
+ /* Properties */
936
+
937
+ void fxEnumerate(txMachine* the)
938
+ {
939
+ mxPush(mxEnumeratorFunction);
940
+ mxCall();
941
+ mxRunCount(0);
942
+ }
943
+
944
+ void fxGetAll(txMachine* the, txID id, txIndex index)
945
+ {
946
+ txBoolean flag = mxIsReference(the->stack) ? 1 : 0;
947
+ txSlot* instance = (flag) ? the->stack->value.reference : fxToInstance(the, the->stack);
948
+ txSlot* property = mxBehaviorGetProperty(the, instance, (txID)id, index, XS_ANY);
949
+ if (!property) {
950
+ the->stack->kind = XS_UNDEFINED_KIND;
951
+ }
952
+ else if (property->kind == XS_ACCESSOR_KIND) {
953
+ txSlot* function = property->value.accessor.getter;
954
+ if (mxIsFunction(function)) {
955
+ txSlot* slot;
956
+ mxOverflow(-5);
957
+ the->stack -= 5;
958
+ slot = the->stack;
959
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
960
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
961
+ mxInitSlotKind(slot++, XS_UNDEFINED_KIND);
962
+ mxInitSlotKind(slot++, XS_UNDEFINED_KIND);
963
+ slot->value.reference = function;
964
+ mxInitSlotKind(slot++, XS_REFERENCE_KIND);
965
+ if (!flag) {
966
+ txSlot* primitive = instance->next;
967
+ slot->value = primitive->value;
968
+ mxInitSlotKind(slot, primitive->kind);
969
+ }
970
+ mxRunCount(0);
971
+ }
972
+ else
973
+ the->stack->kind = XS_UNDEFINED_KIND;
974
+ }
975
+ else {
976
+ the->stack->kind = property->kind;
977
+ the->stack->value = property->value;
978
+ }
979
+ }
980
+
981
+ void fxGetAt(txMachine* the)
982
+ {
983
+ txSlot* at = fxAt(the, the->stack);
984
+ mxPop();
985
+ mxGetAll(at->value.at.id, at->value.at.index);
986
+ }
987
+
988
+ void fxGetID(txMachine* the, txID id)
989
+ {
990
+ mxGetAll(id, 0);
991
+ }
992
+
993
+ void fxGetIndex(txMachine* the, txIndex index)
994
+ {
995
+ mxGetAll(XS_NO_ID, index);
996
+ }
997
+
998
+ txBoolean fxHasAll(txMachine* the, txID id, txIndex index)
999
+ {
1000
+ txSlot* instance = fxToInstance(the, the->stack);
1001
+ txBoolean result = mxBehaviorHasProperty(the, instance, id, index);
1002
+ mxPop();
1003
+ return result;
1004
+ }
1005
+
1006
+ txBoolean fxHasAt(txMachine* the)
1007
+ {
1008
+ txSlot* at = fxAt(the, the->stack);
1009
+ mxPop();
1010
+ return mxHasAll(at->value.at.id, at->value.at.index);
1011
+ }
1012
+
1013
+ txBoolean fxHasID(txMachine* the, txID id)
1014
+ {
1015
+ return mxHasAll(id, 0);
1016
+ }
1017
+
1018
+ txBoolean fxHasIndex(txMachine* the, txIndex index)
1019
+ {
1020
+ return mxHasAll(XS_NO_ID, index);
1021
+ }
1022
+
1023
+ void fxSetAll(txMachine* the, txID id, txIndex index)
1024
+ {
1025
+ txSlot* value = the->stack + 1;
1026
+ txSlot* instance = fxToInstance(the, the->stack);
1027
+ txSlot* property = mxBehaviorSetProperty(the, instance, (txID)id, index, XS_ANY);
1028
+ if (!property)
1029
+ mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: not extensible", id);
1030
+ if (property->kind == XS_ACCESSOR_KIND) {
1031
+ txSlot* slot;
1032
+ txSlot* function = property->value.accessor.setter;
1033
+ if (!mxIsFunction(function))
1034
+ mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: no setter", id);
1035
+ mxOverflow(-5);
1036
+ the->stack -= 5;
1037
+ slot = the->stack;
1038
+ slot->value = value->value;
1039
+ mxInitSlotKind(slot++, value->kind);
1040
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
1041
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
1042
+ slot->value = value->value;
1043
+ mxInitSlotKind(slot++, value->kind);
1044
+ mxInitSlotKind(slot++, XS_UNDEFINED_KIND);
1045
+ slot->value.reference = function;
1046
+ mxInitSlotKind(slot++, XS_REFERENCE_KIND);
1047
+ slot->value.reference = instance;
1048
+ mxInitSlotKind(slot, XS_REFERENCE_KIND);
1049
+ mxRunCount(1);
1050
+ }
1051
+ else {
1052
+ if (property->flag & XS_DONT_SET_FLAG)
1053
+ mxDebugID(XS_TYPE_ERROR, "C: xsSet %s: not writable", id);
1054
+ property->kind = value->kind;
1055
+ property->value = value->value;
1056
+ mxPop();
1057
+ }
1058
+ }
1059
+
1060
+ void fxSetAt(txMachine* the)
1061
+ {
1062
+ txSlot* at = fxAt(the, the->stack);
1063
+ mxPop();
1064
+ mxSetAll(at->value.at.id, at->value.at.index);
1065
+ }
1066
+
1067
+ void fxSetID(txMachine* the, txID id)
1068
+ {
1069
+ mxSetAll(id, 0);
1070
+ }
1071
+
1072
+ void fxSetIndex(txMachine* the, txIndex index)
1073
+ {
1074
+ mxSetAll(XS_NO_ID, index);
1075
+ }
1076
+
1077
+ void fxDeleteAll(txMachine* the, txID id, txIndex index)
1078
+ {
1079
+ txSlot* instance = fxToInstance(the, the->stack);
1080
+ if (!mxBehaviorDeleteProperty(the, instance, (txID)id, index))
1081
+ mxDebugID(XS_TYPE_ERROR, "delete %s: not configurable", id);
1082
+ }
1083
+
1084
+ void fxDeleteAt(txMachine* the)
1085
+ {
1086
+ txSlot* at = fxAt(the, the->stack);
1087
+ txSlot* instance = fxToInstance(the, the->stack + 1);
1088
+ mxPop();
1089
+ if (!mxBehaviorDeleteProperty(the, instance, at->value.at.id, at->value.at.index))
1090
+ mxDebugID(XS_TYPE_ERROR, "delete %s: not configurable", at->value.at.id);
1091
+ }
1092
+
1093
+ void fxDeleteID(txMachine* the, txID id)
1094
+ {
1095
+ txSlot* instance = fxToInstance(the, the->stack);
1096
+ if (!mxBehaviorDeleteProperty(the, instance, (txID)id, 0))
1097
+ mxDebugID(XS_TYPE_ERROR, "delete %s: not configurable", id);
1098
+ }
1099
+
1100
+ void fxDeleteIndex(txMachine* the, txIndex index)
1101
+ {
1102
+ txSlot* instance = fxToInstance(the, the->stack);
1103
+ if (!mxBehaviorDeleteProperty(the, instance, XS_NO_ID, index))
1104
+ mxTypeError("delete %ld: not configurable", index);
1105
+ }
1106
+
1107
+ void fxDefineAll(txMachine* the, txID id, txIndex index, txFlag flag, txFlag mask)
1108
+ {
1109
+ txSlot* instance = fxToInstance(the, the->stack);
1110
+ txSlot* slot = the->stack + 1;
1111
+ if (mask & XS_GETTER_FLAG) {
1112
+ slot->value.accessor.getter = slot->value.reference;
1113
+ slot->value.accessor.setter = C_NULL;
1114
+ slot->kind = XS_ACCESSOR_KIND;
1115
+ }
1116
+ else if (mask & XS_SETTER_FLAG) {
1117
+ slot->value.accessor.setter = slot->value.reference;
1118
+ slot->value.accessor.getter = C_NULL;
1119
+ slot->kind = XS_ACCESSOR_KIND;
1120
+ }
1121
+ slot->flag = flag & XS_GET_ONLY;
1122
+ if (!mxBehaviorDefineOwnProperty(the, instance, id, index, slot, mask))
1123
+ mxTypeError("define %ld: not configurable", id);
1124
+ mxPop();
1125
+ }
1126
+
1127
+ void fxDefineAt(txMachine* the, txFlag flag, txFlag mask)
1128
+ {
1129
+ txSlot* at = fxAt(the, the->stack++);
1130
+ mxDefineAll(at->value.at.id, at->value.at.index, flag, mask);
1131
+ }
1132
+
1133
+ void fxDefineID(txMachine* the, txID id, txFlag flag, txFlag mask)
1134
+ {
1135
+ mxDefineAll(id, 0, flag, mask);
1136
+ }
1137
+
1138
+ void fxDefineIndex(txMachine* the, txIndex index, txFlag flag, txFlag mask)
1139
+ {
1140
+ mxDefineAll(XS_NO_ID, index, flag, mask);
1141
+ }
1142
+
1143
+ void fxCall(txMachine* the)
1144
+ {
1145
+ // TARGET
1146
+ (--the->stack)->next = C_NULL;
1147
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1148
+ // RESULT
1149
+ (--the->stack)->next = C_NULL;
1150
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1151
+ // FRAME
1152
+ (--the->stack)->next = C_NULL;
1153
+ mxInitSlotKind(the->stack, XS_UNINITIALIZED_KIND);
1154
+ // COUNT
1155
+ (--the->stack)->next = C_NULL;
1156
+ mxInitSlotKind(the->stack, XS_UNINITIALIZED_KIND);
1157
+ }
1158
+
1159
+ void fxCallID(txMachine* the, txID theID)
1160
+ {
1161
+ mxDub();
1162
+ mxGetID(theID);
1163
+ fxCall(the);
1164
+ }
1165
+
1166
+ void fxCallFrame(txMachine* the)
1167
+ {
1168
+ mxOverflow(-4);
1169
+ fxCall(the);
1170
+ }
1171
+
1172
+ void fxNew(txMachine* the)
1173
+ {
1174
+ txSlot* constructor = the->stack;
1175
+ txSlot* slot = constructor - 5;
1176
+ the->stack = slot;
1177
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
1178
+ mxInitSlotKind(slot++, XS_UNINITIALIZED_KIND);
1179
+ mxInitSlotKind(slot++, XS_UNDEFINED_KIND);
1180
+ slot->value = constructor->value;
1181
+ mxInitSlotKind(slot++, constructor->kind);
1182
+ slot->value = constructor->value;
1183
+ mxInitSlotKind(slot++, constructor->kind);
1184
+ mxInitSlotKind(slot, XS_UNINITIALIZED_KIND);
1185
+ }
1186
+
1187
+ void fxNewID(txMachine* the, txID theID)
1188
+ {
1189
+ mxGetID(theID);
1190
+ fxNew(the);
1191
+ }
1192
+
1193
+ void fxNewFrame(txMachine* the)
1194
+ {
1195
+ mxOverflow(-5);
1196
+ fxNew(the);
1197
+ }
1198
+
1199
+ void fxRunCount(txMachine* the, txInteger count)
1200
+ {
1201
+ fxRunID(the, C_NULL, count);
1202
+ }
1203
+
1204
+ txBoolean fxRunTest(txMachine* the)
1205
+ {
1206
+ txBoolean result;
1207
+
1208
+ switch (the->stack->kind) {
1209
+ case XS_UNDEFINED_KIND:
1210
+ case XS_NULL_KIND:
1211
+ result = 0;
1212
+ break;
1213
+ case XS_BOOLEAN_KIND:
1214
+ result = the->stack->value.boolean;
1215
+ break;
1216
+ case XS_INTEGER_KIND:
1217
+ result = (the->stack->value.integer == 0) ? 0 : 1;
1218
+ break;
1219
+ case XS_NUMBER_KIND:
1220
+ switch (c_fpclassify(the->stack->value.number)) {
1221
+ case FP_NAN:
1222
+ case FP_ZERO:
1223
+ result = 0;
1224
+ break;
1225
+ default:
1226
+ result = 1;
1227
+ break;
1228
+ }
1229
+ break;
1230
+ case XS_STRING_KIND:
1231
+ case XS_STRING_X_KIND:
1232
+ if (c_isEmpty(the->stack->value.string))
1233
+ result = 0;
1234
+ else
1235
+ result = 1;
1236
+ break;
1237
+ default:
1238
+ result = 1;
1239
+ break;
1240
+ }
1241
+ mxPop();
1242
+ return result;
1243
+ }
1244
+
1245
+ /* Arguments and Variables */
1246
+
1247
+ void fxVars(txMachine* the, txInteger theCount)
1248
+ {
1249
+ if (the->scope != the->stack)
1250
+ mxSyntaxError("C: xsVars: too late");
1251
+ mxOverflow(theCount);
1252
+ the->scope->value.environment.variable.count = theCount;
1253
+ while (theCount) {
1254
+ mxPushUndefined();
1255
+ theCount--;
1256
+ }
1257
+ }
1258
+
1259
+ txInteger fxCheckArg(txMachine* the, txInteger theIndex)
1260
+ {
1261
+ if ((theIndex < 0) || (mxArgc <= theIndex))
1262
+ mxSyntaxError("C: xsArg(%ld): invalid index", theIndex);
1263
+ return theIndex;
1264
+ }
1265
+
1266
+ txInteger fxCheckVar(txMachine* the, txInteger theIndex)
1267
+ {
1268
+ if ((theIndex < 0) || (mxVarc <= theIndex))
1269
+ mxSyntaxError("C: xsVar(%ld): invalid index", theIndex);
1270
+ return theIndex;
1271
+ }
1272
+
1273
+ void fxOverflow(txMachine* the, txInteger theCount, txString thePath, txInteger theLine)
1274
+ {
1275
+ txSlot* aStack = the->stack + theCount;
1276
+ if (theCount < 0) {
1277
+ if (aStack < the->stackBottom) {
1278
+ fxReport(the, "stack overflow (%ld)!\n", (the->stack - the->stackBottom) + theCount);
1279
+ fxAbort(the, XS_STACK_OVERFLOW_EXIT);
1280
+ }
1281
+ }
1282
+ else if (theCount > 0) {
1283
+ if (aStack > the->stackTop) {
1284
+ fxReport(the, "stack overflow (%ld)!\n", theCount - (the->stackTop - the->stack));
1285
+ fxAbort(the, XS_STACK_OVERFLOW_EXIT);
1286
+ }
1287
+ }
1288
+ }
1289
+
1290
+ /* Exceptions */
1291
+
1292
+ void fxThrow(txMachine* the, txString path, txInteger line)
1293
+ {
1294
+ #ifdef mxDebug
1295
+ fxDebugThrow(the, path, line, "C: xsThrow");
1296
+ #endif
1297
+ fxJump(the);
1298
+ }
1299
+
1300
+ void fxThrowMessage(txMachine* the, txString path, txInteger line, txError error, txString format, ...)
1301
+ {
1302
+ char message[128] = "";
1303
+ txSize length = 0;
1304
+ va_list arguments;
1305
+ txSlot* slot;
1306
+ #ifdef mxDebug
1307
+ fxBufferFrameName(the, message, sizeof(message), the->frame, ": ");
1308
+ length = mxStringLength(message);
1309
+ #endif
1310
+ va_start(arguments, format);
1311
+ c_vsnprintf(message + length, sizeof(message) - length, format, arguments);
1312
+ va_end(arguments);
1313
+
1314
+ length = c_strlen(message) - 1;
1315
+ while (length && (0x80 & message[length]))
1316
+ message[length--] = 0;
1317
+
1318
+ if ((error <= XS_NO_ERROR) || (XS_ERROR_COUNT <= error))
1319
+ error = XS_UNKNOWN_ERROR;
1320
+
1321
+ slot = fxNewSlot(the);
1322
+ slot->kind = XS_INSTANCE_KIND;
1323
+ slot->value.instance.garbage = C_NULL;
1324
+ slot->value.instance.prototype = mxErrorPrototypes(error).value.reference;
1325
+ mxException.kind = XS_REFERENCE_KIND;
1326
+ mxException.value.reference = slot;
1327
+ slot = slot->next = fxNewSlot(the);
1328
+ slot->flag = XS_INTERNAL_FLAG;
1329
+ slot->kind = XS_ERROR_KIND;
1330
+ slot->value.error.info = C_NULL;
1331
+ slot->value.error.which = error;
1332
+ if (gxDefaults.captureErrorStack)
1333
+ gxDefaults.captureErrorStack(the, slot, the->frame);
1334
+ slot = fxNextStringProperty(the, slot, message, mxID(_message), XS_DONT_ENUM_FLAG);
1335
+ #ifdef mxDebug
1336
+ fxDebugThrow(the, path, line, message);
1337
+ #endif
1338
+ fxJump(the);
1339
+ }
1340
+
1341
+ /* Debugger */
1342
+
1343
+ void fxDebugger(txMachine* the, txString thePath, txInteger theLine)
1344
+ {
1345
+ #ifdef mxDebug
1346
+ fxDebugLoop(the, thePath, theLine, "C: xsDebugger");
1347
+ #endif
1348
+ }
1349
+
1350
+ /* Machine */
1351
+
1352
+ const txByte gxNoCode[3] ICACHE_FLASH_ATTR = { XS_CODE_BEGIN_STRICT, 0, XS_CODE_END };
1353
+
1354
+ txMachine* fxCreateMachine(txCreation* theCreation, txString theName, void* theContext, txID profileID)
1355
+ {
1356
+ txMachine* the = (txMachine* )c_calloc(sizeof(txMachine), 1);
1357
+ if (the) {
1358
+ txJump aJump;
1359
+
1360
+ aJump.nextJump = C_NULL;
1361
+ aJump.stack = C_NULL;
1362
+ aJump.scope = C_NULL;
1363
+ aJump.frame = C_NULL;
1364
+ aJump.code = C_NULL;
1365
+ aJump.flag = 0;
1366
+ the->firstJump = &aJump;
1367
+ if (c_setjmp(aJump.buffer) == 0) {
1368
+ txInteger id;
1369
+ txSlot* slot;
1370
+
1371
+ if (gxDefaults.initializeSharedCluster)
1372
+ gxDefaults.initializeSharedCluster();
1373
+
1374
+ the->dtoa = fxNew_dtoa(the);
1375
+ the->context = theContext;
1376
+ fxCreateMachinePlatform(the);
1377
+
1378
+ #ifdef mxDebug
1379
+ the->name = theName;
1380
+ #endif
1381
+ the->profileID = (profileID != XS_NO_ID) ? profileID : mxBaseProfileID;
1382
+ fxAllocate(the, theCreation);
1383
+
1384
+ c_memset(the->nameTable, 0, the->nameModulo * sizeof(txSlot *));
1385
+ c_memset(the->symbolTable, 0, the->symbolModulo * sizeof(txSlot *));
1386
+
1387
+ /* mxGlobal */
1388
+ mxPushUndefined();
1389
+ /* mxException */
1390
+ mxPushUndefined();
1391
+ /* mxProgram */
1392
+ mxPushNull();
1393
+ fxNewProgramInstance(the);
1394
+ /* mxHosts */
1395
+ mxPushUndefined();
1396
+ /* mxModuleQueue */
1397
+ fxNewInstance(the);
1398
+ /* mxUnhandledPromises */
1399
+ fxNewInstance(the);
1400
+ /* mxDuringJobs */
1401
+ fxNewInstance(the);
1402
+ /* mxFinalizationRegistries */
1403
+ fxNewInstance(the);
1404
+ /* mxPendingJobs */
1405
+ fxNewInstance(the);
1406
+ /* mxRunningJobs */
1407
+ fxNewInstance(the);
1408
+ /* mxBreakpoints */
1409
+ mxPushList();
1410
+ /* mxHostInspectors */
1411
+ mxPushList();
1412
+ /* mxInstanceInspectors */
1413
+ mxPushList();
1414
+
1415
+ for (id = mxInstanceInspectorsStackIndex + 1; id < mxEmptyCodeStackIndex; id++)
1416
+ mxPushUndefined();
1417
+
1418
+ /* mxEmptyCode */
1419
+ mxPushUndefined();
1420
+ the->stack->value.code.address = (txByte*)gxNoCode;
1421
+ the->stack->value.code.closures = C_NULL;
1422
+ the->stack->kind = XS_CODE_X_KIND;
1423
+ /* mxEmptyString */
1424
+ mxPushStringX("");
1425
+ /* mxEmptyRegExp */
1426
+ mxPushStringX("(?:)");
1427
+ /* mxBigIntString */
1428
+ mxPushStringX("bigint");
1429
+ /* mxBooleanString */
1430
+ mxPushStringX("boolean");
1431
+ /* mxDefaultString */
1432
+ mxPushStringX("default");
1433
+ /* mxFunctionString */
1434
+ mxPushStringX("function");
1435
+ /* mxNumberString */
1436
+ mxPushStringX("number");
1437
+ /* mxObjectString */
1438
+ mxPushStringX("object");
1439
+ /* mxStringString */
1440
+ mxPushStringX("string");
1441
+ /* mxSymbolString */
1442
+ mxPushStringX("symbol");
1443
+ /* mxUndefinedString */
1444
+ mxPushStringX("undefined");
1445
+
1446
+ fxBuildKeys(the);
1447
+ fxBuildGlobal(the);
1448
+ fxBuildObject(the);
1449
+ fxBuildFunction(the);
1450
+ fxBuildGenerator(the);
1451
+ fxBuildArguments(the);
1452
+ fxBuildArray(the);
1453
+ fxBuildString(the);
1454
+ fxBuildBoolean(the);
1455
+ fxBuildNumber(the);
1456
+ fxBuildBigInt(the);
1457
+ fxBuildDate(the);
1458
+ fxBuildMath(the);
1459
+ fxBuildRegExp(the);
1460
+ fxBuildError(the);
1461
+ fxBuildJSON(the);
1462
+ fxBuildDataView(the);
1463
+ fxBuildAtomics(the);
1464
+ fxBuildPromise(the);
1465
+ fxBuildSymbol(the);
1466
+ fxBuildProxy(the);
1467
+ fxBuildMapSet(the);
1468
+ fxBuildModule(the);
1469
+
1470
+ mxPushUndefined();
1471
+ mxPush(mxObjectPrototype);
1472
+ #ifdef mxLink
1473
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
1474
+ #else
1475
+ slot = fxLastProperty(the, fxNewGlobalInstance(the));
1476
+ #endif
1477
+ for (id = XS_SYMBOL_ID_COUNT; id < _Infinity; id++)
1478
+ slot = fxNextSlotProperty(the, slot, &the->stackPrototypes[-1 - id], mxID(id), XS_DONT_ENUM_FLAG);
1479
+ for (; id < _Compartment; id++)
1480
+ slot = fxNextSlotProperty(the, slot, &the->stackPrototypes[-1 - id], mxID(id), XS_GET_ONLY);
1481
+ for (; id < XS_INTRINSICS_COUNT; id++)
1482
+ slot = fxNextSlotProperty(the, slot, &the->stackPrototypes[-1 - id], mxID(id), XS_DONT_ENUM_FLAG);
1483
+ slot = fxNextSlotProperty(the, slot, the->stack, mxID(_global), XS_DONT_ENUM_FLAG);
1484
+ slot = fxNextSlotProperty(the, slot, the->stack, mxID(_globalThis), XS_DONT_ENUM_FLAG);
1485
+ mxGlobal.value = the->stack->value;
1486
+ mxGlobal.kind = the->stack->kind;
1487
+ fxNewInstance(the);
1488
+ fxNewInstance(the);
1489
+ mxPushUndefined();
1490
+ fxNewEnvironmentInstance(the, C_NULL);
1491
+ mxPushUndefined();
1492
+ mxPushUndefined();
1493
+ mxPushUndefined();
1494
+ mxPushUndefined();
1495
+ mxPushUndefined();
1496
+ mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm = fxNewRealmInstance(the);
1497
+ mxPop();
1498
+
1499
+ the->collectFlag = XS_COLLECTING_FLAG;
1500
+
1501
+ /*{
1502
+ int c = 32;
1503
+ while (--c)
1504
+ fxCollectGarbage(the);
1505
+ }*/
1506
+
1507
+ #ifdef mxDebug
1508
+ fxLogin(the);
1509
+ #endif
1510
+
1511
+ the->firstJump = C_NULL;
1512
+ }
1513
+ else {
1514
+ fxFree(the);
1515
+ c_free(the);
1516
+ the = NULL;
1517
+
1518
+ if (gxDefaults.terminateSharedCluster)
1519
+ gxDefaults.terminateSharedCluster();
1520
+ }
1521
+ }
1522
+ return the;
1523
+ }
1524
+
1525
+ void fxDeleteMachine(txMachine* the)
1526
+ {
1527
+ txSlot* aSlot;
1528
+ #ifndef mxLink
1529
+ txSlot* bSlot;
1530
+ txSlot* cSlot;
1531
+ #endif
1532
+
1533
+ if (!(the->shared)) {
1534
+ #ifdef mxFrequency
1535
+ fxReportFrequency(the);
1536
+ #endif
1537
+ #ifdef mxDebug
1538
+ fxLogout(the);
1539
+ #endif
1540
+ }
1541
+ the->context = C_NULL;
1542
+ aSlot = the->cRoot;
1543
+ while (aSlot) {
1544
+ aSlot->flag |= XS_MARK_FLAG;
1545
+ aSlot = aSlot->next;
1546
+ }
1547
+ #ifndef mxLink
1548
+ aSlot = the->firstHeap;
1549
+ while (aSlot) {
1550
+ bSlot = aSlot + 1;
1551
+ cSlot = aSlot->value.reference;
1552
+ while (bSlot < cSlot) {
1553
+ if ((bSlot->kind == XS_HOST_KIND) && (bSlot->value.host.variant.destructor)) {
1554
+ if (bSlot->flag & XS_HOST_HOOKS_FLAG) {
1555
+ if (bSlot->value.host.variant.hooks->destructor)
1556
+ (*(bSlot->value.host.variant.hooks->destructor))(bSlot->value.host.data);
1557
+ }
1558
+ else
1559
+ (*(bSlot->value.host.variant.destructor))(bSlot->value.host.data);
1560
+ }
1561
+ bSlot++;
1562
+ }
1563
+ aSlot = aSlot->next;
1564
+ }
1565
+ #endif
1566
+ fxDelete_dtoa(the->dtoa);
1567
+ fxDeleteMachinePlatform(the);
1568
+ fxFree(the);
1569
+ c_free(the);
1570
+
1571
+ if (gxDefaults.terminateSharedCluster)
1572
+ gxDefaults.terminateSharedCluster();
1573
+ }
1574
+
1575
+ txMachine* fxCloneMachine(txCreation* theCreation, txMachine* theMachine, txString theName, void* theContext)
1576
+ {
1577
+ txMachine* the = (txMachine *)c_calloc(sizeof(txMachine), 1);
1578
+ if (the) {
1579
+ txJump aJump;
1580
+
1581
+ aJump.nextJump = C_NULL;
1582
+ aJump.stack = C_NULL;
1583
+ aJump.scope = C_NULL;
1584
+ aJump.frame = C_NULL;
1585
+ aJump.code = C_NULL;
1586
+ aJump.flag = 0;
1587
+ the->firstJump = &aJump;
1588
+ if (c_setjmp(aJump.buffer) == 0) {
1589
+ txSlot* sharedSlot;
1590
+ txSlot* slot;
1591
+
1592
+ if (gxDefaults.initializeSharedCluster)
1593
+ gxDefaults.initializeSharedCluster();
1594
+
1595
+ the->dtoa = fxNew_dtoa(the);
1596
+ the->preparation = theMachine->preparation;
1597
+ the->context = theContext;
1598
+ the->archive = theMachine->archive;
1599
+ the->sharedMachine = theMachine;
1600
+ fxCreateMachinePlatform(the);
1601
+
1602
+ #ifdef mxDebug
1603
+ the->name = theName;
1604
+ #endif
1605
+ the->profileID = theMachine->profileID;
1606
+ fxAllocate(the, theCreation);
1607
+
1608
+ c_memcpy(the->nameTable, theMachine->nameTable, the->nameModulo * sizeof(txSlot *));
1609
+ c_memcpy(the->symbolTable, theMachine->symbolTable, the->symbolModulo * sizeof(txSlot *));
1610
+ the->colors = theMachine->colors;
1611
+ the->keyCount = theMachine->keyIndex + (txID)theCreation->initialKeyCount;
1612
+ the->keyIndex = theMachine->keyIndex;
1613
+ the->keyOffset = the->keyIndex;
1614
+ the->keyArrayHost = theMachine->keyArray;
1615
+ fxBuildArchiveKeys(the);
1616
+
1617
+ the->aliasCount = theMachine->aliasCount;
1618
+ if (the->aliasCount) {
1619
+ the->aliasArray = (txSlot **)c_malloc_uint32(the->aliasCount * sizeof(txSlot*));
1620
+ if (!the->aliasArray)
1621
+ fxAbort(the, XS_NOT_ENOUGH_MEMORY_EXIT);
1622
+ c_memset(the->aliasArray, 0, the->aliasCount * sizeof(txSlot*));
1623
+ }
1624
+
1625
+ /* mxGlobal */
1626
+ mxPushUndefined();
1627
+ /* mxException */
1628
+ mxPushUndefined();
1629
+ /* mxProgram */
1630
+ mxPushNull();
1631
+ fxNewProgramInstance(the);
1632
+ /* mxHosts */
1633
+ mxPushUndefined();
1634
+ /* mxModuleQueue */
1635
+ fxNewInstance(the);
1636
+ /* mxUnhandledPromises */
1637
+ fxNewInstance(the);
1638
+ /* mxDuringJobs */
1639
+ fxNewInstance(the);
1640
+ /* mxFinalizationRegistries */
1641
+ fxNewInstance(the);
1642
+ /* mxPendingJobs */
1643
+ fxNewInstance(the);
1644
+ /* mxRunningJobs */
1645
+ fxNewInstance(the);
1646
+ /* mxBreakpoints */
1647
+ mxPushList();
1648
+ /* mxHostInspectors */
1649
+ mxPushList();
1650
+ /* mxInstanceInspectors */
1651
+ mxPushList();
1652
+
1653
+ the->stackPrototypes = theMachine->stackTop;
1654
+
1655
+ mxPushUndefined();
1656
+ mxPush(theMachine->stackTop[-1 - mxGlobalStackIndex]);
1657
+ slot = fxLastProperty(the, fxNewObjectInstance(the));
1658
+ slot = fxNextSlotProperty(the, slot, the->stack, mxID(_global), XS_DONT_ENUM_FLAG);
1659
+ slot = fxNextSlotProperty(the, slot, the->stack, mxID(_globalThis), XS_DONT_ENUM_FLAG);
1660
+ mxGlobal.value = the->stack->value;
1661
+ mxGlobal.kind = the->stack->kind;
1662
+ if (the->archive) {
1663
+ fxNewHostObject(the, C_NULL);
1664
+ the->stack->value.reference->next->value.host.data = the->archive;
1665
+ slot = fxNextSlotProperty(the, slot, the->stack, fxID(the, "archive"), XS_DONT_ENUM_FLAG);
1666
+ mxPop();
1667
+ }
1668
+
1669
+ fxNewInstance(the);
1670
+ mxPush(theMachine->stackTop[-1 - mxProgramStackIndex]); //@@
1671
+ fxNewHostInstance(the);
1672
+
1673
+ mxPushUndefined();
1674
+ slot = fxLastProperty(the, fxNewEnvironmentInstance(the, C_NULL));
1675
+ sharedSlot = theMachine->stackTop[-1 - mxExceptionStackIndex].value.reference->next->next; //@@
1676
+ while (sharedSlot) {
1677
+ slot = slot->next = fxDuplicateSlot(the, sharedSlot);
1678
+ sharedSlot = sharedSlot->next;
1679
+ }
1680
+
1681
+
1682
+ mxPushUndefined();
1683
+ mxPushUndefined();
1684
+ mxPushUndefined();
1685
+ mxPushUndefined();
1686
+ mxPushUndefined();
1687
+ mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm = fxNewRealmInstance(the);
1688
+ mxPop();
1689
+
1690
+ the->collectFlag = XS_COLLECTING_FLAG;
1691
+
1692
+ #ifdef mxDebug
1693
+ fxLogin(the);
1694
+ #endif
1695
+
1696
+ the->firstJump = C_NULL;
1697
+
1698
+ }
1699
+ else {
1700
+ fxFree(the);
1701
+ c_free(the);
1702
+ the = NULL;
1703
+ }
1704
+ }
1705
+ return the;
1706
+ }
1707
+
1708
+ txMachine* fxPrepareMachine(txCreation* creation, txPreparation* preparation, txString name, void* context, void* archive)
1709
+ {
1710
+ txMachine _root;
1711
+ txMachine* root = &_root;
1712
+ if ((preparation->version[0] != XS_MAJOR_VERSION) || (preparation->version[1] != XS_MINOR_VERSION))
1713
+ return C_NULL;
1714
+ c_memset(root, 0, sizeof(txMachine));
1715
+ root->preparation = preparation;
1716
+ root->archive = archive;
1717
+ root->keyArray = preparation->keys;
1718
+ root->colors = preparation->colors;
1719
+ root->keyCount = (txID)preparation->keyCount + (txID)preparation->creation.initialKeyCount;
1720
+ root->keyIndex = (txID)preparation->keyCount;
1721
+ root->nameModulo = preparation->nameModulo;
1722
+ root->nameTable = preparation->names;
1723
+ root->symbolModulo = preparation->symbolModulo;
1724
+ root->symbolTable = preparation->symbols;
1725
+
1726
+ root->stack = &preparation->stack[0];
1727
+ root->stackBottom = &preparation->stack[0];
1728
+ root->stackTop = &preparation->stack[preparation->stackCount];
1729
+
1730
+ root->firstHeap = &preparation->heap[0];
1731
+ root->freeHeap = &preparation->heap[preparation->heapCount - 1];
1732
+ root->aliasCount = (txID)preparation->aliasCount;
1733
+
1734
+ root->profileID = (txID)preparation->profileID;
1735
+
1736
+ if (!creation)
1737
+ creation = &preparation->creation;
1738
+ return fxCloneMachine(creation, root, name, context);
1739
+ }
1740
+
1741
+ void fxShareMachine(txMachine* the)
1742
+ {
1743
+ if (!(the->shared)) {
1744
+ #ifdef mxDebug
1745
+ fxLogout(the);
1746
+ #endif
1747
+ {
1748
+ txSlot* realm = mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm;
1749
+ txSlot* modules = mxOwnModules(realm)->value.reference;
1750
+ txSlot* module = modules->next;
1751
+ while (module) {
1752
+ mxModuleInstanceInternal(module->value.reference)->value.module.realm = NULL;
1753
+ module = module->next;
1754
+ }
1755
+ mxModuleInstanceInternal(mxProgram.value.reference)->value.module.realm = NULL;
1756
+ mxException.kind = XS_REFERENCE_KIND;
1757
+ mxException.value.reference = mxRealmClosures(realm)->value.reference;
1758
+ mxProgram.value.reference = modules; //@@
1759
+
1760
+ {
1761
+ txSlot* target = fxNewInstance(the);
1762
+ txSlot* modules = mxOwnModules(realm)->value.reference;
1763
+ txSlot* module = modules->next;
1764
+ while (module) {
1765
+ target = target->next = fxNewSlot(the);
1766
+ target->value.symbol = mxModuleInstanceInternal(module->value.reference)->value.module.id;
1767
+ target->kind = XS_SYMBOL_KIND;
1768
+ target->ID = mxModuleInstanceInternal(module->value.reference)->value.module.id;
1769
+ module = module->next;
1770
+ }
1771
+ mxPull(mxHosts); //@@
1772
+ }
1773
+ mxModuleQueue = mxUndefined;
1774
+ mxDuringJobs = mxUndefined;
1775
+ mxFinalizationRegistries = mxUndefined;
1776
+ mxPendingJobs = mxUndefined;
1777
+ mxRunningJobs = mxUndefined;
1778
+ mxBreakpoints = mxUndefined;
1779
+ mxHostInspectors = mxUndefined;
1780
+ mxInstanceInspectors = mxUndefined;
1781
+ }
1782
+ fxCollectGarbage(the);
1783
+ fxShare(the);
1784
+ the->shared = 1;
1785
+ }
1786
+ }
1787
+
1788
+ /* Garbage Collector */
1789
+
1790
+ void fxCollectGarbage(txMachine* the)
1791
+ {
1792
+ fxCollect(the, XS_COMPACT_FLAG);
1793
+ }
1794
+
1795
+ void fxEnableGarbageCollection(txMachine* the, txBoolean enableIt)
1796
+ {
1797
+ if (enableIt)
1798
+ the->collectFlag |= XS_COLLECTING_FLAG;
1799
+ else
1800
+ the->collectFlag &= ~XS_COLLECTING_FLAG;
1801
+ }
1802
+
1803
+ void fxRemember(txMachine* the, txSlot* theSlot)
1804
+ {
1805
+ txSlot* aHeap;
1806
+ txSlot* aLimit;
1807
+ if ((the->stack <= theSlot) && (theSlot < the->stackTop)) {
1808
+ return;
1809
+ }
1810
+ aHeap = the->firstHeap;
1811
+ while (aHeap) {
1812
+ aLimit = aHeap->value.reference;
1813
+ if ((aHeap < theSlot) && (theSlot < aLimit)) {
1814
+ return;
1815
+ }
1816
+ aHeap = aHeap->next;
1817
+ }
1818
+ fxForget(the, theSlot);
1819
+ theSlot->next = the->cRoot;
1820
+ the->cRoot = theSlot;
1821
+ }
1822
+
1823
+ void fxForget(txMachine* the, txSlot* theSlot)
1824
+ {
1825
+ if (!(theSlot->flag & XS_MARK_FLAG)) {
1826
+ txSlot* aSlot = the->cRoot;
1827
+ txSlot** aSlotAddr = &(the->cRoot);
1828
+ while ((aSlot = *aSlotAddr)) {
1829
+ if (aSlot == theSlot) {
1830
+ *aSlotAddr = aSlot->next;
1831
+ return;
1832
+ }
1833
+ aSlotAddr = &(aSlot->next);
1834
+ }
1835
+ }
1836
+ }
1837
+
1838
+ void fxAccess(txMachine* the, txSlot* theSlot)
1839
+ {
1840
+ if (theSlot)
1841
+ the->scratch = *theSlot;
1842
+ else
1843
+ the->scratch.kind = XS_UNDEFINED_KIND;
1844
+ the->scratch.next = NULL;
1845
+ the->scratch.flag = XS_NO_FLAG;
1846
+ the->scratch.ID = XS_NO_ID;
1847
+ }
1848
+
1849
+ /* Host */
1850
+
1851
+ txMachine* fxBeginHost(txMachine* the)
1852
+ {
1853
+ #if defined(mxInstrument) || defined(mxProfile)
1854
+ if (the->frame == C_NULL)
1855
+ fxCheckProfiler(the, C_NULL);
1856
+ #endif
1857
+ mxOverflow(-7);
1858
+ /* THIS */
1859
+ (--the->stack)->next = C_NULL;
1860
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1861
+ /* FUNCTION */
1862
+ (--the->stack)->next = C_NULL;
1863
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1864
+ /* TARGET */
1865
+ (--the->stack)->next = C_NULL;
1866
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1867
+ /* RESULT */
1868
+ (--the->stack)->next = C_NULL;
1869
+ mxInitSlotKind(the->stack, XS_UNDEFINED_KIND);
1870
+ /* FRAME */
1871
+ (--the->stack)->next = the->frame;
1872
+ the->stack->ID = XS_NO_ID;
1873
+ the->stack->flag = XS_C_FLAG;
1874
+ #ifdef mxDebug
1875
+ if (the->breakOnStartFlag) {
1876
+ the->breakOnStartFlag = 0;
1877
+ the->stack->flag |= XS_STEP_INTO_FLAG | XS_STEP_OVER_FLAG;
1878
+ }
1879
+ #endif
1880
+ the->stack->kind = XS_FRAME_KIND;
1881
+ the->stack->value.frame.code = the->code;
1882
+ the->stack->value.frame.scope = the->scope;
1883
+ the->frame = the->stack;
1884
+ /* COUNT */
1885
+ (--the->stack)->next = C_NULL;
1886
+ mxInitSlotKind(the->stack, XS_INTEGER_KIND);
1887
+ the->stack->value.integer = 0;
1888
+ /* VARC */
1889
+ (--the->stack)->next = C_NULL;
1890
+ the->stack->ID = XS_NO_ID;
1891
+ the->stack->flag = XS_NO_FLAG;
1892
+ the->stack->kind = XS_VAR_KIND;
1893
+ the->stack->value.environment.variable.count = 0;
1894
+ the->stack->value.environment.line = 0;
1895
+ the->scope = the->stack;
1896
+ the->code = C_NULL;
1897
+ return the;
1898
+ }
1899
+
1900
+ void fxEndHost(txMachine* the)
1901
+ {
1902
+ if (the->frame->next == C_NULL) {
1903
+ fxEndJob(the);
1904
+ }
1905
+ the->stack = the->frame + 5;
1906
+ the->scope = the->frame->value.frame.scope;
1907
+ the->code = the->frame->value.frame.code;
1908
+ the->frame = the->frame->next;
1909
+ }
1910
+
1911
+ void fxEndJob(txMachine* the)
1912
+ {
1913
+ if (gxDefaults.cleanupFinalizationRegistries)
1914
+ gxDefaults.cleanupFinalizationRegistries(the);
1915
+ if (mxDuringJobs.kind == XS_REFERENCE_KIND)
1916
+ mxDuringJobs.value.reference->next = C_NULL;
1917
+ fxCheckUnhandledRejections(the, 0);
1918
+ }
1919
+
1920
+ void fxExitToHost(txMachine* the)
1921
+ {
1922
+ txJump* jump = the->firstJump;
1923
+ while (jump->nextJump) {
1924
+ txJump* nextJump = jump->nextJump;
1925
+ if (jump->flag)
1926
+ c_free(jump);
1927
+ jump = nextJump;
1928
+ }
1929
+ c_longjmp(jump->buffer, 1);
1930
+ }
1931
+
1932
+ typedef struct {
1933
+ txMachine* machine;
1934
+ txU1* archive;
1935
+ txArchiveRead read;
1936
+ txArchiveWrite write;
1937
+ txU1* buffer;
1938
+ txU1* scratch;
1939
+ size_t offset;
1940
+ size_t size;
1941
+ size_t bufferCode;
1942
+ size_t bufferLoop;
1943
+ size_t bufferOffset;
1944
+ size_t bufferSize;
1945
+ size_t scratchSize;
1946
+ txID* ids;
1947
+ txID* map;
1948
+ txID* maps;
1949
+ c_jmp_buf jmp_buf;
1950
+ txBoolean dirty;
1951
+ } txMapper;
1952
+
1953
+ static void fxMapperMapID(txMapper* self);
1954
+ static void fxMapperMapIDs(txMapper* self);
1955
+ static txU1 fxMapperRead1(txMapper* self);
1956
+ static txU2 fxMapperRead2(txMapper* self);
1957
+ static txU4 fxMapperRead4(txMapper* self);
1958
+ static void fxMapperReadAtom(txMapper* self, Atom* atom);
1959
+ static void fxMapperSkip(txMapper* self, size_t size);
1960
+ static void fxMapperStep(txMapper* self);
1961
+
1962
+ #define mxMapAtom(POINTER) \
1963
+ atom.atomSize = c_read32be(POINTER); \
1964
+ POINTER += 4; \
1965
+ atom.atomType = c_read32be(POINTER); \
1966
+ POINTER += 4
1967
+
1968
+
1969
+ #define mxElseStatus(_ASSERTION,_STATUS) \
1970
+ ((void)((_ASSERTION) || ((self->buffer[8] = (_STATUS)), c_longjmp(self->jmp_buf, 1), 0)))
1971
+ #define mxElseFatalCheck(_ASSERTION) mxElseStatus(_ASSERTION, XS_FATAL_CHECK_EXIT)
1972
+ #define mxElseNoMoreKeys(_ASSERTION) mxElseStatus(_ASSERTION, XS_NO_MORE_KEYS_EXIT)
1973
+ #define mxElseNotEnoughMemory(_ASSERTION) mxElseStatus(_ASSERTION, XS_NOT_ENOUGH_MEMORY_EXIT)
1974
+ #define mxElseInstall(_ASSERTION) if (!(_ASSERTION)) goto install
1975
+
1976
+ #define mxArchiveHeaderSize (sizeof(Atom) + sizeof(Atom) + XS_VERSION_SIZE + sizeof(Atom) + XS_DIGEST_SIZE)
1977
+
1978
+ void fxBuildArchiveKeys(txMachine* the)
1979
+ {
1980
+ txPreparation* preparation = the->preparation;
1981
+ if (preparation) {
1982
+ txU1* p = the->archive;
1983
+ if (p) {
1984
+ txU4 atomSize;
1985
+ txID c, i;
1986
+ p += mxArchiveHeaderSize;
1987
+ // NAME
1988
+ atomSize = c_read32be(p);
1989
+ p += atomSize;
1990
+ // SYMB
1991
+ p += sizeof(Atom);
1992
+ c = (txID)c_read16(p);
1993
+ p += 2;
1994
+ p += mxStringLength((txString)p) + 1;
1995
+ for (i = 1; i < c; i++) {
1996
+ fxNewNameX(the, (txString)p);
1997
+ p += mxStringLength((txString)p) + 1;
1998
+ }
1999
+ }
2000
+ }
2001
+ }
2002
+
2003
+ static txU1 *fxGetArchiveModules(txMachine *the, void* archive, txU4 *size)
2004
+ {
2005
+ txPreparation* preparation = the->preparation;
2006
+ txU1* p = archive;
2007
+ if (!preparation || !p) {
2008
+ *size = 0;
2009
+ return NULL;
2010
+ }
2011
+ p += mxArchiveHeaderSize;
2012
+ // NAME
2013
+ p += c_read32be(p);
2014
+ // SYMB
2015
+ p += c_read32be(p);
2016
+ // IDEN
2017
+ p += c_read32be(p);
2018
+ // MAPS
2019
+ p += c_read32be(p);
2020
+ // MODS
2021
+ *size = c_read32be(p) - sizeof(Atom);
2022
+ return p + sizeof(Atom);
2023
+ }
2024
+
2025
+ void* fxGetArchiveCode(txMachine* the, void* archive, txString path, size_t* size)
2026
+ {
2027
+ txU4 atomSize;
2028
+ txU1 *p = fxGetArchiveModules(the, archive, &atomSize), *q;
2029
+ if (!p)
2030
+ return NULL;
2031
+ q = p + atomSize;
2032
+ while (p < q) {
2033
+ // PATH
2034
+ atomSize = c_read32be(p);
2035
+ if (!c_strcmp(path, (txString)(p + sizeof(Atom)))) {
2036
+ p += atomSize;
2037
+ atomSize = c_read32be(p);
2038
+ *size = atomSize - sizeof(Atom);
2039
+ return p + sizeof(Atom);
2040
+ }
2041
+ p += atomSize;
2042
+ // CODE
2043
+ atomSize = c_read32be(p);
2044
+ p += atomSize;
2045
+ }
2046
+ return C_NULL;
2047
+ }
2048
+
2049
+ txInteger fxGetArchiveCodeCount(txMachine* the, void* archive)
2050
+ {
2051
+ txInteger count = 0;
2052
+ txU4 size;
2053
+ txU1 *p = fxGetArchiveModules(the, archive, &size);
2054
+ if (p) {
2055
+ txU1 *q = p + size;
2056
+ while (p < q) {
2057
+ // PATH
2058
+ p += c_read32be(p);
2059
+ // CODE
2060
+ p += c_read32be(p);
2061
+ count += 1;
2062
+ }
2063
+ }
2064
+ return count;
2065
+ }
2066
+
2067
+ void* fxGetArchiveCodeName(txMachine* the, void* archive, txInteger index)
2068
+ {
2069
+ txU4 atomSize;
2070
+ txU1 *p = fxGetArchiveModules(the, archive, &atomSize), *q;
2071
+ if (!p)
2072
+ return NULL;
2073
+ q = p + atomSize;
2074
+ while (p < q) {
2075
+ // PATH
2076
+ if (!index--)
2077
+ return (txString)(p + sizeof(Atom));
2078
+ p += c_read32be(p);
2079
+ // CODE
2080
+ p += c_read32be(p);
2081
+ }
2082
+ return C_NULL;
2083
+ }
2084
+
2085
+ static txU1 *fxGetArchiveResources(txMachine *the, void* archive, txU4 *size)
2086
+ {
2087
+ txPreparation* preparation = the->preparation;
2088
+ txU1* p = archive;
2089
+ if (!preparation || !p) {
2090
+ *size = 0;
2091
+ return NULL;
2092
+ }
2093
+ p += mxArchiveHeaderSize;
2094
+ // NAME
2095
+ p += c_read32be(p);
2096
+ // SYMB
2097
+ p += c_read32be(p);
2098
+ // IDEN
2099
+ p += c_read32be(p);
2100
+ // MAPS
2101
+ p += c_read32be(p);
2102
+ // MODS
2103
+ p += c_read32be(p);
2104
+ // RSRC
2105
+ *size = c_read32be(p) - sizeof(Atom);
2106
+ return p + sizeof(Atom);
2107
+ }
2108
+
2109
+ void* fxGetArchiveData(txMachine* the, void* archive, txString path, size_t* size)
2110
+ {
2111
+ txU4 atomSize;
2112
+ txU1 *p = fxGetArchiveResources(the, archive, &atomSize), *q;
2113
+ if (!p)
2114
+ return NULL;
2115
+ q = p + atomSize;
2116
+ while (p < q) {
2117
+ // PATH
2118
+ atomSize = c_read32be(p);
2119
+ if (!c_strcmp(path, (txString)(p + sizeof(Atom)))) {
2120
+ p += atomSize;
2121
+ atomSize = c_read32be(p);
2122
+ *size = atomSize - sizeof(Atom);
2123
+ return p + sizeof(Atom);
2124
+ }
2125
+ p += atomSize;
2126
+ // DATA
2127
+ atomSize = c_read32be(p);
2128
+ p += atomSize;
2129
+ }
2130
+ return C_NULL;
2131
+ }
2132
+
2133
+ txInteger fxGetArchiveDataCount(txMachine* the, void* archive)
2134
+ {
2135
+ txInteger count = 0;
2136
+ txU4 size;
2137
+ txU1 *p = fxGetArchiveResources(the, archive, &size);
2138
+ if (p) {
2139
+ txU1 *q = p + size;
2140
+ while (p < q) {
2141
+ // PATH
2142
+ p += c_read32be(p);
2143
+ // DATA
2144
+ p += c_read32be(p);
2145
+ count += 1;
2146
+ }
2147
+ }
2148
+ return count;
2149
+ }
2150
+
2151
+ void* fxGetArchiveDataName(txMachine* the, void* archive, txInteger index)
2152
+ {
2153
+ txU4 atomSize;
2154
+ txU1 *p = fxGetArchiveResources(the, archive, &atomSize), *q;
2155
+ if (!p)
2156
+ return NULL;
2157
+ q = p + atomSize;
2158
+ while (p < q) {
2159
+ // PATH
2160
+ if (!index--)
2161
+ return (txString)(p + sizeof(Atom));
2162
+ p += c_read32be(p);
2163
+ // DATA
2164
+ p += c_read32be(p);
2165
+ }
2166
+ return C_NULL;
2167
+ }
2168
+
2169
+ void* fxGetArchiveName(txMachine* the, void* archive)
2170
+ {
2171
+ txU1* p = archive;
2172
+ if (!p)
2173
+ return NULL;
2174
+ p += mxArchiveHeaderSize;
2175
+ // NAME
2176
+ return p + sizeof(Atom);
2177
+ }
2178
+
2179
+ void* fxMapArchive(txMachine* the, txPreparation* preparation, void* archive, size_t bufferSize, txArchiveRead read, txArchiveWrite write)
2180
+ {
2181
+ txMapper mapper;
2182
+ txMapper* self = &mapper;
2183
+ Atom atom;
2184
+ txU1* p;
2185
+ txU1* q;
2186
+ txID id;
2187
+ txID c, i;
2188
+ txFlag clean;
2189
+
2190
+ c_memset(self, 0, sizeof(txMapper));
2191
+ if (c_setjmp(self->jmp_buf) == 0) {
2192
+ self->machine = the;
2193
+ self->archive = archive;
2194
+ self->read = read;
2195
+ self->write = write;
2196
+
2197
+ self->scratchSize = 1024;
2198
+ self->scratch = c_malloc(self->scratchSize + bufferSize);
2199
+ mxElseNotEnoughMemory(self->scratch != C_NULL);
2200
+ self->bufferSize = bufferSize;
2201
+ self->buffer = self->scratch + self->scratchSize;
2202
+
2203
+ mxElseFatalCheck(self->read(self->archive, 0, self->buffer, mxArchiveHeaderSize));
2204
+
2205
+ p = self->buffer;
2206
+ mxMapAtom(p);
2207
+ if (atom.atomType != XS_ATOM_ARCHIVE) {
2208
+ self->archive = NULL;
2209
+ goto bail;
2210
+ }
2211
+ self->size = atom.atomSize;
2212
+ mxMapAtom(p);
2213
+ mxElseFatalCheck(atom.atomType == XS_ATOM_VERSION);
2214
+ mxElseFatalCheck(atom.atomSize == sizeof(Atom) + 4);
2215
+ mxElseFatalCheck(*p++ == XS_MAJOR_VERSION);
2216
+ mxElseFatalCheck(*p++ == XS_MINOR_VERSION);
2217
+ p++;
2218
+ p++;
2219
+ mxMapAtom(p);
2220
+ mxElseFatalCheck(atom.atomType == XS_ATOM_SIGNATURE);
2221
+ mxElseFatalCheck(atom.atomSize == sizeof(Atom) + XS_DIGEST_SIZE);
2222
+ p += XS_DIGEST_SIZE;
2223
+
2224
+ self->bufferOffset = mxArchiveHeaderSize;
2225
+ if (self->bufferSize > self->size)
2226
+ self->bufferSize = self->size;
2227
+ mxElseFatalCheck(self->read(self->archive, mxArchiveHeaderSize, p, self->bufferSize - mxArchiveHeaderSize));
2228
+
2229
+ fxMapperReadAtom(self, &atom);
2230
+ mxElseFatalCheck(atom.atomType == XS_ATOM_NAME);
2231
+ fxMapperSkip(self, atom.atomSize - sizeof(Atom));
2232
+
2233
+ fxMapperReadAtom(self, &atom);
2234
+ mxElseFatalCheck(atom.atomType == XS_ATOM_SYMBOLS);
2235
+ c = fxMapperRead2(self);
2236
+ self->ids = c_malloc(c * sizeof(txID));
2237
+ mxElseFatalCheck(self->ids != C_NULL);
2238
+ id = (txID)preparation->keyCount;
2239
+ for (i = 0; i < c; i++) {
2240
+ txU1 byte;
2241
+ txU4 sum = 0;
2242
+ txU4 modulo = 0;
2243
+ txSlot* result;
2244
+ p = self->scratch;
2245
+ q = p + self->scratchSize;
2246
+ while ((byte = fxMapperRead1(self))) {
2247
+ mxElseFatalCheck(p < q);
2248
+ *p++ = byte;
2249
+ sum = (sum << 1) + byte;
2250
+ }
2251
+ mxElseFatalCheck(p < q);
2252
+ *p = 0;
2253
+ if (i == 0)
2254
+ self->ids[i] = XS_NO_ID;
2255
+ else if (the)
2256
+ self->ids[i] = fxID(the, (txString)self->scratch);
2257
+ else {
2258
+ sum &= 0x7FFFFFFF;
2259
+ modulo = sum % preparation->nameModulo;
2260
+ result = preparation->names[modulo];
2261
+ while (result != C_NULL) {
2262
+ if (result->value.key.sum == sum)
2263
+ if (c_strcmp(result->value.key.string, (txString)self->scratch) == 0)
2264
+ break;
2265
+ result = result->next;
2266
+ }
2267
+ if (result)
2268
+ self->ids[i] = result->ID;
2269
+ else {
2270
+ self->ids[i] = id;
2271
+ id++;
2272
+ }
2273
+ }
2274
+ }
2275
+
2276
+ fxMapperReadAtom(self, &atom);
2277
+ mxElseFatalCheck(atom.atomType == XS_ATOM_IDENTIFIERS);
2278
+ self->bufferLoop = self->bufferOffset - sizeof(Atom) + atom.atomSize;
2279
+ i = 0;
2280
+ clean = 1;
2281
+ while (self->bufferOffset < self->bufferLoop) {
2282
+ txID id = self->ids[i];
2283
+ txU1 low = (txU1)(id & 0x00FF);
2284
+ txU1 high = (txU1)(id >> 8);
2285
+ if (self->bufferOffset == self->bufferSize)
2286
+ fxMapperStep(self);
2287
+ if (*(self->buffer + self->bufferOffset) != low) {
2288
+ *(self->buffer + self->bufferOffset) = low;
2289
+ self->dirty = 1;
2290
+ clean = 0;
2291
+ }
2292
+ self->bufferOffset++;
2293
+ if (self->bufferOffset == self->bufferSize)
2294
+ fxMapperStep(self);
2295
+ if (*(self->buffer + self->bufferOffset) != high) {
2296
+ *(self->buffer + self->bufferOffset) = high;
2297
+ self->dirty = 1;
2298
+ clean = 0;
2299
+ }
2300
+ self->bufferOffset++;
2301
+ i++;
2302
+ }
2303
+ if (clean)
2304
+ goto bail;
2305
+
2306
+ fxMapperReadAtom(self, &atom);
2307
+ mxElseFatalCheck(atom.atomType == XS_ATOM_MAPS);
2308
+ self->bufferLoop = self->bufferOffset - sizeof(Atom) + atom.atomSize;
2309
+ self->maps = self->map = c_malloc((self->bufferLoop - self->bufferOffset));
2310
+ mxElseFatalCheck(self->maps != C_NULL);
2311
+ while (self->bufferOffset < self->bufferLoop)
2312
+ *self->map++ = fxMapperRead2(self);
2313
+ self->map = self->maps;
2314
+
2315
+ fxMapperReadAtom(self, &atom);
2316
+ mxElseFatalCheck(atom.atomType == XS_ATOM_MODULES);
2317
+ self->bufferLoop = self->bufferOffset - sizeof(Atom) + atom.atomSize;
2318
+ while (self->bufferOffset < self->bufferLoop) {
2319
+ id += 2;
2320
+ fxMapperReadAtom(self, &atom);
2321
+ mxElseFatalCheck(atom.atomType == XS_ATOM_PATH);
2322
+ fxMapperSkip(self, atom.atomSize - sizeof(Atom));
2323
+ fxMapperReadAtom(self, &atom);
2324
+ mxElseFatalCheck(atom.atomType == XS_ATOM_CODE);
2325
+ self->bufferCode = self->bufferOffset - sizeof(Atom) + atom.atomSize;
2326
+ fxMapperMapIDs(self);
2327
+ }
2328
+
2329
+ if (preparation->creation.incrementalKeyCount == 0)
2330
+ mxElseNoMoreKeys((id - (txID)preparation->keyCount) < (txID)preparation->creation.initialKeyCount);
2331
+
2332
+ fxMapperReadAtom(self, &atom);
2333
+ mxElseFatalCheck(atom.atomType == XS_ATOM_RESOURCES);
2334
+ self->bufferLoop = self->bufferOffset - sizeof(Atom) + atom.atomSize;
2335
+ while (self->bufferOffset < self->bufferLoop) {
2336
+ fxMapperReadAtom(self, &atom);
2337
+ mxElseFatalCheck(atom.atomType == XS_ATOM_PATH);
2338
+ fxMapperSkip(self, atom.atomSize - sizeof(Atom));
2339
+ fxMapperReadAtom(self, &atom);
2340
+ mxElseFatalCheck(atom.atomType == XS_ATOM_DATA);
2341
+ fxMapperSkip(self, atom.atomSize - sizeof(Atom));
2342
+ }
2343
+
2344
+ if (self->bufferOffset) {
2345
+ if (self->dirty) {
2346
+ mxElseFatalCheck(self->write(self->archive, self->offset, self->buffer, self->bufferOffset));
2347
+ self->dirty = 0;
2348
+ }
2349
+ }
2350
+ }
2351
+ else {
2352
+ self->buffer[0] = 0;
2353
+ self->buffer[1] = 0;
2354
+ self->buffer[2] = 0;
2355
+ self->buffer[3] = 9;
2356
+ self->buffer[4] = 'X';
2357
+ self->buffer[5] = 'S';
2358
+ self->buffer[6] = '_';
2359
+ self->buffer[7] = 'E';
2360
+ self->write(self->archive, 0, self->buffer, 9);
2361
+ self->archive = C_NULL;
2362
+ }
2363
+ bail:
2364
+ if (self->ids)
2365
+ c_free(self->ids);
2366
+ if (self->maps)
2367
+ c_free(self->maps);
2368
+ if (self->scratch)
2369
+ c_free(self->scratch);
2370
+ return self->archive;
2371
+ }
2372
+
2373
+ void fxMapperMapID(txMapper* self)
2374
+ {
2375
+ txID id = self->ids[*(self->map++)];
2376
+ if (self->bufferOffset == self->bufferSize)
2377
+ fxMapperStep(self);
2378
+ *(self->buffer + self->bufferOffset) = (txU1)(id & 0x00FF);
2379
+ self->bufferOffset++;
2380
+ self->dirty = 1;
2381
+ if (self->bufferOffset == self->bufferSize)
2382
+ fxMapperStep(self);
2383
+ *(self->buffer + self->bufferOffset) = (txU1)(id >> 8);
2384
+ self->bufferOffset++;
2385
+ self->dirty = 1;
2386
+ }
2387
+
2388
+ void fxMapperMapIDs(txMapper* self)
2389
+ {
2390
+ register const txS1* bytes = gxCodeSizes;
2391
+ txS1 offset;
2392
+ txU4 index;
2393
+ while (self->bufferOffset < self->bufferCode) {
2394
+ //fprintf(stderr, "%s", gxCodeNames[*((txU1*)p)]);
2395
+ offset = (txS1)c_read8(bytes + fxMapperRead1(self));
2396
+ if (0 < offset)
2397
+ fxMapperSkip(self, offset - 1);
2398
+ else if (0 == offset)
2399
+ fxMapperMapID(self);
2400
+ else if (-1 == offset) {
2401
+ index = fxMapperRead1(self);
2402
+ fxMapperSkip(self, index);
2403
+ }
2404
+ else if (-2 == offset) {
2405
+ index = fxMapperRead2(self);
2406
+ fxMapperSkip(self, index);
2407
+ }
2408
+ //fprintf(stderr, "\n");
2409
+ }
2410
+ }
2411
+
2412
+ txU1 fxMapperRead1(txMapper* self)
2413
+ {
2414
+ txU1 result;
2415
+ if (self->bufferOffset == self->bufferSize)
2416
+ fxMapperStep(self);
2417
+ result = *(self->buffer + self->bufferOffset);
2418
+ self->bufferOffset++;
2419
+ return result;
2420
+ }
2421
+
2422
+ txU2 fxMapperRead2(txMapper* self)
2423
+ {
2424
+ txU2 result;
2425
+ result = fxMapperRead1(self);
2426
+ result |= fxMapperRead1(self) << 8;
2427
+ return result;
2428
+ }
2429
+
2430
+ txU4 fxMapperRead4(txMapper* self)
2431
+ {
2432
+ txU4 result;
2433
+ result = fxMapperRead1(self) << 24;
2434
+ result |= fxMapperRead1(self) << 16;
2435
+ result |= fxMapperRead1(self) << 8;
2436
+ result |= fxMapperRead1(self);
2437
+ return result;
2438
+ }
2439
+
2440
+ void fxMapperReadAtom(txMapper* self, Atom* atom)
2441
+ {
2442
+ atom->atomSize = fxMapperRead4(self);
2443
+ atom->atomType = fxMapperRead4(self);
2444
+ }
2445
+
2446
+ void fxMapperSkip(txMapper* self, size_t size)
2447
+ {
2448
+ size_t offset = self->bufferOffset + size;
2449
+ while ((offset >= self->bufferSize) && (self->bufferSize > 0)) {
2450
+ offset -= self->bufferSize;
2451
+ fxMapperStep(self);
2452
+ }
2453
+ self->bufferOffset = offset;
2454
+ }
2455
+
2456
+ void fxMapperStep(txMapper* self)
2457
+ {
2458
+ if (self->dirty) {
2459
+ mxElseFatalCheck(self->write(self->archive, self->offset, self->buffer, self->bufferSize));
2460
+ self->dirty = 0;
2461
+ }
2462
+ self->offset += self->bufferSize;
2463
+ self->size -= self->bufferSize;
2464
+ self->bufferCode -= self->bufferSize;
2465
+ self->bufferLoop -= self->bufferSize;
2466
+ if (self->bufferSize > self->size)
2467
+ self->bufferSize = self->size;
2468
+ if (self->bufferSize > 0)
2469
+ mxElseFatalCheck(self->read(self->archive, self->offset, self->buffer, self->bufferSize));
2470
+ self->bufferOffset = 0;
2471
+ }
2472
+
2473
+ txBoolean fxIsProfiling(txMachine* the)
2474
+ {
2475
+ #if defined(mxInstrument) || defined(mxProfile)
2476
+ return (the->profiler) ? 1 : 0;
2477
+ #else
2478
+ return 0;
2479
+ #endif
2480
+ }
2481
+
2482
+ void fxStartProfiling(txMachine* the)
2483
+ {
2484
+ #if defined(mxInstrument) || defined(mxProfile)
2485
+ if (the->profiler)
2486
+ return;
2487
+ // if (the->frame)
2488
+ // fxAbort(the, XS_FATAL_CHECK_EXIT);
2489
+ fxCreateProfiler(the);
2490
+ #endif
2491
+ }
2492
+
2493
+ void fxStopProfiling(txMachine* the, void* stream)
2494
+ {
2495
+ #if defined(mxInstrument) || defined(mxProfile)
2496
+ if (!the->profiler)
2497
+ return;
2498
+ // if (the->frame)
2499
+ // fxAbort(the, XS_FATAL_CHECK_EXIT);
2500
+ fxDeleteProfiler(the, stream);
2501
+ #endif
2502
+ }
2503
+
2504
+ #ifdef mxFrequency
2505
+
2506
+ typedef struct {
2507
+ txNumber exit;
2508
+ txNumber frequency;
2509
+ txU1 code;
2510
+ } txFrequency;
2511
+
2512
+ static int fxCompareExit(const void* a, const void* b)
2513
+ {
2514
+ return ((txFrequency*)b)->exit - ((txFrequency*)a)->exit;
2515
+ }
2516
+
2517
+ static int fxCompareFrequency(const void* a, const void* b)
2518
+ {
2519
+ return ((txFrequency*)b)->frequency - ((txFrequency*)a)->frequency;
2520
+ }
2521
+
2522
+ void fxReportFrequency(txMachine* the)
2523
+ {
2524
+ txFrequency frequencies[XS_CODE_COUNT];
2525
+ txU1 code;
2526
+ txNumber exitSum = 0;
2527
+ txNumber frequencySum = 0;
2528
+ for (code = 0; code < XS_CODE_COUNT; code++) {
2529
+ frequencies[code].exit = the->exits[code];
2530
+ frequencies[code].frequency = the->frequencies[code];
2531
+ frequencies[code].code = code;
2532
+ exitSum += the->exits[code];
2533
+ frequencySum += the->frequencies[code];
2534
+ }
2535
+ c_qsort(frequencies, XS_CODE_COUNT, sizeof(txFrequency), fxCompareFrequency);
2536
+ fprintf(stderr, "Frequencies %10.0lf\n", frequencySum);
2537
+ for (code = 0; code < XS_CODE_COUNT; code++) {
2538
+ if (!frequencies[code].frequency)
2539
+ break;
2540
+ fprintf(stderr, "%24s %10.3lf%%\n",
2541
+ gxCodeNames[frequencies[code].code],
2542
+ ((double)(frequencies[code].frequency) * 100.0) / frequencySum);
2543
+ }
2544
+ c_qsort(frequencies, XS_CODE_COUNT, sizeof(txFrequency), fxCompareExit);
2545
+ fprintf(stderr, "Exits %10.0lf\n", exitSum);
2546
+ for (code = 0; code < XS_CODE_COUNT; code++) {
2547
+ if (!frequencies[code].exit)
2548
+ break;
2549
+ fprintf(stderr, "%24s%10.3lf%%\n",
2550
+ gxCodeNames[frequencies[code].code],
2551
+ ((double)(frequencies[code].exit) * 100.0) / exitSum);
2552
+ }
2553
+ }
2554
+ #endif
2555
+