Coverage Report

Created: 2025-06-24 07:03

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