Coverage Report

Created: 2026-08-31 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsMarshall.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2025  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
#if mx32bitID
41
#define mxSymbolBit 0x80000000
42
#define mxSymbolMask 0x7FFFFFFF
43
#else
44
#define mxSymbolBit 0x8000
45
#define mxSymbolMask 0x7FFF
46
#endif
47
48
typedef struct sxMarshallBuffer txMarshallBuffer; 
49
struct sxMarshallBuffer {
50
  txByte* base;
51
  txByte* current;
52
  txSlot* link;
53
  txID* symbolMap;
54
  txSize size;
55
  txID symbolCount;
56
  txSize symbolSize;
57
  txSlot* stack;
58
  c_jmp_buf jmp_buf;
59
  char error[128];
60
};
61
62
static void fxDemarshallChunk(txMachine* the, void* theData, void** theDataAddress);
63
static txID fxDemarshallKey(txMachine* the, txID id, txID* theSymbolMap, txBoolean alien);
64
static void fxDemarshallReference(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txID* theSymbolMap, txBoolean alien);
65
static void fxDemarshallSlot(txMachine* the, txSlot* theSlot, txSlot* theResult, txID* theSymbolMap, txBoolean alien);
66
static void fxMarshallChunk(txMachine* the, void* theData, void** theDataAddress, txMarshallBuffer* theBuffer);
67
static txBoolean fxMarshallKey(txMachine* the, txSlot* slot, txMarshallBuffer* theBuffer, txBoolean alien);
68
static void fxMarshallReference(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txMarshallBuffer* theBuffer, txBoolean alien);
69
static txBoolean fxMarshallSlot(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txMarshallBuffer* theBuffer, txBoolean alien);
70
static void fxMeasureChunk(txMachine* the, void* theData, txMarshallBuffer* theBuffer);
71
static txBoolean fxMeasureKey(txMachine* the, txID theID, txMarshallBuffer* theBuffer, txBoolean alien);
72
static void fxMeasureReference(txMachine* the, txSlot* theSlot, txMarshallBuffer* theBuffer, txBoolean alien);
73
static void fxMeasureSlot(txMachine* the, txSlot* theSlot, txMarshallBuffer* theBuffer, txBoolean alien);
74
static void fxMeasureThrow(txMachine* the, txMarshallBuffer* theBuffer, txString message);
75
76
#define mxMarshallAlign(POINTER,SIZE) \
77
0
  if (((SIZE) &= ((sizeof(txNumber) - 1)))) (POINTER) += sizeof(txNumber) - (SIZE)
78
79
void fxDemarshall(txMachine* the, void* theData, txBoolean alien)
80
0
{
81
0
  txByte* p;
82
0
  txByte* q;
83
0
  txID aSymbolCount;
84
0
  txID aSymbolLength;
85
0
  txID* aSymbolMap;
86
0
  txID* aSymbolPointer;
87
0
  txSlot* aSlot;
88
0
  txChunk* aChunk;
89
0
  txIndex aLength;
90
  
91
0
  if (!theData) {
92
0
    the->stack->kind = XS_UNDEFINED_KIND;
93
0
    return;
94
0
  }
95
0
  p = (txByte*)theData;
96
0
  q = p + *((txSize*)(p));
97
0
  {
98
0
    mxTry(the) {
99
0
      p += sizeof(txSize);
100
0
      aSymbolCount = *((txID*)p);
101
0
      p += sizeof(txID);
102
0
      aSymbolMap = aSymbolPointer = (txID*)p;
103
0
      p += aSymbolCount * sizeof(txID);
104
0
      while (aSymbolCount) {
105
0
        txID id;
106
0
        aSymbolLength = *aSymbolPointer;
107
0
        mxPushStringC((char *)p);
108
0
        id = fxNewName(the, the->stack);
109
0
        mxPop();
110
0
        *aSymbolPointer++ = id;
111
0
        aSymbolCount--;
112
0
        p += aSymbolLength;
113
0
      }
114
0
      aLength = mxPtrDiff(p - (txByte*)theData);
115
0
      mxMarshallAlign(p, aLength);
116
0
      mxPushUndefined();
117
0
      fxDemarshallSlot(the, (txSlot*)p, the->stack, aSymbolMap, alien);
118
0
    }
119
0
    mxCatch(the) {
120
0
      the->stack->kind = XS_UNDEFINED_KIND;
121
0
      break;
122
0
    }
123
0
    while (p < q) {
124
0
      aSlot = (txSlot*)p;
125
0
      p += sizeof(txSlot);
126
0
      switch (aSlot->kind) {
127
0
      case XS_STRING_KIND:
128
0
      case XS_BIGINT_KIND:
129
0
        aChunk = (txChunk*)p;
130
0
        p += aChunk->size;
131
0
        mxMarshallAlign(p, aChunk->size);
132
0
        break;
133
0
      case XS_ARRAY_BUFFER_KIND:
134
0
        if (aSlot->value.arrayBuffer.address) {
135
0
          aChunk = (txChunk*)p;
136
0
          p += aChunk->size;
137
0
          mxMarshallAlign(p, aChunk->size);
138
0
        }
139
0
        break;
140
0
      case XS_REGEXP_KIND:
141
0
        if (aSlot->value.regexp.code) {
142
0
          aChunk = (txChunk*)p;
143
0
          p += aChunk->size;
144
0
          mxMarshallAlign(p, aChunk->size);
145
0
        }
146
0
        if (aSlot->value.regexp.data) {
147
0
          aChunk = (txChunk*)p;
148
0
          p += aChunk->size;
149
0
          mxMarshallAlign(p, aChunk->size);
150
0
        }
151
0
        break;
152
0
      case XS_KEY_KIND:
153
0
        if (aSlot->value.key.string) {
154
0
          aChunk = (txChunk*)p;
155
0
          p += aChunk->size;
156
0
          mxMarshallAlign(p, aChunk->size);
157
0
        }
158
0
        mxFallThrough;
159
0
      case XS_INSTANCE_KIND:
160
0
        aSlot->value.instance.garbage = C_NULL;
161
0
        break;
162
0
      }
163
0
    }
164
0
  }
165
0
}
166
167
void fxDemarshallChunk(txMachine* the, void* theData, void** theDataAddress)
168
0
{
169
0
  txSize aSize = ((txChunk*)(((txByte*)theData) - sizeof(txChunk)))->size - sizeof(txChunk);
170
0
  txByte* aResult = (txByte *)fxNewChunk(the, aSize);
171
0
  c_memcpy(aResult, theData, aSize);
172
0
  *theDataAddress = aResult;
173
0
}
174
175
txID fxDemarshallKey(txMachine* the, txID id, txID* theSymbolMap, txBoolean alien)
176
0
{
177
0
  if (id != XS_NO_ID) {
178
0
    if (alien)
179
0
      id = theSymbolMap[id - 1];
180
0
    else if (id >= the->keyOffset)
181
0
      id = theSymbolMap[id - the->keyOffset];
182
0
  }
183
0
  return id;
184
0
}
185
186
void fxDemarshallReference(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txID* theSymbolMap, txBoolean alien)
187
0
{
188
0
  if (!alien && (theSlot->flag & XS_DONT_MARSHALL_FLAG))
189
0
    *theSlotAddress = theSlot;
190
0
  else if (theSlot->value.instance.garbage)
191
0
    *theSlotAddress = theSlot->value.instance.garbage;
192
0
  else {
193
0
    mxCheckCStack();
194
0
    *theSlotAddress = fxNewSlot(the);
195
0
    fxDemarshallSlot(the, theSlot, *theSlotAddress, theSymbolMap, alien);
196
0
  }
197
0
}
198
199
void fxDemarshallSlot(txMachine* the, txSlot* theSlot, txSlot* theResult, txID* theSymbolMap, txBoolean alien)
200
0
{
201
0
  txSlot* aSlot;
202
0
  txIndex index, offset;
203
0
  txSlot* aResult;
204
0
  txSlot** aSlotAddress;
205
206
0
  if (!(theSlot->flag & XS_INTERNAL_FLAG))
207
0
    theResult->ID = fxDemarshallKey(the, theSlot->ID, theSymbolMap, alien);
208
0
  else
209
0
    theResult->ID = theSlot->ID;
210
0
  theResult->flag = theSlot->flag;
211
0
  switch (theSlot->kind) {
212
0
  case XS_UNDEFINED_KIND:
213
0
  case XS_NULL_KIND:
214
0
  case XS_BOOLEAN_KIND:
215
0
  case XS_INTEGER_KIND:
216
0
  case XS_NUMBER_KIND:
217
0
  case XS_DATE_KIND:
218
0
  case XS_STRING_X_KIND:
219
0
  case XS_BIGINT_X_KIND:
220
0
  case XS_DATA_VIEW_KIND:
221
0
  case XS_KEY_X_KIND:
222
0
  case XS_BUFFER_INFO_KIND:
223
0
    theResult->value = theSlot->value;
224
0
    theResult->kind = theSlot->kind;
225
0
    break;
226
    
227
0
  case XS_STRING_KIND:
228
0
    fxDemarshallChunk(the, theSlot->value.string, (void **)&theResult->value.string);
229
0
    theResult->kind = theSlot->kind;
230
0
    break;
231
0
  case XS_BIGINT_KIND:
232
0
    fxDemarshallChunk(the, theSlot->value.bigint.data, (void **)&theResult->value.bigint.data);
233
0
    theResult->value.bigint.size = theSlot->value.bigint.size;
234
0
    theResult->value.bigint.sign = theSlot->value.bigint.sign;
235
0
    theResult->kind = theSlot->kind;
236
0
    break;
237
0
  case XS_ARRAY_BUFFER_KIND: 
238
0
    if (theSlot->value.arrayBuffer.address)
239
0
      fxDemarshallChunk(the, theSlot->value.arrayBuffer.address, (void **)&(theResult->value.arrayBuffer.address));
240
0
    else
241
0
      theResult->value.arrayBuffer.address = C_NULL;
242
0
    theResult->kind = theSlot->kind;
243
0
    break;
244
0
  case XS_REGEXP_KIND:
245
0
    theResult->value.regexp.code = C_NULL;
246
0
    theResult->value.regexp.data = C_NULL;
247
0
    theResult->kind = theSlot->kind;
248
0
    if (theSlot->value.regexp.code)
249
0
      fxDemarshallChunk(the, theSlot->value.regexp.code, (void**)&(theResult->value.regexp.code));
250
0
    if (theSlot->value.regexp.data)
251
0
      fxDemarshallChunk(the, theSlot->value.regexp.data, (void**)&(theResult->value.regexp.data));
252
0
    break;  
253
0
  case XS_KEY_KIND:
254
0
    if (theSlot->value.key.string)
255
0
      fxDemarshallChunk(the, theSlot->value.key.string, (void **)&theResult->value.key.string);
256
0
    else
257
0
      theResult->value.key.string = C_NULL;
258
0
    theResult->value.key.sum = theSlot->value.key.sum;
259
0
    theResult->kind = theSlot->kind;
260
0
    break;
261
    
262
0
  case XS_SYMBOL_KIND:
263
0
    theResult->value.symbol = fxDemarshallKey(the, theSlot->value.symbol, theSymbolMap, alien);
264
0
    theResult->kind = theSlot->kind;
265
0
    break;
266
    
267
0
  case XS_HOST_KIND:
268
0
    theResult->value.host.data = fxRetainSharedChunk(theSlot->value.host.data);
269
0
    theResult->value.host.variant.destructor = fxReleaseSharedChunk;
270
0
    theResult->kind = theSlot->kind;
271
0
    break;
272
0
  case XS_MAP_KIND:
273
0
  case XS_SET_KIND:
274
0
        theResult->value.table.length = theSlot->value.table.length;
275
0
    aSlotAddress = (txSlot**)fxNewChunk(the, theResult->value.table.length * sizeof(txSlot*));
276
0
    c_memset(aSlotAddress, 0, theResult->value.table.length * sizeof(txSlot*));
277
0
    theResult->value.table.address = aSlotAddress;
278
0
    theResult->kind = theSlot->kind;
279
0
    break;  
280
0
  case XS_TYPED_ARRAY_KIND:
281
0
    theResult->value.typedArray.dispatch = (txTypeDispatch*)&gxTypeDispatches[theSlot->value.integer];
282
0
    theResult->value.typedArray.atomics = (txTypeAtomics*)&gxTypeAtomics[theSlot->value.integer];
283
0
    theResult->kind = theSlot->kind;
284
0
    break;
285
    
286
0
  case XS_REFERENCE_KIND:
287
0
    theResult->value.error.info = C_NULL;
288
0
    theResult->kind = XS_ERROR_KIND;
289
0
    fxDemarshallReference(the, theSlot->value.reference, &(theResult->value.error.info), theSymbolMap, alien);
290
0
    theResult->value.reference = theResult->value.error.info;
291
0
    theResult->kind = XS_REFERENCE_KIND;
292
0
    break;
293
0
  case XS_INSTANCE_KIND:
294
0
    theSlot->value.instance.garbage = theResult;
295
0
    theResult->value.instance.garbage = C_NULL;
296
0
    theResult->kind = theSlot->kind;
297
0
    aSlot = theSlot->next;
298
0
    if (!alien && theSlot->value.instance.prototype) {
299
0
          theResult->value.instance.prototype = theSlot->value.instance.prototype;
300
0
    }
301
0
    else {
302
0
          theResult->value.instance.prototype = mxObjectPrototype.value.reference;
303
0
      if (aSlot) {
304
0
        if (aSlot->flag & XS_INTERNAL_FLAG) {
305
0
          if (aSlot->ID == XS_ARRAY_BEHAVIOR)
306
0
            theResult->value.instance.prototype = mxArrayPrototype.value.reference;
307
0
          else {
308
0
            switch (aSlot->kind) {
309
0
            case XS_ARRAY_BUFFER_KIND: theResult->value.instance.prototype = mxArrayBufferPrototype.value.reference; break;
310
0
            case XS_BOOLEAN_KIND: theResult->value.instance.prototype = mxBooleanPrototype.value.reference; break;
311
0
            case XS_DATA_VIEW_KIND: theResult->value.instance.prototype = mxDataViewPrototype.value.reference; break;
312
0
            case XS_DATE_KIND: theResult->value.instance.prototype = mxDatePrototype.value.reference; break;
313
0
            case XS_ERROR_KIND: theResult->value.instance.prototype = mxErrorPrototypes(aSlot->value.error.which).value.reference; break;
314
0
            case XS_HOST_KIND: theResult->value.instance.prototype = mxSharedArrayBufferPrototype.value.reference; break;
315
0
            case XS_MAP_KIND: theResult->value.instance.prototype = mxMapPrototype.value.reference; break;
316
0
            case XS_NUMBER_KIND: theResult->value.instance.prototype = mxNumberPrototype.value.reference; break;
317
0
            case XS_REGEXP_KIND: theResult->value.instance.prototype = mxRegExpPrototype.value.reference; break;
318
0
            case XS_SET_KIND: theResult->value.instance.prototype = mxSetPrototype.value.reference; break;
319
0
            case XS_STRING_KIND: theResult->value.instance.prototype = mxStringPrototype.value.reference; break;
320
0
            case XS_TYPED_ARRAY_KIND: {
321
0
              txTypeDispatch* dispatch = (txTypeDispatch*)&gxTypeDispatches[aSlot->value.integer];
322
0
              mxPush(the->stackIntrinsics[-1 - (txInteger)dispatch->constructorID]);
323
0
              mxGetID(mxID(_prototype));
324
0
              theResult->value.instance.prototype = the->stack->value.reference;
325
0
              mxPop();
326
0
              } break;
327
0
            }
328
0
          }
329
0
        }
330
0
      }
331
0
    }
332
0
    aSlotAddress = &(theResult->next);
333
0
    while (aSlot) {
334
0
      *aSlotAddress = fxNewSlot(the);
335
0
      fxDemarshallSlot(the, aSlot, *aSlotAddress, theSymbolMap, alien);
336
0
      aSlot = aSlot->next;
337
0
      aSlotAddress = &((*aSlotAddress)->next);
338
0
    }
339
0
    aSlot = theResult->next;
340
0
    if (aSlot) {
341
0
      if (aSlot->kind == XS_MAP_KIND) {
342
0
        txSlot* key = aSlot->next->value.list.first;
343
0
        while (key) {
344
0
          txSlot* value = key->next;
345
0
          txU4 sum = fxSumEntry(the, key);
346
0
          txU4 modulo = sum % aSlot->value.table.length;
347
0
          txSlot* entry = fxNewSlot(the);
348
0
          txSlot** address = &(aSlot->value.table.address[modulo]);
349
0
          entry->next = *address;
350
0
          entry->kind = XS_ENTRY_KIND;
351
0
          entry->value.entry.slot = key;
352
0
          entry->value.entry.sum = sum;
353
0
          *address = entry;
354
0
          key = value->next;
355
0
        }
356
0
      }
357
0
      else if (aSlot->kind == XS_SET_KIND) {
358
0
        txSlot* key = aSlot->next->value.list.first;
359
0
        while (key) {
360
0
          txU4 sum = fxSumEntry(the, key);
361
0
          txU4 modulo = sum % aSlot->value.table.length;
362
0
          txSlot* entry = fxNewSlot(the);
363
0
          txSlot** address = &(aSlot->value.table.address[modulo]);
364
0
          entry->next = *address;
365
0
          entry->kind = XS_ENTRY_KIND;
366
0
          entry->value.entry.slot = key;
367
0
          entry->value.entry.sum = sum;
368
0
          *address = entry;
369
0
          key = key->next;
370
0
        }
371
0
      }
372
0
    }
373
0
    break;  
374
0
  case XS_ARRAY_KIND:
375
0
    theResult->value.array.length = 0;
376
0
    theResult->value.array.address = C_NULL;
377
0
    theResult->kind = theSlot->kind;
378
0
    if ((index = theSlot->value.array.length)) {
379
0
      theResult->value.array.address = (txSlot *)fxNewChunk(the, index * sizeof(txSlot));
380
0
      c_memset(theResult->value.array.address, 0, index * sizeof(txSlot));
381
0
      aSlot = theSlot->value.array.address;
382
0
      index = 0;
383
0
      offset = 0;
384
0
      while (aSlot) {
385
0
        if (aSlot->kind == XS_AT_KIND)
386
0
          index = aSlot->value.at.index;
387
0
        else {
388
0
          mxPushUndefined();
389
0
          fxDemarshallSlot(the, aSlot, the->stack, theSymbolMap, alien);
390
0
          aResult = theResult->value.array.address + offset;
391
0
          aResult->value = the->stack->value;
392
0
          aResult->kind = the->stack->kind;
393
0
          mxPop();
394
0
          *((txIndex*)aResult) = index;
395
0
          index++;
396
0
          offset++;
397
0
          theResult->value.array.length = index;
398
0
        }
399
0
        aSlot = aSlot->next;
400
0
      }
401
0
    }
402
0
    break;
403
0
  case XS_ERROR_KIND:
404
0
    theResult->value.error.info = C_NULL;
405
0
    theResult->value.error.which = theSlot->value.error.which;
406
0
    theResult->kind = theSlot->kind;
407
0
    if (theSlot->value.error.info)
408
0
      fxDemarshallReference(the, theSlot->value.error.info, &theResult->value.error.info, theSymbolMap, alien);
409
0
    break;
410
0
  case XS_PROXY_KIND:
411
0
    theResult->value.proxy.handler = C_NULL;
412
0
    theResult->value.proxy.target = C_NULL;
413
0
    theResult->kind = theSlot->kind;
414
0
    if (theSlot->value.proxy.handler)
415
0
      fxDemarshallReference(the, theSlot->value.proxy.handler, &theResult->value.proxy.handler, theSymbolMap, alien);
416
0
    if (theSlot->value.proxy.target)
417
0
      fxDemarshallReference(the, theSlot->value.proxy.target, &theResult->value.proxy.target, theSymbolMap, alien);
418
0
    break;  
419
420
0
  case XS_LIST_KIND:
421
0
    theResult->value.list.first = C_NULL;
422
0
    theResult->value.list.last = C_NULL;
423
0
    theResult->kind = theSlot->kind;
424
0
    aSlot = theSlot->value.list.first;
425
0
    aSlotAddress = &(theResult->value.list.first);
426
0
    while (aSlot) {
427
0
      theResult->value.list.last = *aSlotAddress = fxNewSlot(the);
428
0
      fxDemarshallSlot(the, aSlot, *aSlotAddress, theSymbolMap, alien);
429
0
      aSlot = aSlot->next;
430
0
      aSlotAddress = &((*aSlotAddress)->next);
431
0
    }
432
0
    break;  
433
0
  case XS_PRIVATE_KIND:
434
0
    theResult->value.private.check = theSlot->value.private.check;
435
0
    theResult->value.private.first = C_NULL;
436
0
    theResult->kind = theSlot->kind;
437
0
    aSlot = theSlot->value.private.first;
438
0
    aSlotAddress = &(theResult->value.private.first);
439
0
    while (aSlot) {
440
0
      *aSlotAddress = fxNewSlot(the);
441
0
      fxDemarshallSlot(the, aSlot, *aSlotAddress, theSymbolMap, alien);
442
0
      aSlot = aSlot->next;
443
0
      aSlotAddress = &((*aSlotAddress)->next);
444
0
    }
445
0
    break;  
446
0
  default:
447
0
    break;
448
0
  }
449
0
}
450
451
void* fxMarshall(txMachine* the, txBoolean alien)
452
0
{
453
0
  txMarshallBuffer aBuffer;
454
0
  txSlot* aSlot;
455
0
  txSlot* bSlot;
456
0
  txSlot* cSlot;
457
  
458
0
  c_memset(&aBuffer, 0, sizeof(aBuffer));
459
0
  if (c_setjmp(aBuffer.jmp_buf) == 0) {
460
0
    size_t mapSize = alien ? the->keyIndex : (the->keyIndex - the->keyOffset);
461
0
    aBuffer.symbolSize = sizeof(txSize) + sizeof(txID);
462
0
    aBuffer.symbolMap = c_calloc(mapSize, sizeof(txID));
463
0
    if (mapSize && !aBuffer.symbolMap)
464
0
      fxMeasureThrow(the,  &aBuffer, "out of memory");
465
0
        the->stack->ID = XS_NO_ID;
466
0
        aBuffer.stack = the->stack;
467
0
    fxMeasureSlot(the, the->stack, &aBuffer, alien);
468
    
469
0
    aBuffer.size += aBuffer.symbolSize;
470
0
    mxMarshallAlign(aBuffer.size, aBuffer.symbolSize);
471
0
    aBuffer.base = aBuffer.current = (txByte *)c_malloc(aBuffer.size);
472
0
    if (!aBuffer.base)
473
0
      fxMeasureThrow(the,  &aBuffer, "out of memory");
474
0
    *((txSize*)(aBuffer.current)) = aBuffer.size;
475
0
    aBuffer.current += sizeof(txSize);
476
0
    *((txID*)(aBuffer.current)) = aBuffer.symbolCount;
477
0
    aBuffer.current += sizeof(txID);
478
0
    if (aBuffer.symbolCount) {
479
0
      txID* lengths = (txID*)aBuffer.current;
480
0
      txID* map = aBuffer.symbolMap;
481
0
      txID dstIndex = 1;
482
0
      txSlot** p;
483
0
      txSlot** q;
484
0
      txSlot* key;
485
0
      aBuffer.current += aBuffer.symbolCount * sizeof(txID);
486
0
      if (alien) {
487
0
        p = the->keyArrayHost;
488
0
        q = p + the->keyOffset;
489
0
        while (p < q) {
490
0
          txID length = *map;
491
0
          if (length) {
492
0
            *map = dstIndex;
493
0
            key = *p;
494
0
            mxCheck(the, (key->kind == XS_KEY_KIND) || (key->kind  == XS_KEY_X_KIND));
495
0
            *lengths++ = length;
496
0
            c_memcpy(aBuffer.current, key->value.key.string, length);
497
0
            aBuffer.current += length;
498
0
            dstIndex++;
499
0
          }
500
0
          map++;
501
0
          p++;
502
0
        }
503
0
      }
504
0
      else 
505
0
        dstIndex = the->keyOffset;
506
0
      p = the->keyArray;
507
0
      q = p + the->keyIndex - the->keyOffset;
508
0
      while (p < q) {
509
0
        txID length = *map;
510
0
        if (length) {
511
0
          *map = dstIndex;
512
0
          key = *p;
513
0
          mxCheck(the, (key->kind == XS_KEY_KIND) || (key->kind  == XS_KEY_X_KIND));
514
0
          *lengths++ = length;
515
0
          c_memcpy(aBuffer.current, key->value.key.string, length);
516
0
          aBuffer.current += length;
517
0
          dstIndex++;
518
0
        }
519
0
        map++;
520
0
        p++;
521
0
      }
522
0
    }
523
0
    mxMarshallAlign(aBuffer.current, aBuffer.symbolSize);
524
    
525
0
    fxMarshallSlot(the, the->stack, &aSlot, &aBuffer, alien);
526
0
    aSlot = aBuffer.link;
527
0
    while (aSlot) {
528
0
      bSlot = aSlot->value.instance.garbage;
529
0
      aSlot->flag &= ~XS_MARK_FLAG;
530
0
      aSlot->value.instance.garbage = C_NULL;
531
0
      aSlot = bSlot;
532
0
    }
533
    
534
0
    mxCheck(the, aBuffer.current == aBuffer.base + aBuffer.size);
535
0
  }
536
0
  else {
537
0
    aSlot = the->firstHeap;
538
0
    while (aSlot) {
539
0
      bSlot = aSlot + 1;
540
0
      cSlot = aSlot->value.reference;
541
0
      while (bSlot < cSlot) {
542
0
        bSlot->flag &= ~XS_MARK_FLAG; 
543
0
        bSlot++;
544
0
      }
545
0
      aSlot = aSlot->next;
546
0
    }
547
0
    if (aBuffer.base)
548
0
      c_free(aBuffer.base);
549
0
    if (aBuffer.symbolMap)
550
0
      c_free(aBuffer.symbolMap);
551
0
    mxUnknownError(aBuffer.error);  
552
0
  }
553
0
  mxPop();
554
0
  c_free(aBuffer.symbolMap);
555
0
  return aBuffer.base;
556
0
}
557
558
void fxMarshallChunk(txMachine* the, void* theData, void** theDataAddress, txMarshallBuffer* theBuffer)
559
0
{
560
0
  txChunk* aChunk = ((txChunk*)(((txByte*)theData) - sizeof(txChunk)));
561
0
  txSize aSize = aChunk->size & 0x7FFFFFFF;
562
0
  txByte* aResult = theBuffer->current;
563
0
  theBuffer->current += aSize;
564
0
  c_memcpy(aResult, aChunk, aSize);
565
0
  aChunk = (txChunk*)aResult;
566
0
  aChunk->size &= 0x7FFFFFFF;
567
0
  *theDataAddress = aResult + sizeof(txChunk);
568
0
  mxMarshallAlign(theBuffer->current, aSize);
569
0
}
570
571
txBoolean fxMarshallKey(txMachine* the, txSlot* slot, txMarshallBuffer* theBuffer, txBoolean alien)
572
0
{
573
0
  txID id = slot->ID;
574
0
  txSlot* result = (txSlot*)(theBuffer->current);
575
0
  txSlot* key;
576
0
  if ((id == XS_NO_ID) || (slot->flag & XS_INTERNAL_FLAG)) {
577
0
    result->ID = id;
578
0
    return 1;
579
0
  }
580
0
  if (alien) {
581
0
    key = fxGetKey(the, id);
582
0
    if (key->flag & XS_DONT_ENUM_FLAG) {
583
0
      result->ID = theBuffer->symbolMap[id];
584
0
      return 1;
585
0
    }
586
0
  }
587
0
  else if (id >= the->keyOffset) {
588
0
    key = fxGetKey(the, id);
589
0
    if (key->flag & XS_DONT_ENUM_FLAG) {
590
0
      result->ID = theBuffer->symbolMap[id - the->keyOffset];
591
0
      return 1;
592
0
    }
593
0
  }
594
0
  else {
595
0
    result->ID = id;
596
0
    return 1;
597
0
  }
598
0
  return 0;
599
0
}
600
601
void fxMarshallReference(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txMarshallBuffer* theBuffer, txBoolean alien)
602
0
{
603
0
  if (!alien && (theSlot->flag & XS_DONT_MARSHALL_FLAG))
604
0
    *theSlotAddress = theSlot;
605
0
  else if (theSlot->value.instance.garbage)
606
0
    *theSlotAddress = theSlot->value.instance.garbage;
607
0
  else {
608
0
    mxCheckCStack();
609
0
    fxMarshallSlot(the, theSlot, theSlotAddress, theBuffer, alien);
610
0
  }
611
0
}
612
613
txBoolean fxMarshallSlot(txMachine* the, txSlot* theSlot, txSlot** theSlotAddress, txMarshallBuffer* theBuffer, txBoolean alien)
614
0
{
615
0
  txSlot* aResult;
616
0
  txSlot* aSlot;
617
0
  txSlot** aSlotAddress;
618
  
619
0
  if ((theSlot->kind == XS_PRIVATE_KIND) && (alien || ~(theSlot->value.private.check->flag & XS_DONT_MARSHALL_FLAG)))
620
0
    return 0;
621
0
  if (!fxMarshallKey(the, theSlot, theBuffer, alien))
622
0
    return 0;
623
0
  aResult = (txSlot*)(theBuffer->current);
624
0
  theBuffer->current += sizeof(txSlot);
625
0
  aResult->flag = theSlot->flag;
626
0
  aResult->kind = theSlot->kind;
627
0
  aResult->value = theSlot->value;
628
0
  *theSlotAddress = aResult;
629
0
  switch (theSlot->kind) {
630
0
  case XS_UNDEFINED_KIND:
631
0
  case XS_NULL_KIND:
632
0
  case XS_BOOLEAN_KIND:
633
0
  case XS_INTEGER_KIND:
634
0
  case XS_NUMBER_KIND:
635
0
  case XS_DATE_KIND:
636
0
  case XS_STRING_X_KIND:
637
0
  case XS_BIGINT_X_KIND:
638
0
  case XS_DATA_VIEW_KIND:
639
0
  case XS_KEY_X_KIND:
640
0
  case XS_BUFFER_INFO_KIND:
641
0
    break;
642
    
643
0
  case XS_STRING_KIND:
644
0
    fxMarshallChunk(the, theSlot->value.string, (void **)&(aResult->value.string), theBuffer);
645
0
    break;
646
0
  case XS_BIGINT_KIND:
647
0
    fxMarshallChunk(the, theSlot->value.bigint.data, (void **)&(aResult->value.bigint.data), theBuffer);
648
0
    break;
649
0
  case XS_ARRAY_BUFFER_KIND: 
650
0
    if (theSlot->value.arrayBuffer.address)
651
0
      fxMarshallChunk(the, theSlot->value.arrayBuffer.address, (void **) &(aResult->value.arrayBuffer.address), theBuffer);
652
0
    break;
653
0
  case XS_REGEXP_KIND:
654
0
    if (theSlot->value.regexp.code)
655
0
      fxMarshallChunk(the, theSlot->value.regexp.code, (void**)&(aResult->value.regexp.code), theBuffer);
656
0
    if (theSlot->value.regexp.data)
657
0
      fxMarshallChunk(the, theSlot->value.regexp.data, (void**)&(aResult->value.regexp.data), theBuffer);
658
0
    break;  
659
0
  case XS_KEY_KIND:
660
0
    if (theSlot->value.key.string)
661
0
      fxMarshallChunk(the, theSlot->value.key.string, (void **)&(aResult->value.key.string), theBuffer);
662
0
    break;
663
    
664
0
  case XS_SYMBOL_KIND:
665
0
    aResult->value.symbol = theSlot->value.symbol; //@@ only shared symbols remain
666
0
    break;
667
    
668
0
  case XS_HOST_KIND: 
669
0
    break;
670
0
  case XS_MAP_KIND:
671
0
  case XS_SET_KIND:
672
0
    aResult->value.table.address = C_NULL;
673
0
    break;  
674
0
  case XS_TYPED_ARRAY_KIND:
675
0
    aResult->value.integer = (txInteger)(theSlot->value.typedArray.dispatch - &gxTypeDispatches[0]);
676
0
    break;
677
    
678
0
  case XS_REFERENCE_KIND:
679
0
    fxMarshallReference(the, theSlot->value.reference, &aResult->value.reference,  theBuffer, alien);
680
0
    break;
681
0
  case XS_INSTANCE_KIND:
682
0
    aResult->value.instance.garbage = theBuffer->link;
683
0
    aResult->value.instance.prototype = C_NULL;
684
0
    aSlot = theSlot->value.instance.prototype;
685
0
    if (!alien && aSlot && (aSlot->flag & XS_DONT_MARSHALL_FLAG))
686
0
      aResult->value.instance.prototype = aSlot;
687
0
    theSlot->value.instance.garbage = aResult;
688
0
    theBuffer->link = theSlot;
689
0
    aSlotAddress = &(aResult->next);
690
0
    aSlot = theSlot->next;
691
0
    while (aSlot) {
692
0
      if (fxMarshallSlot(the, aSlot, aSlotAddress, theBuffer, alien))
693
0
        aSlotAddress = &((*aSlotAddress)->next);
694
0
      aSlot = aSlot->next;
695
0
    }
696
0
    *aSlotAddress = C_NULL;
697
0
    break;  
698
0
  case XS_ARRAY_KIND: {
699
0
    txIndex length = theSlot->value.array.length;
700
0
    txIndex size = fxGetIndexSize(the, theSlot);
701
0
    txSlot* slot = theSlot->value.array.address;
702
0
    txSlot* limit = slot + size;
703
0
    aResult->value.array.length = size;
704
0
    aSlotAddress = &(aResult->value.array.address);
705
0
    if (length == size) {
706
0
      while (slot < limit) {
707
0
        fxMarshallSlot(the, slot, aSlotAddress, theBuffer, alien);
708
0
        aSlotAddress = &((*aSlotAddress)->next);
709
0
        slot++;
710
0
      }
711
0
    }
712
0
    else {
713
0
      txSlot elision = { NULL, {.ID = XS_NO_ID, .flag = XS_NO_FLAG, .kind = XS_AT_KIND}, .value = { .at = { 0x0, XS_NO_ID } } };
714
0
      while (slot < limit) {
715
0
        txIndex index = *((txIndex*)slot);
716
0
        if (elision.value.at.index != index) {
717
0
          elision.value.at.index = index;
718
0
          fxMarshallSlot(the, &elision, aSlotAddress, theBuffer, alien);
719
0
          aSlotAddress = &((*aSlotAddress)->next);
720
0
        }
721
0
        fxMarshallSlot(the, slot, aSlotAddress, theBuffer, alien);
722
0
        aSlotAddress = &((*aSlotAddress)->next);
723
0
        elision.value.at.index = index + 1;
724
0
        slot++;
725
0
      }
726
0
    }
727
0
    *aSlotAddress = C_NULL;
728
0
    } break;
729
0
  case XS_ERROR_KIND:
730
0
    if (theSlot->value.error.info)
731
0
      fxMarshallReference(the, theSlot->value.error.info, &aResult->value.error.info, theBuffer, alien);
732
0
    break;  
733
0
  case XS_PROXY_KIND:
734
0
    if (theSlot->value.proxy.handler)
735
0
      fxMarshallReference(the, theSlot->value.proxy.handler, &aResult->value.proxy.handler, theBuffer, alien);
736
0
    if (theSlot->value.proxy.target)
737
0
      fxMarshallReference(the, theSlot->value.proxy.target, &aResult->value.proxy.target, theBuffer, alien);
738
0
    break;  
739
740
0
  case XS_LIST_KIND:
741
0
    aSlot = theSlot->value.list.first;
742
0
    aSlotAddress = &(aResult->value.list.first);
743
0
    while (aSlot) {
744
0
      fxMarshallSlot(the, aSlot, aSlotAddress, theBuffer, alien);
745
0
      aResult->value.list.last = *aSlotAddress;
746
0
      aSlot = aSlot->next;
747
0
      aSlotAddress = &((*aSlotAddress)->next);
748
0
    }
749
0
    *aSlotAddress = C_NULL;
750
0
    break;  
751
0
  case XS_PRIVATE_KIND:
752
0
    aSlot = theSlot->value.private.check;
753
0
    if (!alien && (aSlot->flag & XS_DONT_MARSHALL_FLAG)) {
754
0
      aSlot = theSlot->value.private.first;
755
0
      aSlotAddress = &(aResult->value.private.first);
756
0
      while (aSlot) {
757
0
        fxMarshallSlot(the, aSlot, aSlotAddress, theBuffer, alien);
758
0
        aSlot = aSlot->next;
759
0
        aSlotAddress = &((*aSlotAddress)->next);
760
0
      }
761
0
      *aSlotAddress = C_NULL;
762
0
    }
763
0
    else {
764
0
      theBuffer->current -= sizeof(txSlot);
765
0
      return 0;
766
0
    }
767
0
    break; 
768
0
  default:
769
0
    break;
770
0
  }
771
0
  return 1;
772
0
}
773
774
void fxMeasureChunk(txMachine* the, void* theData, txMarshallBuffer* theBuffer)
775
0
{
776
0
  txChunk* aChunk = ((txChunk*)(((txByte*)theData) - sizeof(txChunk)));
777
0
  txSize aSize = aChunk->size & 0x7FFFFFFF;
778
0
  theBuffer->size += aSize;
779
0
  if (theBuffer->size < 0)
780
0
    fxMeasureThrow(the, theBuffer, "too big");
781
0
  mxMarshallAlign(theBuffer->size, aSize);
782
0
}
783
784
txBoolean fxMeasureKey(txMachine* the, txID id, txMarshallBuffer* theBuffer, txBoolean alien)
785
0
{
786
0
  txSlot* key;
787
0
  txSize length;
788
0
  if (id == XS_NO_ID)
789
0
    return 1;
790
0
  if (alien) {
791
0
    if (theBuffer->symbolMap[id])
792
0
      return 1;
793
0
    key = fxGetKey(the, id);
794
0
    if (!(key->flag & XS_DONT_ENUM_FLAG))
795
0
      return 0;
796
0
  }
797
0
  else if (id >= the->keyOffset) {
798
0
    if (theBuffer->symbolMap[id - the->keyOffset])
799
0
      return 1;
800
0
    key = fxGetKey(the, id);
801
0
    if (!(key->flag & XS_DONT_ENUM_FLAG))
802
0
      return 0;
803
0
    id -= the->keyOffset;
804
0
  }
805
0
  else
806
0
    return 1;
807
0
  length = mxStringLength(key->value.key.string) + 1;  
808
0
  theBuffer->symbolMap[id] = (txID)length;
809
0
  theBuffer->symbolSize += sizeof(txID);
810
0
  theBuffer->symbolSize += length;
811
0
  theBuffer->symbolCount++;
812
0
  return 1;
813
0
}
814
815
void fxMeasureReference(txMachine* the, txSlot* theSlot, txMarshallBuffer* theBuffer, txBoolean alien)
816
0
{
817
0
  if (theSlot->flag & XS_DONT_MARSHALL_FLAG) {
818
0
    if (alien)
819
0
      if (theSlot->value.host.variant.destructor != fxReleaseSharedChunk)
820
0
        fxMeasureThrow(the, theBuffer, "read only object");
821
0
  }
822
0
  else if ((theSlot->flag & XS_MARK_FLAG) == 0) {
823
0
    mxCheckCStack();
824
0
    fxMeasureSlot(the, theSlot, theBuffer, alien);
825
0
  }
826
0
}
827
828
void fxMeasureSlot(txMachine* the, txSlot* theSlot, txMarshallBuffer* theBuffer, txBoolean alien)
829
0
{
830
0
  txSlot* aSlot;
831
832
0
  if (!(theSlot->flag & XS_INTERNAL_FLAG) && !fxMeasureKey(the, theSlot->ID, theBuffer, alien))
833
0
    return;
834
0
  theBuffer->size += sizeof(txSlot);
835
0
  if (theBuffer->size < 0)
836
0
    fxMeasureThrow(the, theBuffer, "too big");
837
0
  switch (theSlot->kind) {
838
0
  case XS_UNDEFINED_KIND:
839
0
  case XS_NULL_KIND:
840
0
  case XS_BOOLEAN_KIND:
841
0
  case XS_INTEGER_KIND:
842
0
  case XS_NUMBER_KIND:
843
0
  case XS_DATE_KIND:
844
0
  case XS_STRING_X_KIND:
845
0
  case XS_BIGINT_X_KIND:
846
0
  case XS_DATA_VIEW_KIND:
847
0
  case XS_KEY_X_KIND:
848
0
  case XS_BUFFER_INFO_KIND:
849
0
    break;
850
    
851
0
  case XS_STRING_KIND:
852
0
    fxMeasureChunk(the, theSlot->value.string, theBuffer);
853
0
    break;
854
0
  case XS_BIGINT_KIND:
855
0
    fxMeasureChunk(the, theSlot->value.bigint.data, theBuffer);
856
0
    break;
857
0
  case XS_ARRAY_BUFFER_KIND: 
858
0
    if (theSlot->value.arrayBuffer.address)
859
0
      fxMeasureChunk(the, theSlot->value.arrayBuffer.address, theBuffer);
860
0
    break;
861
0
  case XS_REGEXP_KIND:
862
0
    if (theSlot->value.regexp.code)
863
0
      fxMeasureChunk(the, theSlot->value.regexp.code, theBuffer);
864
0
    if (theSlot->value.regexp.data)
865
0
      fxMeasureChunk(the, theSlot->value.regexp.data, theBuffer);
866
0
    break;  
867
0
  case XS_KEY_KIND:
868
0
    if (theSlot->value.key.string)
869
0
      fxMeasureChunk(the, theSlot->value.string, theBuffer);
870
0
    break;
871
    
872
0
  case XS_SYMBOL_KIND:
873
0
    if (!fxMeasureKey(the, theSlot->value.symbol, theBuffer, alien))
874
0
      fxMeasureThrow(the, theBuffer, "symbol");
875
0
    break;
876
    
877
0
  case XS_HOST_KIND: 
878
0
    if (theSlot->value.host.variant.destructor != fxReleaseSharedChunk)
879
0
      fxMeasureThrow(the, theBuffer, "host object");
880
0
    break;
881
0
  case XS_MAP_KIND:
882
0
  case XS_SET_KIND:
883
0
    break; 
884
0
  case XS_TYPED_ARRAY_KIND:
885
0
    break;
886
    
887
0
  case XS_REFERENCE_KIND:
888
0
    fxMeasureReference(the, theSlot->value.reference, theBuffer, alien);
889
0
    break;
890
0
  case XS_INSTANCE_KIND:
891
0
    theSlot->flag |= XS_MARK_FLAG;
892
0
    theSlot->value.instance.garbage = C_NULL;
893
0
    aSlot = theSlot->next;
894
0
    while (aSlot) {
895
0
      mxPushAt(aSlot->ID, 0);
896
0
      fxMeasureSlot(the, aSlot, theBuffer, alien);
897
0
      mxPop();
898
0
      aSlot = aSlot->next;
899
0
    }
900
0
    break;  
901
0
  case XS_ARRAY_KIND: {
902
0
    txIndex length = theSlot->value.array.length;
903
0
    txIndex size = fxGetIndexSize(the, theSlot);
904
0
    txSlot* slot = theSlot->value.array.address;
905
0
    txSlot* limit = slot + size;
906
0
    if (length == size) {
907
0
      while (slot < limit) {
908
0
        mxPushAt(XS_NO_ID, *((txIndex*)slot));
909
0
        fxMeasureSlot(the, slot, theBuffer, alien);
910
0
        mxPop();
911
0
        slot++;
912
0
      }
913
0
    }
914
0
    else {
915
0
      txSlot elision = { NULL, {.ID = XS_NO_ID, .flag = XS_NO_FLAG, .kind = XS_AT_KIND}, .value = { .at = { 0x0, XS_NO_ID } } };
916
0
      while (slot < limit) {
917
0
        txIndex index = *((txIndex*)slot);
918
0
        if (elision.value.at.index != index) {
919
0
          elision.value.at.index = index;
920
0
          theBuffer->size += sizeof(txSlot);
921
0
          if (theBuffer->size < 0)
922
0
            fxMeasureThrow(the, theBuffer, "too big");
923
0
        }
924
0
        mxPushAt(XS_NO_ID, index);
925
0
        fxMeasureSlot(the, slot, theBuffer, alien);
926
0
        mxPop();
927
0
        elision.value.at.index = index + 1;
928
0
        slot++;
929
0
      }
930
0
    }
931
0
    } break;
932
0
  case XS_ERROR_KIND:
933
0
    if (theSlot->value.error.info)
934
0
      fxMeasureReference(the, theSlot->value.error.info, theBuffer, alien);
935
0
    break;
936
0
  case XS_PROXY_KIND:
937
0
    if (theSlot->value.proxy.handler)
938
0
      fxMeasureReference(the, theSlot->value.proxy.handler, theBuffer, alien);
939
0
    if (theSlot->value.proxy.target)
940
0
      fxMeasureReference(the, theSlot->value.proxy.target, theBuffer, alien);
941
0
    break;  
942
943
0
  case XS_LIST_KIND:
944
0
    aSlot = theSlot->value.list.first;
945
0
    while (aSlot) {
946
0
      fxMeasureSlot(the, aSlot, theBuffer, alien);
947
0
      aSlot = aSlot->next;
948
0
    }
949
0
    break;
950
0
  case XS_PRIVATE_KIND:
951
0
    aSlot = theSlot->value.private.check;
952
0
    if (!alien && (aSlot->flag & XS_DONT_MARSHALL_FLAG)) {
953
0
      aSlot = theSlot->value.private.first;
954
0
      while (aSlot) {
955
0
        mxPushAt(aSlot->ID, 0);
956
0
        fxMeasureSlot(the, aSlot, theBuffer, alien);
957
0
        mxPop();
958
0
        aSlot = aSlot->next;
959
0
      }
960
0
    }
961
0
    else
962
0
      theBuffer->size -= sizeof(txSlot);
963
0
    break;
964
    
965
0
  case XS_ARGUMENTS_SLOPPY_KIND:
966
0
  case XS_ARGUMENTS_STRICT_KIND:
967
0
    fxMeasureThrow(the, theBuffer, "arguments");
968
0
    break;
969
0
  case XS_CALLBACK_KIND:
970
0
  case XS_CALLBACK_X_KIND:
971
0
  case XS_CODE_KIND:
972
0
  case XS_CODE_X_KIND:
973
#if mxHostFunctionPrimitive
974
  case XS_HOST_FUNCTION_KIND:
975
#endif
976
0
    fxMeasureThrow(the, theBuffer, "function");
977
0
    break;
978
0
  case XS_FINALIZATION_CELL_KIND:
979
0
  case XS_FINALIZATION_REGISTRY_KIND:
980
0
    fxMeasureThrow(the, theBuffer, "finalization");
981
0
    break;
982
0
  case XS_MODULE_KIND:
983
0
  case XS_PROGRAM_KIND:
984
0
    fxMeasureThrow(the, theBuffer, "module");
985
0
    break;
986
0
  case XS_PROMISE_KIND:
987
0
    fxMeasureThrow(the, theBuffer, "promise");
988
0
    break;
989
0
  case XS_WEAK_MAP_KIND:
990
0
    fxMeasureThrow(the, theBuffer, "weak map");
991
0
    break;
992
0
  case XS_WEAK_REF_KIND:
993
0
    fxMeasureThrow(the, theBuffer, "weak ref");
994
0
    break;
995
0
  case XS_WEAK_SET_KIND:
996
0
    fxMeasureThrow(the, theBuffer, "weak set");
997
0
    break;
998
0
  case XS_ACCESSOR_KIND:
999
0
    fxMeasureThrow(the, theBuffer, "accessor");
1000
0
    break;
1001
0
  case XS_STACK_KIND:
1002
0
    fxMeasureThrow(the, theBuffer, "generator");
1003
0
    break;
1004
0
  default:
1005
0
    fxMeasureThrow(the, theBuffer, "no way");
1006
0
    break;
1007
0
  }
1008
0
}
1009
1010
void fxMeasureThrow(txMachine* the, txMarshallBuffer* theBuffer, txString message)
1011
0
{
1012
0
  txSlot* slot = theBuffer->stack;
1013
0
  txInteger i = 0;
1014
0
  txInteger c = sizeof(theBuffer->error);
1015
0
  i += c_snprintf(theBuffer->error, c, "marshall ");
1016
0
  while (slot > the->stack) {
1017
0
    slot--;
1018
0
    if (slot->kind == XS_AT_KIND) {
1019
0
      if (slot->value.at.id != XS_NO_ID) {
1020
0
        txBoolean adorn;
1021
0
        txString string = fxGetKeyString(the, slot->value.at.id, &adorn);
1022
0
        if (adorn) {
1023
0
          if (i < c) i += c_snprintf(theBuffer->error + i, c - i, "[%s]", string);
1024
0
        }
1025
0
        else {
1026
0
          if (i < c) i += c_snprintf(theBuffer->error + i, c - i, ".%s", string);
1027
0
        }
1028
0
      }
1029
0
      else {
1030
0
        if (i < c) i += c_snprintf(theBuffer->error + i, c - i, "[%d]", (int)slot->value.at.index);
1031
0
      }
1032
0
    }
1033
0
  }
1034
0
  if (i < c)
1035
0
    i += c_snprintf(theBuffer->error + i, c - i, ": %s", message);
1036
0
  c_longjmp(theBuffer->jmp_buf, 1);
1037
0
}
1038