Coverage Report

Created: 2025-12-24 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsArray.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
1.23M
#define mxArraySize(ARRAY) (((ARRAY)->value.array.address) ? (((txChunk*)(((txByte*)((ARRAY)->value.array.address)) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0)
41
42
static txIndex fxCheckArrayLength(txMachine* the, txSlot* slot);
43
static txBoolean fxCallThisItem(txMachine* the, txSlot* function, txIndex index, txSlot* item);
44
static txSlot* fxCheckArray(txMachine* the, txSlot* slot, txBoolean mutable);
45
static txSlot* fxCheckArrayItems(txMachine* the, txSlot* array, txIndex from, txIndex to);
46
static int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i);
47
static txSlot* fxCreateArray(txMachine* the, txFlag flag, txIndex length);
48
static txSlot* fxCreateArraySpecies(txMachine* the, txNumber length);
49
static void fxFindThisItem(txMachine* the, txSlot* function, txNumber index, txSlot* item);
50
static txNumber fxGetArrayLength(txMachine* the, txSlot* reference);
51
static txIndex fxGetArrayLimit(txMachine* the, txSlot* reference);
52
static void fxMoveThisItem(txMachine* the, txNumber from, txNumber to);
53
static void fxReduceThisItem(txMachine* the, txSlot* function, txIndex index);
54
static txBoolean fxSetArrayLength(txMachine* the, txSlot* array, txIndex target);
55
static void fx_Array_from_aux(txMachine* the, txSlot* function, txSlot* value, txIndex index);
56
static txIndex fx_Array_prototype_flatAux(txMachine* the, txSlot* source, txIndex length, txIndex start, txIndex depth, txSlot* function);
57
58
static txBoolean fxArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot, txFlag mask);
59
static txBoolean fxArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
60
static txBoolean fxArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* slot);
61
static txSlot* fxArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
62
static txBoolean fxArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index);
63
static void fxArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys);
64
static txSlot* fxArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag);
65
66
const txBehavior ICACHE_FLASH_ATTR gxArrayBehavior = {
67
  fxArrayGetProperty,
68
  fxArraySetProperty,
69
  fxOrdinaryCall,
70
  fxOrdinaryConstruct,
71
  fxArrayDefineOwnProperty,
72
  fxArrayDeleteProperty,
73
  fxArrayGetOwnProperty,
74
  fxOrdinaryGetPropertyValue,
75
  fxOrdinaryGetPrototype,
76
  fxArrayHasProperty,
77
  fxOrdinaryIsExtensible,
78
  fxArrayOwnKeys,
79
  fxOrdinaryPreventExtensions,
80
  fxOrdinarySetPropertyValue,
81
  fxOrdinarySetPrototype,
82
};
83
84
void fxBuildArray(txMachine* the)
85
27.5k
{
86
27.5k
  txSlot* instance;
87
27.5k
  txSlot* slot;
88
27.5k
  txSlot* property;
89
27.5k
  txSlot* unscopable;
90
  
91
27.5k
  mxPush(mxObjectPrototype);
92
27.5k
  instance = fxNewArrayInstance(the);
93
94
27.5k
  fxNewHostFunction(the, mxCallback(fxArrayLengthGetter), 0, mxID(_length), XS_NO_ID);
95
27.5k
  property = mxFunctionInstanceHome(the->stack->value.reference);
96
27.5k
  property->value.home.object = instance;
97
27.5k
  fxNewHostFunction(the, mxCallback(fxArrayLengthSetter), 1, mxID(_length), XS_NO_ID);
98
27.5k
  property = mxFunctionInstanceHome(the->stack->value.reference);
99
27.5k
  property->value.home.object = instance;
100
27.5k
  mxPushUndefined();
101
27.5k
  the->stack->flag = XS_DONT_DELETE_FLAG;
102
27.5k
  the->stack->kind = XS_ACCESSOR_KIND;
103
27.5k
  the->stack->value.accessor.getter = (the->stack + 2)->value.reference;
104
27.5k
  the->stack->value.accessor.setter = (the->stack + 1)->value.reference;
105
27.5k
  mxPull(mxArrayLengthAccessor);
106
27.5k
  mxPop();
107
27.5k
  mxPop();
108
109
27.5k
  slot = fxLastProperty(the, instance);
110
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_at), 1, mxID(_at), XS_DONT_ENUM_FLAG);
111
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_concat), 1, mxID(_concat), XS_DONT_ENUM_FLAG);
112
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_copyWithin), 2, mxID(_copyWithin), XS_DONT_ENUM_FLAG);
113
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_entries), 0, mxID(_entries), XS_DONT_ENUM_FLAG);
114
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_every), 1, mxID(_every), XS_DONT_ENUM_FLAG);
115
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_fill), 1, mxID(_fill), XS_DONT_ENUM_FLAG);
116
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_filter), 1, mxID(_filter), XS_DONT_ENUM_FLAG);
117
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_find), 1, mxID(_find), XS_DONT_ENUM_FLAG);
118
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findIndex), 1, mxID(_findIndex), XS_DONT_ENUM_FLAG);
119
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLast), 1, mxID(_findLast), XS_DONT_ENUM_FLAG);
120
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_findLastIndex), 1, mxID(_findLastIndex), XS_DONT_ENUM_FLAG);
121
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flat), 0, mxID(_flat), XS_DONT_ENUM_FLAG);
122
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_flatMap), 1, mxID(_flatMap), XS_DONT_ENUM_FLAG);
123
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_forEach), 1, mxID(_forEach), XS_DONT_ENUM_FLAG);
124
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_includes), 1, mxID(_includes), XS_DONT_ENUM_FLAG);
125
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_indexOf), 1, mxID(_indexOf), XS_DONT_ENUM_FLAG);
126
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_join), 1, mxID(_join), XS_DONT_ENUM_FLAG);
127
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_keys), 0, mxID(_keys), XS_DONT_ENUM_FLAG);
128
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_lastIndexOf), 1, mxID(_lastIndexOf), XS_DONT_ENUM_FLAG);
129
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_map), 1, mxID(_map), XS_DONT_ENUM_FLAG);
130
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_pop), 0, mxID(_pop), XS_DONT_ENUM_FLAG);
131
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_push), 1, mxID(_push), XS_DONT_ENUM_FLAG);
132
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduce), 1, mxID(_reduce), XS_DONT_ENUM_FLAG);
133
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reduceRight), 1, mxID(_reduceRight), XS_DONT_ENUM_FLAG);
134
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_reverse), 0, mxID(_reverse), XS_DONT_ENUM_FLAG);
135
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_shift), 0, mxID(_shift), XS_DONT_ENUM_FLAG);
136
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_slice), 2, mxID(_slice), XS_DONT_ENUM_FLAG);
137
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_some), 1, mxID(_some), XS_DONT_ENUM_FLAG);
138
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_sort), 1, mxID(_sort), XS_DONT_ENUM_FLAG);
139
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_splice), 2, mxID(_splice), XS_DONT_ENUM_FLAG);
140
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toLocaleString), 0, mxID(_toLocaleString), XS_DONT_ENUM_FLAG);
141
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG);
142
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_unshift), 1, mxID(_unshift), XS_DONT_ENUM_FLAG);
143
27.5k
  property = slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_values), 0, mxID(_values), XS_DONT_ENUM_FLAG);
144
27.5k
  mxPushSlot(property);
145
27.5k
  mxPull(mxArrayIteratorFunction);
146
27.5k
  slot = fxNextSlotProperty(the, slot, property, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG);
147
27.5k
  unscopable = fxLastProperty(the, fxNewInstance(the));
148
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_copyWithin), XS_NO_FLAG);
149
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_at), XS_NO_FLAG);
150
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_entries), XS_NO_FLAG);
151
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_fill), XS_NO_FLAG);
152
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_find), XS_NO_FLAG);
153
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findIndex), XS_NO_FLAG);
154
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLast), XS_NO_FLAG);
155
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_findLastIndex), XS_NO_FLAG);
156
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flat), XS_NO_FLAG);
157
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_flatMap), XS_NO_FLAG);
158
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_includes), XS_NO_FLAG);
159
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_keys), XS_NO_FLAG);
160
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_values), XS_NO_FLAG);
161
27.5k
#if mxECMAScript2023
162
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toReversed), XS_NO_FLAG);
163
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSorted), XS_NO_FLAG);
164
27.5k
  unscopable = fxNextBooleanProperty(the, unscopable, 1, mxID(_toSpliced), XS_NO_FLAG);
165
27.5k
#endif
166
27.5k
  slot = fxNextSlotProperty(the, slot, the->stack++, mxID(_Symbol_unscopables), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
167
27.5k
#if mxECMAScript2023
168
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toReversed), 0, mxID(_toReversed), XS_DONT_ENUM_FLAG);
169
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSorted), 1, mxID(_toSorted), XS_DONT_ENUM_FLAG);
170
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_toSpliced), 2, mxID(_toSpliced), XS_DONT_ENUM_FLAG);
171
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_prototype_with), 2, mxID(_with), XS_DONT_ENUM_FLAG);
172
27.5k
#endif
173
27.5k
  mxArrayPrototype = *the->stack;
174
27.5k
  slot = fxBuildHostConstructor(the, mxCallback(fx_Array), 1, mxID(_Array));
175
27.5k
  mxArrayConstructor = *the->stack;
176
27.5k
  slot = fxLastProperty(the, slot);
177
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_from), 1, mxID(_from), XS_DONT_ENUM_FLAG);
178
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_isArray), 1, mxID(_isArray), XS_DONT_ENUM_FLAG);
179
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Array_of), 0, mxID(_of), XS_DONT_ENUM_FLAG);
180
27.5k
  slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_species_get), C_NULL, mxID(_Symbol_species), XS_DONT_ENUM_FLAG);
181
27.5k
  mxPop();
182
183
27.5k
  mxPush(mxIteratorPrototype);
184
27.5k
  slot = fxLastProperty(the, fxNewObjectInstance(the));
185
27.5k
  slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_ArrayIterator_prototype_next), 0, mxID(_next), XS_DONT_ENUM_FLAG);
186
27.5k
  slot = fxNextStringXProperty(the, slot, "Array Iterator", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG);
187
27.5k
  mxPull(mxArrayIteratorPrototype);
188
27.5k
}
189
190
txNumber fxArgToIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
191
8.35M
{
192
8.35M
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
193
3.97M
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
194
3.97M
    if (c_isnan(i) || (i == 0))
195
1.48M
      i = 0;
196
3.97M
    if (i < 0) {
197
746k
      i = length + i;
198
746k
      if (i < 0)
199
419k
        i = 0;
200
746k
    }
201
3.22M
    else if (i > length)
202
1.35M
      i = length;
203
3.97M
    index = i;
204
3.97M
  }
205
8.35M
  return index;
206
8.35M
}
207
208
txInteger fxArgToIndexInteger(txMachine* the, txInteger argi, txInteger index, txInteger length)
209
1.09M
{
210
1.09M
  if (mxArgc <= argi)
211
234
    return index;
212
213
1.09M
  txSlot *slot = mxArgv(argi);
214
1.09M
  if (slot->kind != XS_INTEGER_KIND)
215
276k
    return fxArgToIndex(the, argi, index, length);
216
217
815k
  index = slot->value.integer;
218
815k
  if (index < 0) {
219
1.92k
    index = length + index;
220
1.92k
    if (index < 0)
221
1.64k
      index = 0;
222
1.92k
  }
223
813k
  else if (index > length)
224
810k
    index = length;
225
226
815k
  return index;
227
1.09M
}
228
229
txNumber fxArgToLastIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
230
347k
{
231
347k
  if (mxArgc > argi) {
232
12.0k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
233
12.0k
    if (c_isnan(i) || (i == 0))
234
8.40k
      i = 0;
235
12.0k
    if (i < 0) {
236
21
      i = length + i;
237
21
      if (i < 0)
238
5
        index = 0;
239
16
      else
240
16
        index = i + 1;
241
21
    }
242
12.0k
    else if (i < length)
243
8.41k
      index = i + 1;
244
12.0k
  }
245
347k
  return index;
246
347k
}
247
248
txNumber fxArgToRange(txMachine* the, txInteger argi, txNumber index, txNumber min, txNumber max)
249
519k
{
250
519k
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
251
519k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
252
519k
    if (c_isnan(i))
253
91.1k
      i = min;
254
519k
    if (i <= min)
255
134k
      i = min;
256
385k
    else if (i > max)
257
314k
      i = max;
258
519k
    index = i;
259
519k
  }
260
519k
  return index;
261
519k
}
262
263
txNumber fxArgToRelativeIndex(txMachine* the, txInteger argi, txNumber index, txNumber length)
264
28.9k
{
265
28.9k
  if ((mxArgc > argi) && (mxArgv(argi)->kind != XS_UNDEFINED_KIND)) {
266
24.3k
    txNumber i = c_trunc(fxToNumber(the, mxArgv(argi)));
267
24.3k
    if (c_isnan(i) || (i == 0))
268
10.7k
      i = 0;
269
24.3k
    if (i < 0)
270
2.08k
      i = length + i;
271
24.3k
    index = i;
272
24.3k
  }
273
28.9k
  return index;
274
28.9k
}
275
276
void fxCacheArray(txMachine* the, txSlot* instance)
277
9.74M
{
278
9.74M
  txSlot* array = instance->next;
279
9.74M
  txIndex length = array->value.array.length;
280
9.74M
  if (length) {
281
9.51M
    txSlot* address = (txSlot *)fxNewChunk(the, fxMultiplyChunkSizes(the, length, sizeof(txSlot)));
282
9.51M
    txSlot* srcSlot = array->next;
283
9.51M
    txSlot* dstSlot = address;
284
9.51M
    txIndex index = 0;
285
53.8M
    while (srcSlot) {
286
44.3M
      dstSlot->next = C_NULL;
287
44.3M
      *((txIndex*)dstSlot) = index; 
288
44.3M
      dstSlot->ID = XS_NO_ID;
289
44.3M
      dstSlot->flag = XS_NO_FLAG;
290
44.3M
      dstSlot->kind = srcSlot->kind;
291
44.3M
      dstSlot->value = srcSlot->value;
292
44.3M
      srcSlot = srcSlot->next;
293
44.3M
      dstSlot++;
294
44.3M
      index++;
295
44.3M
    }
296
9.51M
    array->value.array.address = address;
297
9.51M
    array->next = C_NULL;
298
9.51M
  }
299
9.74M
}
300
301
txBoolean fxCallThisItem(txMachine* the, txSlot* function, txIndex index, txSlot* item)
302
6.99M
{
303
6.99M
  mxPushSlot(mxThis);
304
6.99M
  if (mxHasIndex(index)) {
305
    /* THIS */
306
194k
    if (mxArgc > 1)
307
2.87k
      mxPushSlot(mxArgv(1));
308
191k
    else
309
191k
      mxPushUndefined();
310
    /* FUNCTION */
311
194k
    mxPushSlot(function);
312
194k
    mxCall();
313
    /* ARGUMENTS */
314
194k
    mxPushSlot(mxThis);
315
194k
    mxGetIndex(index);
316
194k
    if (item) {
317
795
      item->kind = the->stack->kind;
318
795
      item->value = the->stack->value;
319
795
    }
320
194k
    mxPushUnsigned(index);
321
194k
    mxPushSlot(mxThis);
322
194k
    mxRunCount(3);
323
194k
    return 1;
324
194k
  }
325
6.79M
  return 0;
326
6.99M
}
327
328
txSlot* fxCheckArray(txMachine* the, txSlot* slot, txBoolean mutable)
329
5.13M
{
330
5.13M
  txSlot* instance = fxToInstance(the, slot);
331
5.13M
  txSlot* array = instance->next;
332
5.13M
  if (array && (array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR)) {
333
#if mxAliasInstance
334
    if (instance->ID) {
335
      txSlot* alias = the->aliasArray[instance->ID];
336
      if (alias)
337
        array = alias->next;
338
      else if (mutable) {
339
        instance = fxAliasInstance(the, instance);
340
        array = instance->next;
341
      }
342
    }
343
#endif
344
5.13M
    {
345
5.13M
      txSlot* address = array->value.array.address;
346
5.13M
      txIndex size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0;
347
5.13M
      txSlot* prototype = instance->value.instance.prototype;
348
5.13M
      if (array->value.array.length != size)
349
1.78M
        return C_NULL;
350
3.35M
      if (mutable && ((instance->flag & XS_DONT_PATCH_FLAG) || (array->flag & XS_DONT_SET_FLAG)))
351
6
        return C_NULL;
352
10.0M
      while (prototype) {
353
6.70M
        txSlot* property = prototype->next;
354
10.0M
        while (property) {
355
10.0M
          if (property->flag & XS_INTERNAL_FLAG) {
356
3.35M
            if ((property->kind == XS_ARRAY_KIND) && (property->value.array.address != C_NULL)) 
357
3.64k
              return C_NULL;
358
3.35M
          }
359
6.70M
          else 
360
6.70M
            break;
361
3.35M
          property = property->next;
362
3.35M
        }
363
6.70M
        prototype = prototype->value.instance.prototype;
364
6.70M
      }        
365
3.34M
      return array;
366
3.35M
    }
367
3.35M
  }
368
470
  return C_NULL;
369
5.13M
}
370
371
txSlot* fxCheckArrayItems(txMachine* the, txSlot* array, txIndex from, txIndex to)
372
1.88M
{
373
1.88M
  txSlot* address = array->value.array.address;
374
1.88M
  txIndex length = array->value.array.length;
375
1.88M
  if (length < from)
376
83
    return C_NULL;
377
1.88M
  if (length < to)
378
841
    return C_NULL;
379
1.88M
  address += from;
380
6.82M
  while (from < to) {
381
4.94M
    if (address->flag)
382
5
      return C_NULL;
383
4.94M
    if (address->kind == XS_ACCESSOR_KIND)
384
3
      return C_NULL;
385
4.94M
    address++;
386
4.94M
    from++;
387
4.94M
  }
388
1.88M
  return array;
389
1.88M
}
390
391
txIndex fxCheckArrayLength(txMachine* the, txSlot* slot)
392
7.81M
{
393
7.81M
  if (slot->kind == XS_INTEGER_KIND) {
394
7.48M
    if (slot->value.integer >= 0)
395
7.48M
      return (txIndex)slot->value.integer;
396
7.48M
  }
397
328k
  else if (slot->kind == XS_NUMBER_KIND) {
398
328k
    txIndex length = (txIndex)slot->value.number;
399
328k
    txNumber check = length;
400
328k
    if (slot->value.number == check)
401
328k
      return length;
402
328k
  }
403
36
  else {
404
36
    txUnsigned length;
405
36
    txNumber check;
406
36
    mxPushSlot(slot);
407
36
    length = fxToUnsigned(the, the->stack);
408
36
    mxPop();
409
36
    mxPushSlot(slot);
410
36
    check = fxToNumber(the, the->stack);
411
36
    mxPop();
412
36
    if (length == check)
413
28
      return length;
414
36
  }
415
7.81M
  mxRangeError("invalid length");
416
0
  return 0;
417
7.81M
}
418
419
int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i)
420
960k
{
421
960k
  txSlot* address = array->value.array.address;
422
960k
  txSlot* a = address + i;
423
960k
  txSlot* b = the->stack;
424
960k
  txSlot* ai = a->next;
425
960k
  txSlot* bi = b->next;
426
960k
  int result;
427
  
428
960k
  if (a->kind == XS_UNDEFINED_KIND)
429
1.57k
    result = (b->kind == XS_UNDEFINED_KIND) ? 0 : 1;
430
959k
  else if (b->kind == XS_UNDEFINED_KIND)
431
178
    result = -1;
432
959k
  else {
433
959k
    if (function) {
434
      /* THIS */
435
690k
      mxPushUndefined();
436
      /* FUNCTION */
437
690k
      mxPushSlot(function);
438
690k
      mxCall();
439
      /* ARGUMENTS */
440
690k
      mxPushSlot(a);
441
690k
      mxPushSlot(b);
442
690k
      mxRunCount(2);
443
690k
      if (the->stack->kind == XS_INTEGER_KIND)
444
184k
        result = the->stack->value.integer;
445
505k
      else {
446
505k
        txNumber number = fxToNumber(the, the->stack);
447
505k
        result = (number < 0) ? -1 :  (number > 0) ? 1 : 0;
448
505k
      }
449
690k
      mxPop();
450
690k
    }
451
268k
    else {
452
268k
      mxPushSlot(a);
453
268k
      mxPushSlot(b);
454
268k
      fxToString(the, the->stack + 1);
455
268k
      fxToString(the, the->stack);
456
268k
      result = fxUTF8Compare((the->stack + 1)->value.string, the->stack->value.string);
457
268k
      mxPop();
458
268k
      mxPop();
459
268k
      mxMeterSome(3);
460
268k
    }
461
959k
  }
462
960k
  if (result == 0)
463
421k
    result = (bi > ai) ? -1 : (bi < ai) ? 1 : 0;
464
960k
  return result;
465
960k
}
466
467
void fxConstructArrayEntry(txMachine* the, txSlot* entry)
468
16.1k
{
469
16.1k
  txSlot* value = the->stack;
470
16.1k
  txSlot* key = the->stack + 1;
471
16.1k
  txSlot* instance;
472
16.1k
  txSlot* array;
473
16.1k
  txSlot* item;
474
16.1k
  mxPush(mxArrayPrototype);
475
16.1k
  instance = fxNewArrayInstance(the);
476
16.1k
  array = instance->next;
477
16.1k
  fxSetIndexSize(the, array, 2, XS_CHUNK);
478
16.1k
  item = array->value.array.address;
479
16.1k
  *((txIndex*)item) = 0;
480
16.1k
  item->ID = XS_NO_ID;
481
16.1k
  item->kind = key->kind;
482
16.1k
  item->value = key->value;
483
16.1k
  item++;
484
16.1k
  *((txIndex*)item) = 1;
485
16.1k
  item->ID = XS_NO_ID;
486
16.1k
  item->kind = value->kind;
487
16.1k
  item->value = value->value;
488
16.1k
  entry->kind = the->stack->kind;
489
16.1k
  entry->value = the->stack->value;
490
16.1k
  the->stack += 3;
491
16.1k
}
492
493
txSlot* fxCreateArray(txMachine* the, txFlag flag, txIndex length)
494
429k
{
495
429k
  if (mxIsReference(mxThis) && mxIsConstructor(mxThis->value.reference))
496
115
    mxPushSlot(mxThis);
497
429k
  else
498
429k
    mxPush(mxArrayConstructor);
499
429k
  mxNew();
500
429k
  if (flag) {
501
263k
    mxPushUnsigned(length);
502
263k
    mxRunCount(1);
503
263k
  }
504
166k
  else
505
166k
    mxRunCount(0);
506
429k
  mxPullSlot(mxResult);
507
429k
  return fxCheckArray(the, mxResult, XS_MUTABLE);
508
429k
}
509
510
txSlot* fxCreateArraySpecies(txMachine* the, txNumber length)
511
301k
{
512
301k
  txSlot* instance = fxToInstance(the, mxThis);
513
301k
  txFlag flag = 1;
514
301k
  if (fxIsArray(the, instance)) {
515
294k
    mxPushSlot(mxThis);
516
294k
    mxGetID(mxID(_constructor));
517
294k
    if (mxIsReference(the->stack)) {
518
294k
      mxGetID(mxID(_Symbol_species));
519
294k
      if (the->stack->kind == XS_NULL_KIND)
520
1
        the->stack->kind = XS_UNDEFINED_KIND;
521
294k
    }
522
294k
  }
523
7.19k
  else
524
7.19k
    mxPushUndefined();
525
301k
    if (the->stack->kind == XS_UNDEFINED_KIND) {
526
7.20k
    *the->stack = mxArrayConstructor;
527
7.20k
        flag = 0;
528
7.20k
    }
529
294k
  else if (mxIsReference(the->stack) && mxIsConstructor(the->stack->value.reference)) {
530
294k
    if (the->stack->value.reference != mxArrayConstructor.value.reference)
531
11
      flag = 0;
532
294k
  }
533
38
  else
534
38
    mxTypeError("invalid constructor");
535
301k
  mxNew();
536
301k
  mxPushNumber(length);
537
301k
  mxRunCount(1);
538
301k
  mxPullSlot(mxResult);
539
301k
  return (flag) ? mxResult->value.reference->next : C_NULL;
540
301k
}
541
542
void fxFindThisItem(txMachine* the, txSlot* function, txNumber index, txSlot* item)
543
57.3k
{
544
  /* THIS */
545
57.3k
  if (mxArgc > 1)
546
8
    mxPushSlot(mxArgv(1));
547
57.3k
  else
548
57.3k
    mxPushUndefined();
549
  /* FUNCTION */
550
57.3k
  mxPushSlot(function);
551
57.3k
  mxCall();
552
  /* ARGUMENTS */
553
57.3k
  mxPushSlot(mxThis);
554
57.3k
  mxGetIndex((txIndex)index);
555
57.3k
  if (item) {
556
141
    item->kind = the->stack->kind;
557
141
    item->value = the->stack->value;
558
141
  }
559
57.3k
  mxPushNumber(index);
560
57.3k
  mxPushSlot(mxThis);
561
  /* ARGC */
562
57.3k
  mxRunCount(3);
563
57.3k
}
564
565
txNumber fxGetArrayLength(txMachine* the, txSlot* reference)
566
3.78M
{
567
3.78M
  txNumber length;
568
3.78M
  txSlot* instance = fxToInstance(the, reference);
569
3.78M
  mxPushReference(instance);
570
3.78M
  mxGetID(mxID(_length));
571
3.78M
  length = fxToLength(the, the->stack);
572
3.78M
  mxPop();
573
3.78M
  return length;
574
3.78M
}
575
576
txIndex fxGetArrayLimit(txMachine* the, txSlot* reference)
577
8.76M
{
578
8.76M
  txNumber length;
579
8.76M
  txSlot* instance = fxToInstance(the, reference);
580
8.76M
  txSlot* array = instance->next;
581
8.76M
  if (array && (array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR)) {
582
#if mxAliasInstance
583
    if (instance->ID) {
584
      txSlot* alias = the->aliasArray[instance->ID];
585
      if (alias)
586
        array = alias->next;
587
    }
588
#endif
589
8.65M
    return array->value.array.length;
590
8.65M
  }
591
104k
  if (array && (array->kind == XS_TYPED_ARRAY_KIND) && (array->ID == XS_TYPED_ARRAY_BEHAVIOR)) {
592
65.4k
    txSlot* view = array->next;
593
65.4k
    txSlot* buffer = view->next;
594
65.4k
    if (mxThis->value.reference != instance) { // iterator
595
65.4k
      if (fxIsDataViewOutOfBound(the, view, buffer))
596
2
        mxTypeError("out of bound buffer");
597
65.4k
    }
598
65.4k
    return fxGetDataViewSize(the, view, buffer) >> array->value.typedArray.dispatch->shift;
599
65.4k
  }
600
39.4k
  mxPushReference(instance);
601
39.4k
  mxGetID(mxID(_length));
602
39.4k
  length = fxToLength(the, the->stack);
603
39.4k
  mxPop();
604
39.4k
  if (length > 0xFFFFFFFF) { // @@ practical limit for iterations
605
16
    txSlot* result = instance->next;
606
16
    length = 0;
607
16
    while (result && (result->flag & XS_INTERNAL_FLAG)) {
608
15
      if (result->kind == XS_ARRAY_KIND) {
609
15
        length = result->value.array.length;
610
15
        break;
611
15
      }
612
0
      result = result->next;
613
0
    }
614
16
  }
615
39.4k
  return (txIndex)length;
616
104k
}
617
618
void fxIndexArray(txMachine* the, txSlot* array) 
619
9.43M
{
620
9.43M
  txSlot* address = array->value.array.address;
621
9.43M
  if (address) {
622
1.49M
    txIndex size = (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot);
623
1.49M
    txIndex index = 0;
624
11.2M
    while (index < size) {
625
9.70M
      *((txIndex*)address) = index; 
626
9.70M
      address->flag = XS_NO_FLAG;
627
9.70M
      address++;
628
9.70M
      index++;
629
9.70M
    }
630
1.49M
  }
631
9.43M
}
632
633
txBoolean fxIsArray(txMachine* the, txSlot* instance) 
634
1.06M
{
635
1.08M
again:
636
1.08M
  if (instance) {
637
1.08M
    txSlot* internal = instance->next;
638
1.08M
    if (internal && (internal->flag & XS_INTERNAL_FLAG)) {
639
896k
      if ((internal->kind == XS_ARRAY_KIND) && (internal->ID == XS_ARRAY_BEHAVIOR))
640
352k
        return 1;
641
543k
      if (internal->kind == XS_PROXY_KIND) {
642
15.0k
        instance = internal->value.proxy.target;
643
15.0k
        if (instance)
644
15.0k
          goto again;
645
15.0k
        mxTypeError("revoked proxy");
646
647
15.0k
      }
648
543k
    }
649
1.08M
  }
650
714k
  return 0;
651
1.08M
}
652
653
void fxMoveThisItem(txMachine* the, txNumber from, txNumber to)
654
6.37M
{
655
6.37M
  mxPushSlot(mxThis);
656
6.37M
  mxPushNumber(from);
657
6.37M
  if (mxHasAt()) {
658
408k
    mxPushSlot(mxThis);
659
408k
    mxPushNumber(from);
660
408k
    mxGetAt();
661
408k
    mxPushSlot(mxThis);
662
408k
    mxPushNumber(to);
663
408k
    mxSetAt();
664
408k
    mxPop();
665
408k
  }
666
5.97M
  else {
667
5.97M
    mxPushSlot(mxThis);
668
5.97M
    mxPushNumber(to);
669
5.97M
    mxDeleteAt();
670
5.97M
    mxPop();
671
5.97M
  }
672
6.37M
}
673
674
txSlot* fxNewArrayInstance(txMachine* the)
675
18.8M
{
676
18.8M
  txSlot* instance;
677
18.8M
  txSlot* property;
678
18.8M
  instance = fxNewObjectInstance(the);
679
18.8M
  instance->flag |= XS_EXOTIC_FLAG;
680
18.8M
  property = instance->next = fxNewSlot(the);
681
18.8M
  property->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG;
682
18.8M
  property->ID = XS_ARRAY_BEHAVIOR;
683
18.8M
  property->kind = XS_ARRAY_KIND;
684
18.8M
  property->value.array.length = 0;
685
18.8M
  property->value.array.address = C_NULL;
686
18.8M
  return instance;
687
18.8M
}
688
689
void fxReduceThisItem(txMachine* the, txSlot* function, txIndex index)
690
6.85k
{
691
6.85k
  mxPushSlot(mxThis);
692
6.85k
  if (fxHasIndex(the, index)) {
693
    /* THIS */
694
6.72k
    mxPushUndefined();
695
    /* FUNCTION */
696
6.72k
    mxPushSlot(function);
697
6.72k
    mxCall();
698
    /* ARGUMENTS */
699
6.72k
    mxPushSlot(mxResult);
700
6.72k
    mxPushSlot(mxThis);
701
6.72k
    mxGetIndex(index);
702
6.72k
    mxPushUnsigned(index);
703
6.72k
    mxPushSlot(mxThis);
704
6.72k
    mxRunCount(4);
705
6.72k
    mxPullSlot(mxResult);
706
6.72k
  }
707
6.85k
}
708
709
txBoolean fxSetArrayLength(txMachine* the, txSlot* array, txIndex length)
710
7.81M
{
711
7.81M
  txSlot* address = array->value.array.address;
712
7.81M
  txSlot* chunk = address;
713
7.81M
  txBoolean success = 1;
714
7.81M
  if (address) {
715
188k
    txSize size = (((txChunk*)(((txByte*)chunk) - sizeof(txChunk)))->size) / sizeof(txSlot);
716
188k
    txSlot* result = address + size;
717
188k
    txSlot* limit = result;
718
188k
    txIndex at;
719
3.01M
    while (result > address) {
720
3.01M
      result--;
721
3.01M
      at = *((txIndex*)result);
722
3.01M
      if (length > at) {
723
188k
        result++;
724
188k
        break;
725
188k
      }
726
2.82M
      else if (result->flag & XS_DONT_DELETE_FLAG) {
727
4
        result++;
728
4
        length = at + 1;
729
4
        success = 0;
730
4
        break;
731
4
      }
732
3.01M
    }
733
188k
    if (result < limit) {
734
1.87k
      if (result > address) {
735
1.77k
        size = mxPtrDiff(result - address);
736
1.77k
        chunk = (txSlot*)fxNewChunk(the, fxMultiplyChunkSizes(the, size, sizeof(txSlot)));
737
1.77k
        address = array->value.array.address;
738
1.77k
        c_memcpy(chunk, address, size * sizeof(txSlot));
739
1.77k
      }
740
99
      else
741
99
        chunk = C_NULL;
742
1.87k
    }  
743
188k
  }
744
7.81M
  array->value.array.length = length;
745
7.81M
  array->value.array.address = chunk;
746
7.81M
  return success;
747
7.81M
}
748
749
void fxSortArrayItems(txMachine* the, txSlot* function, txSlot* array, txNumber LENGTH, txSlot* target)
750
259k
{
751
259k
  txBoolean flag = mxThis->value.reference != target->value.reference;
752
259k
  txSlot* instance = C_NULL;
753
259k
  txIndex index;
754
259k
    txSlot* item;
755
259k
  txIndex length;
756
259k
  txIndex size;
757
259k
again:
758
259k
  if (!array) {
759
259k
    LENGTH = fxGetArrayLength(the, mxThis);
760
259k
    if (LENGTH > 0xFFFFFFFF)
761
0
      mxRangeError("array overflow");
762
259k
    mxPush(mxArrayPrototype);
763
259k
    instance = fxNewArrayInstance(the);
764
259k
    array = instance->next;
765
259k
    item = array;
766
259k
        index = 0;
767
6.71M
    while (index < LENGTH) {
768
6.45M
      mxPushSlot(mxThis);
769
6.45M
      if (flag || fxHasIndex(the, index)) {
770
2.89M
        item->next = fxNewSlot(the);
771
2.89M
        item = item->next;
772
2.89M
        array->value.array.length++;
773
2.89M
        mxPushSlot(mxThis);
774
2.89M
        mxGetIndex(index);
775
2.89M
        mxPullSlot(item);
776
2.89M
      }
777
6.45M
      index++;
778
6.45M
    }
779
259k
    fxCacheArray(the, instance);
780
259k
  }
781
259k
  length = array->value.array.length;
782
259k
  size = mxArraySize(array);
783
  /* like GCC qsort */
784
259k
  #define CHECK \
785
978k
    if (size != mxArraySize(array)) { \
786
0
      array = C_NULL; \
787
0
      goto again; \
788
0
    }
789
259k
  #define COMPARE(INDEX) \
790
968k
    fxCompareArrayItem(the, function, array, INDEX)
791
259k
  #define COPY \
792
474k
    to->next = from->next; \
793
474k
    to->ID = from->ID; \
794
474k
    to->kind = from->kind; \
795
474k
    to->value = from->value
796
259k
  #define MOVE(FROM,TO) \
797
259k
    from = array->value.array.address + (FROM); \
798
194k
    to = array->value.array.address + (TO); \
799
194k
    COPY
800
259k
  #define PUSH(INDEX) \
801
259k
    from = array->value.array.address + (INDEX); \
802
151k
    mxPushUndefined(); \
803
151k
    to = the->stack; \
804
151k
    COPY
805
259k
  #define PULL(INDEX) \
806
259k
    from = the->stack++; \
807
128k
    to = array->value.array.address + (INDEX); \
808
128k
    COPY
809
259k
  if (length > 0) {
810
55.3k
    txIndex i, j;
811
55.3k
    txSlot* from;
812
55.3k
    txSlot* to;
813
55.3k
    if (length > mxSortThreshold) {
814
10.7k
      txIndex lo = 0, hi = length - 1;
815
10.7k
      txSortPartition stack[mxSortPartitionCount];
816
10.7k
      txSortPartition *top = stack + 1;
817
33.9k
      while (stack < top) {
818
23.2k
        txIndex mid = lo + ((hi - lo) >> 1);
819
23.2k
        PUSH(mid);
820
23.2k
        if (COMPARE(lo) > 0) {
821
7.23k
          CHECK;
822
7.23k
          MOVE(lo, mid);
823
7.23k
          PULL(lo);
824
7.23k
          PUSH(mid);
825
7.23k
        }
826
16.0k
        else
827
23.2k
          CHECK;
828
23.2k
        if (COMPARE(hi) < 0) {
829
2.74k
          CHECK;
830
2.74k
          MOVE(hi, mid);
831
2.74k
          PULL(hi);
832
2.74k
          PUSH(mid);
833
2.74k
          if (COMPARE(lo) > 0) {
834
473
            CHECK;
835
473
            MOVE(lo, mid);
836
473
            PULL(lo);
837
473
            PUSH(mid);
838
473
          }
839
2.27k
          else
840
2.74k
            CHECK;
841
2.74k
        }
842
20.4k
        else
843
23.2k
          CHECK;
844
23.2k
        i = lo + 1;
845
23.2k
        j = hi - 1;
846
35.0k
        do {
847
301k
          while ((COMPARE(i) < 0) && (i <= j)) { CHECK; i++; }
848
70.1k
                    CHECK;
849
352k
          while ((COMPARE(j) > 0) && (i <= j)) { CHECK; j--; }
850
70.1k
          CHECK;
851
70.1k
          if (i < j) {
852
13.7k
            PUSH(i);
853
13.7k
            MOVE(j, i);
854
13.7k
            PULL(j);
855
13.7k
            i++;
856
13.7k
            j--;
857
13.7k
          }
858
21.3k
          else if (i == j) {
859
12.3k
            i++;
860
12.3k
            j--;
861
12.3k
            break;
862
12.3k
          }
863
70.1k
        } while (i <= j);
864
23.2k
        if ((j - lo) <= mxSortThreshold) {
865
15.3k
          if ((hi - i) <= mxSortThreshold) {
866
12.2k
            top--;
867
12.2k
            lo = top->lo; 
868
12.2k
            hi = top->hi;
869
12.2k
          }
870
3.04k
          else {
871
3.04k
            lo = i;
872
3.04k
          }
873
15.3k
        }
874
7.92k
        else if ((hi - i) <= mxSortThreshold) {
875
1.33k
          hi = j;
876
1.33k
        }
877
6.58k
        else if ((j - lo) > (hi - i)) {
878
183
          top->lo = lo;
879
183
          top->hi = j; 
880
183
          top++;
881
183
          lo = i;
882
183
        }
883
6.40k
        else {
884
6.40k
          top->lo = i;
885
6.40k
          top->hi = hi; 
886
6.40k
          top++;
887
6.40k
          hi = j;
888
6.40k
        }
889
23.2k
        mxPop();
890
23.2k
      }
891
10.7k
    }
892
159k
    for (i = 1; i < length; i++) {
893
104k
      PUSH(i);
894
274k
      for (j = i; (j > 0) && (COMPARE(j - 1) > 0); j--) {
895
170k
        CHECK;
896
170k
        MOVE(j - 1, j);
897
170k
      }
898
208k
            CHECK;
899
208k
      PULL(j);
900
208k
    }
901
55.3k
  }
902
259k
  if (instance) {
903
245k
    index = 0;
904
379k
    while (index < length) {
905
133k
      item = array->value.array.address + index;
906
133k
      mxPushSlot(item);
907
133k
      mxPushSlot(target);
908
133k
      if (flag)
909
17.6k
        mxDefineIndex(index, 0, XS_GET_ONLY);
910
116k
      else
911
116k
        mxSetIndex(index);
912
133k
      mxPop();
913
133k
      index++;
914
133k
    }
915
1.33M
    while (index < LENGTH) {
916
1.08M
      mxPushSlot(target);
917
1.08M
      mxDeleteIndex(index);
918
1.08M
      index++;
919
1.08M
    }
920
245k
    mxPop();
921
245k
  }
922
14.0k
  else
923
14.0k
    fxIndexArray(the, array);
924
259k
}
925
926
txNumber fxToLength(txMachine* the, txSlot* slot)
927
23.8M
{
928
23.9M
again:
929
23.9M
  if (slot->kind == XS_INTEGER_KIND) {
930
17.5M
    txInteger length = slot->value.integer;
931
17.5M
    if (length < 0)
932
13
      length = 0;
933
17.5M
    slot->value.number = (txNumber)length;
934
17.5M
    slot->kind = XS_NUMBER_KIND;
935
17.5M
    return (txNumber)length;
936
17.5M
  }
937
6.39M
  if (slot->kind == XS_NUMBER_KIND) {
938
6.33M
    txNumber length = slot->value.number;
939
6.33M
    if (c_isnan(length))
940
4.83k
      length = 0;
941
6.33M
    else if (length <= 0)
942
37.5k
      length = 0;
943
6.29M
    else if (length > C_MAX_SAFE_INTEGER)
944
46.9k
      length = C_MAX_SAFE_INTEGER;
945
6.24M
    else
946
6.24M
      length = c_trunc(length);
947
6.33M
    slot->value.number = length;
948
6.33M
    return length;
949
6.33M
  }
950
51.7k
  fxToNumber(the, slot);
951
51.7k
  goto again;
952
6.39M
}
953
954
void fxArrayLengthGetter(txMachine* the)
955
9.03M
{
956
9.03M
  txSlot* instance = fxToInstance(the, mxThis);
957
9.03M
  txSlot* array;
958
9.03M
  while (instance) {
959
9.03M
    if (instance->flag & XS_EXOTIC_FLAG) {
960
9.03M
      array = instance->next;
961
9.03M
      if ((array->kind == XS_ARRAY_KIND) && (array->ID == XS_ARRAY_BEHAVIOR))
962
9.03M
        break;
963
9.03M
    }
964
2.10k
    instance = fxGetPrototype(the, instance);
965
2.10k
  }
966
9.03M
  if (!instance)
967
0
    return;
968
#if mxAliasInstance
969
  if (instance->ID) {
970
    txSlot* alias = the->aliasArray[instance->ID];
971
    if (alias)
972
      array = alias->next;
973
  }
974
#endif
975
9.03M
  if (((txInteger)array->value.array.length) < 0) {
976
96
    mxResult->value.number = array->value.array.length;
977
96
    mxResult->kind = XS_NUMBER_KIND;
978
96
  }
979
9.03M
  else {
980
9.03M
    mxResult->value.integer = (txInteger)array->value.array.length;
981
9.03M
    mxResult->kind = XS_INTEGER_KIND;
982
9.03M
  }
983
9.03M
}
984
985
void fxArrayLengthSetter(txMachine* the)
986
7.24M
{
987
7.24M
  txSlot* instance = fxToInstance(the, mxThis);
988
7.24M
  txSlot* array;
989
7.24M
  txIndex length;
990
7.24M
  while (instance) {
991
7.24M
    if (instance->flag & XS_EXOTIC_FLAG) {
992
7.24M
      array = instance->next;
993
7.24M
      if (array->ID == XS_ARRAY_BEHAVIOR)
994
7.24M
        break;
995
7.24M
    }
996
16
    instance = fxGetPrototype(the, instance);
997
16
  }
998
7.24M
  if (!instance)
999
0
    return;
1000
#if mxAliasInstance
1001
  if (instance->ID) {
1002
    txSlot* alias = the->aliasArray[instance->ID];
1003
    if (!alias)
1004
      alias = fxAliasInstance(the, instance);
1005
    array = alias->next;
1006
  }
1007
#endif
1008
7.24M
  length = fxCheckArrayLength(the, mxArgv(0));
1009
7.24M
  if (array->flag & XS_DONT_SET_FLAG) {
1010
2
    if (the->frame->next->flag & XS_STRICT_FLAG)
1011
1
      mxTypeError("set length: not writable");
1012
1
    else
1013
1
      return;
1014
2
  }
1015
7.24M
  fxSetArrayLength(the, array, length);
1016
7.24M
}
1017
1018
txBoolean fxArrayDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask) 
1019
18.7M
{
1020
18.7M
  if (id == mxID(_length)) {
1021
170
    txSlot* array = instance->next;
1022
170
    txSlot slot;
1023
170
    txBoolean result = 1;
1024
170
        txIndex length = ((descriptor->kind != XS_UNINITIALIZED_KIND) && (descriptor->kind != XS_ACCESSOR_KIND)) ? fxCheckArrayLength(the, descriptor) : 0;
1025
170
        slot.flag = array->flag;
1026
170
    slot.ID = id;
1027
170
    slot.kind = XS_NUMBER_KIND;
1028
170
    slot.value.number = array->value.array.length;
1029
170
    if (!fxIsPropertyCompatible(the, &slot, descriptor, mask))
1030
24
      return 0;
1031
#if mxAliasInstance
1032
    if (instance->ID) {
1033
      txSlot* alias = the->aliasArray[instance->ID];
1034
      if (!alias) {
1035
        alias = fxAliasInstance(the, instance);
1036
        array = alias->next;
1037
      }
1038
    }
1039
#endif
1040
146
    if (descriptor->kind != XS_UNINITIALIZED_KIND) {
1041
26
      if (array->value.array.length != length)
1042
22
        result = fxSetArrayLength(the, array, length);
1043
26
    }
1044
146
    if ((mask & XS_DONT_SET_FLAG) && (descriptor->flag & XS_DONT_SET_FLAG) && !(array->flag & XS_DONT_SET_FLAG))
1045
93
      array->flag |= XS_DONT_SET_FLAG;
1046
146
    return result;
1047
170
  }
1048
18.7M
  return fxOrdinaryDefineOwnProperty(the, instance, id, index, descriptor, mask);
1049
18.7M
}
1050
1051
txBoolean fxArrayDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index)
1052
3.70M
{
1053
3.70M
  if (id == mxID(_length))
1054
1
    return 0;
1055
3.70M
  return fxOrdinaryDeleteProperty(the, instance, id, index);
1056
3.70M
}
1057
1058
txBoolean fxArrayGetOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor)
1059
322k
{
1060
322k
  if (id == mxID(_length)) {
1061
19.2k
    txSlot* array = instance->next;
1062
19.2k
    descriptor->flag = array->flag;
1063
19.2k
    descriptor->ID = id;
1064
19.2k
    descriptor->kind = XS_NUMBER_KIND;
1065
19.2k
    descriptor->value.number = array->value.array.length;
1066
19.2k
    return 1;
1067
19.2k
  }
1068
303k
  return fxOrdinaryGetOwnProperty(the, instance, id, index, descriptor);
1069
322k
}
1070
1071
txSlot* fxArrayGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1072
216M
{
1073
216M
  if (id == mxID(_length))
1074
9.03M
    return &mxArrayLengthAccessor;
1075
207M
  return fxOrdinaryGetProperty(the, instance, id, index, flag);
1076
216M
}
1077
1078
txBoolean fxArrayHasProperty(txMachine* the, txSlot* instance, txID id, txIndex index) 
1079
42.8M
{
1080
42.8M
  if (id == mxID(_length))
1081
4
    return 1;
1082
42.8M
  return fxOrdinaryHasProperty(the, instance, id, index);
1083
42.8M
}
1084
1085
void fxArrayOwnKeys(txMachine* the, txSlot* instance, txFlag flag, txSlot* keys)
1086
15.1k
{
1087
15.1k
  txSlot* property = instance->next;
1088
15.1k
  keys = fxQueueIndexKeys(the, property, flag, keys);
1089
15.1k
  if (flag & XS_EACH_NAME_FLAG)
1090
15.1k
    keys = fxQueueKey(the, mxID(_length), 0, keys);
1091
15.1k
  property = property->next;
1092
15.1k
  fxQueueIDKeys(the, property, flag, keys);
1093
15.1k
}
1094
1095
txSlot* fxArraySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag)
1096
26.5M
{
1097
26.5M
  if (id == mxID(_length)) {
1098
7.24M
    txSlot* array = instance->next;
1099
7.24M
    if (array->flag & XS_DONT_SET_FLAG)
1100
1.80k
      return array;
1101
7.24M
    return &mxArrayLengthAccessor;
1102
7.24M
  }
1103
19.3M
  return fxOrdinarySetProperty(the, instance, id, index, flag);
1104
26.5M
}
1105
1106
void fx_Array(txMachine* the)
1107
950k
{
1108
950k
  txSlot* instance;
1109
950k
  txSlot* array;
1110
950k
  txSlot* argument;
1111
950k
  txIndex count = (txIndex)mxArgc;
1112
950k
  txBoolean flag = 0;
1113
950k
  txIndex index = 0;
1114
950k
  txSlot* slot;
1115
  
1116
950k
  if (mxIsUndefined(mxTarget))
1117
215k
    mxPushSlot(mxFunction);
1118
734k
  else
1119
734k
    mxPushSlot(mxTarget);
1120
950k
  fxGetPrototypeFromConstructor(the, &mxArrayPrototype);
1121
950k
  instance = fxNewArrayInstance(the);
1122
950k
  mxPullSlot(mxResult);
1123
950k
  array = instance->next; 
1124
  
1125
950k
  if (count == 1) {
1126
602k
    argument = mxArgv(0);
1127
602k
    if ((argument->kind == XS_INTEGER_KIND) || (argument->kind == XS_NUMBER_KIND)) {
1128
568k
      count = fxCheckArrayLength(the, mxArgv(0));
1129
568k
      flag = 1;
1130
568k
    }
1131
602k
  }
1132
950k
  if (array) {
1133
950k
    if (flag)
1134
568k
      fxSetArrayLength(the, array, count);
1135
382k
    else {
1136
382k
      fxSetIndexSize(the, array, count, XS_CHUNK);
1137
382k
      slot = array->value.array.address;
1138
780k
      while (index < count) {
1139
397k
        argument = mxArgv(index);
1140
397k
        *((txIndex*)slot) = index;
1141
397k
        slot->ID = XS_NO_ID;
1142
397k
        slot->kind = argument->kind;
1143
397k
        slot->value = argument->value;
1144
397k
        slot++;
1145
397k
        index++;
1146
397k
      }
1147
382k
    }
1148
950k
  }
1149
6
  else {
1150
6
    mxPushNumber(count);
1151
6
    mxPushSlot(mxThis);
1152
6
    mxSetID(mxID(_length));
1153
6
    mxPop();
1154
6
    if (!flag) {
1155
0
      while (index < count) {
1156
0
        mxPushSlot(mxArgv(index));
1157
0
        mxPushSlot(mxThis);
1158
0
        mxDefineIndex(index, 0, XS_GET_ONLY);
1159
0
        mxPop();
1160
0
        index++;
1161
0
      }
1162
0
    }
1163
6
  }
1164
950k
}
1165
1166
void fx_Array_from(txMachine* the)
1167
429k
{
1168
429k
  txSlot* function = (mxArgc > 1) ? fxArgToCallback(the, 1) : C_NULL;
1169
429k
  txIndex length = 0;
1170
429k
  txSlot* iterator;
1171
429k
  txSlot* next;
1172
429k
  txSlot* value;
1173
429k
  if (mxArgc > 0) {
1174
166k
    mxPushSlot(mxArgv(0));
1175
166k
    mxGetID(mxID(_Symbol_iterator));
1176
166k
    if (mxIsUndefined(the->stack) || mxIsNull(the->stack)) {
1177
9
      txIndex index = 0;
1178
9
      mxPushSlot(mxArgv(0));
1179
9
      mxGetID(mxID(_length));
1180
9
      if (mxIsUndefined(the->stack))
1181
1
        length = 0;
1182
8
      else
1183
8
        length = fxCheckArrayLength(the, the->stack);
1184
9
      mxPop();
1185
9
      fxCreateArray(the, 1, length);
1186
621
      while (index < length) {
1187
612
        mxPushSlot(mxArgv(0));
1188
612
        mxGetIndex(index);
1189
612
        fx_Array_from_aux(the, function, the->stack, index);
1190
612
        mxPop();
1191
612
        index++;
1192
612
      }
1193
9
    }
1194
166k
    else {
1195
166k
      fxCreateArray(the, 0, 0);
1196
166k
      mxTemporary(iterator);
1197
166k
      mxTemporary(next);
1198
166k
      fxGetIterator(the, mxArgv(0), iterator, next, 0);
1199
166k
      mxTemporary(value);
1200
166k
      length = 0;
1201
1.85M
      while (fxIteratorNext(the, iterator, next, value)) {
1202
1.68M
        mxTry(the) {
1203
1.68M
          fx_Array_from_aux(the, function, value, length);
1204
1.68M
          length++;
1205
1.68M
        }
1206
1.68M
        mxCatch(the) {
1207
3
          fxIteratorReturn(the, iterator, 1);
1208
3
          fxJump(the);
1209
3
        }
1210
1.68M
      }
1211
166k
      mxPop();
1212
166k
    }
1213
166k
  }
1214
263k
  else {
1215
263k
    fxCreateArray(the, 1, 0);
1216
263k
  }
1217
429k
  mxPushUnsigned(length);
1218
429k
  mxPushSlot(mxResult);
1219
429k
  mxSetID(mxID(_length));
1220
429k
  mxPop();
1221
429k
}
1222
1223
void fx_Array_from_aux(txMachine* the, txSlot* function, txSlot* value, txIndex index)
1224
1.68M
{
1225
1.68M
  if (function) {
1226
    /* THIS */
1227
70.8k
    if (mxArgc > 2)
1228
36.6k
      mxPushSlot(mxArgv(2));
1229
34.2k
    else
1230
34.2k
      mxPushUndefined();
1231
    /* FUNCTION */
1232
70.8k
    mxPushSlot(function);
1233
70.8k
    mxCall();
1234
    /* ARGUMENTS */
1235
70.8k
    mxPushSlot(value);
1236
70.8k
    mxPushInteger(index);
1237
70.8k
    mxRunCount(2);
1238
70.8k
  }
1239
1.61M
  else
1240
1.61M
    mxPushSlot(value);
1241
1.68M
  mxPushSlot(mxResult);
1242
1.68M
  mxDefineIndex(index, 0, XS_GET_ONLY);
1243
1.68M
  mxPop();
1244
1.68M
}
1245
1246
void fx_Array_isArray(txMachine* the)
1247
436
{
1248
436
  mxResult->kind = XS_BOOLEAN_KIND;
1249
436
  mxResult->value.boolean = (mxArgc > 0) ? fxIsArray(the, fxGetInstance(the, mxArgv(0))) : 0;
1250
436
}
1251
1252
void fx_Array_of(txMachine* the)
1253
62
{
1254
62
  txIndex count = (txIndex)mxArgc, index = 0;
1255
62
  txSlot* array = fxCreateArray(the, 1, count);
1256
62
  if (array) {
1257
24
    txSlot* slot;
1258
24
    fxSetIndexSize(the, array, count, XS_CHUNK);
1259
24
    slot = array->value.array.address;
1260
24
    while (index < count) {
1261
0
      txSlot* argument = mxArgv(index);
1262
0
      *((txIndex*)slot) = index;
1263
0
      slot->ID = XS_NO_ID;
1264
0
      slot->kind = argument->kind;
1265
0
      slot->value = argument->value;
1266
0
      slot++;
1267
0
      mxMeterSome(4);
1268
0
      index++;
1269
0
    }
1270
24
    mxMeterSome(4);
1271
24
  }
1272
38
  else {
1273
103
    while (index < count) {
1274
65
      mxPushSlot(mxArgv(index));
1275
65
      mxPushSlot(mxResult);
1276
65
      mxDefineIndex(index, 0, XS_GET_ONLY);
1277
65
      mxPop();
1278
65
      index++;
1279
65
    }
1280
38
    mxPushInteger(count);
1281
38
    mxPushSlot(mxResult);
1282
38
    mxSetID(mxID(_length));
1283
38
    mxPop();
1284
38
  }
1285
62
}
1286
1287
void fx_Array_prototype_at(txMachine* the)
1288
1.52k
{
1289
1.52k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
1290
1.52k
  txNumber length = (array) ? array->value.array.length : fxGetArrayLength(the, mxThis);
1291
1.52k
  txNumber index = (mxArgc > 0) ? c_trunc(fxToNumber(the, mxArgv(0))) : C_NAN;
1292
1.52k
  if (c_isnan(index) || (index == 0))
1293
1.11k
    index = 0;
1294
1.52k
  if (index < 0)
1295
315
    index = length + index;
1296
1.52k
  if ((0 <= index) && (index < length)) {
1297
1.10k
    mxPushSlot(mxThis);
1298
1.10k
    mxPushNumber(index);
1299
1.10k
    mxGetAt();
1300
1.10k
    mxPullSlot(mxResult);
1301
1.10k
  }
1302
1.52k
}
1303
1304
void fx_Array_prototype_concat(txMachine* the)
1305
10.9k
{
1306
10.9k
  txSlot* resultArray = fxCreateArraySpecies(the, 0);
1307
10.9k
  txIndex resultLength = 0;
1308
10.9k
  txInteger c = mxArgc;
1309
10.9k
  txInteger i = -1;
1310
10.9k
  if (resultArray) {
1311
3.81k
    txSlot* list = fxNewInstance(the);
1312
3.81k
    txSlot* slot = list;
1313
3.81k
    txSlot* resultSlot;
1314
3.81k
    txIndex holeCount = 0;
1315
3.81k
    mxPushSlot(mxThis);
1316
8.59k
    for (;;) {
1317
8.59k
      txSlot* argument = the->stack;
1318
8.59k
      txBoolean flag = 0;
1319
8.59k
      if (mxIsReference(argument)) {
1320
7.45k
        mxPushSlot(argument);
1321
7.45k
        mxGetID(mxID(_Symbol_isConcatSpreadable));
1322
7.45k
        if (mxIsUndefined(the->stack))
1323
7.42k
          flag = fxIsArray(the, argument->value.reference);
1324
33
        else
1325
33
          flag = fxToBoolean(the, the->stack);
1326
7.45k
        mxPop();
1327
7.45k
      }
1328
8.59k
      if (flag) { 
1329
7.36k
        txIndex length, index;
1330
7.36k
        mxPushSlot(argument);
1331
7.36k
        mxGetID(mxID(_length));
1332
7.36k
        length = (txIndex)fxToLength(the, the->stack);
1333
7.36k
        mxPop();
1334
7.36k
                if (resultLength + length < resultLength)
1335
6
                    mxTypeError("array overflow");
1336
7.35k
        index = 0;
1337
15.5k
        while (index < length) {
1338
8.23k
          mxPushSlot(argument);
1339
8.23k
          if (fxHasIndex(the, index)) {
1340
7.41k
            mxPushSlot(argument);
1341
7.41k
            mxGetIndex(index);
1342
7.41k
            slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
1343
7.41k
            mxMeterSome(2);
1344
7.41k
            mxPop();
1345
7.41k
          }
1346
818
          else {
1347
818
            slot = slot->next = fxNewSlot(the);
1348
818
            slot->kind = XS_UNINITIALIZED_KIND;
1349
818
            holeCount++;
1350
818
          }
1351
8.23k
          index++;
1352
8.23k
          resultLength++;
1353
8.23k
        }
1354
7.35k
      }
1355
1.22k
      else {
1356
1.22k
        slot = fxNextSlotProperty(the, slot, argument, XS_NO_ID, XS_NO_FLAG);
1357
1.22k
        mxMeterSome(4);
1358
1.22k
        resultLength++;
1359
1.22k
        if (resultLength == 0)
1360
0
          mxTypeError("array overflow");
1361
1.22k
      }
1362
8.58k
      mxPop();
1363
8.58k
      i++;
1364
8.58k
      if (i == c)
1365
3.81k
        break;
1366
4.77k
      mxPushSlot(mxArgv(i));
1367
4.77k
    }
1368
3.81k
    fxSetIndexSize(the, resultArray, resultLength - holeCount, XS_CHUNK);
1369
3.81k
    resultArray->value.array.length = resultLength;
1370
3.81k
    resultSlot = resultArray->value.array.address;
1371
3.81k
    slot = list->next;
1372
3.81k
    resultLength = 0;
1373
13.2k
    while (slot) {
1374
9.45k
      if (slot->kind != XS_UNINITIALIZED_KIND) {
1375
8.63k
        *((txIndex*)resultSlot) = resultLength;
1376
8.63k
        resultSlot->ID = XS_NO_ID;
1377
8.63k
        resultSlot->kind = slot->kind;
1378
8.63k
        resultSlot->value = slot->value;
1379
8.63k
        resultSlot++;
1380
8.63k
      }
1381
9.45k
      slot = slot->next;
1382
9.45k
      resultLength++;
1383
9.45k
    }
1384
3.81k
    mxMeterSome(3);
1385
3.81k
    mxPop();
1386
3.81k
  }
1387
7.11k
  else {
1388
7.11k
    mxPushSlot(mxThis);
1389
13.9k
    for (;;) {
1390
13.9k
      txSlot* argument = the->stack;
1391
13.9k
      txBoolean flag = 0;
1392
13.9k
      if (mxIsReference(argument)) {
1393
7.15k
        mxPushSlot(argument);
1394
7.15k
        mxGetID(mxID(_Symbol_isConcatSpreadable));
1395
7.15k
        if (mxIsUndefined(the->stack))
1396
7.14k
          flag = fxIsArray(the, argument->value.reference);
1397
11
        else
1398
11
          flag = fxToBoolean(the, the->stack);
1399
7.15k
        mxPop();
1400
7.15k
      }
1401
13.9k
      if (flag) { 
1402
29
        txIndex length, index;
1403
29
        mxPushSlot(argument);
1404
29
        mxGetID(mxID(_length));
1405
29
        length = (txIndex)fxToLength(the, the->stack);
1406
29
        mxPop();
1407
29
        index = 0;
1408
457
        while (index < length) {
1409
428
          mxPushSlot(argument);
1410
428
          if (fxHasIndex(the, index)) {
1411
117
            mxPushSlot(argument);
1412
117
            mxGetIndex(index);
1413
117
            mxPushSlot(mxResult);
1414
117
            mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1415
117
            mxPop();
1416
117
          }
1417
428
          index++;
1418
428
          resultLength++;
1419
428
        }
1420
29
      }
1421
13.9k
      else {
1422
13.9k
        mxPushSlot(argument);
1423
13.9k
        mxPushSlot(mxResult);
1424
13.9k
        mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1425
13.9k
        mxPop();
1426
13.9k
        resultLength++;
1427
13.9k
      }
1428
13.9k
      mxPop();
1429
13.9k
      i++;
1430
13.9k
      if (i == c)
1431
7.10k
        break;
1432
6.89k
      mxPushSlot(mxArgv(i));
1433
6.89k
    }
1434
7.11k
    mxPushInteger(resultLength);
1435
7.11k
    mxPushSlot(mxResult);
1436
7.11k
    mxSetID(mxID(_length));
1437
7.11k
    mxPop();
1438
7.11k
  }
1439
10.9k
}
1440
1441
void fx_Array_prototype_copyWithin(txMachine* the)
1442
1.72M
{
1443
1.72M
  txNumber length = fxGetArrayLength(the, mxThis);
1444
1.72M
  txNumber to = fxArgToIndex(the, 0, 0, length);
1445
1.72M
  txNumber from = fxArgToIndex(the, 1, 0, length);
1446
1.72M
  txNumber final = fxArgToIndex(the, 2, length, length);
1447
1.72M
  txNumber count = (final > from) ? final - from : 0;
1448
1.72M
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
1449
1.72M
  if (count > length - to)
1450
928k
    count = length - to;
1451
1.72M
  if (array) {
1452
805k
    if (count > 0) {
1453
403k
      if (from < to)
1454
259k
        array = fxCheckArrayItems(the, array, (txIndex)from, (txIndex)(to + count));
1455
143k
      else
1456
143k
        array = fxCheckArrayItems(the, array, (txIndex)to, (txIndex)(from + count));
1457
403k
    }
1458
805k
  }
1459
1.72M
  if (array) {
1460
805k
    if (count > 0) {
1461
403k
      c_memmove(array->value.array.address + (txIndex)to, array->value.array.address + (txIndex)from, (txIndex)count * sizeof(txSlot));
1462
403k
      fxIndexArray(the, array);
1463
403k
      mxMeterSome((txU4)count * 10);
1464
403k
    }
1465
805k
  }
1466
921k
  else {
1467
921k
    txNumber direction;
1468
921k
    if ((from < to) && (to < from + count)) {
1469
14.7k
      direction = -1;
1470
14.7k
      from += count - 1;
1471
14.7k
      to += count - 1;
1472
14.7k
    }
1473
906k
    else
1474
906k
      direction = 1;
1475
1.75M
    while (count > 0) {
1476
830k
      fxMoveThisItem(the, from, to);
1477
830k
      from += direction;
1478
830k
      to += direction;
1479
830k
      count--;
1480
830k
      mxCheckMetering();
1481
830k
    }  
1482
921k
  }  
1483
1.72M
  mxResult->kind = mxThis->kind;
1484
1.72M
  mxResult->value = mxThis->value;
1485
1.72M
}
1486
1487
void fx_Array_prototype_entries(txMachine* the)
1488
15
{
1489
15
  txSlot* property;
1490
15
  fxToInstance(the, mxThis);
1491
15
  mxPush(mxArrayIteratorPrototype);
1492
15
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
1493
15
  property = fxNextIntegerProperty(the, property, 2, XS_NO_ID, XS_INTERNAL_FLAG);
1494
15
  mxPullSlot(mxResult);
1495
15
}
1496
1497
void fx_Array_prototype_every(txMachine* the)
1498
56.5k
{
1499
56.5k
  txIndex length = fxGetArrayLimit(the, mxThis);
1500
56.5k
  txIndex index = 0;
1501
56.5k
  txSlot* function = fxArgToCallback(the, 0);
1502
56.5k
  mxResult->kind = XS_BOOLEAN_KIND;
1503
56.5k
  mxResult->value.boolean = 1;
1504
2.42M
  while (index < length) {
1505
2.37M
    if (fxCallThisItem(the, function, index, C_NULL)) {
1506
56.5k
      mxResult->value.boolean = fxToBoolean(the, the->stack);
1507
56.5k
      mxPop();
1508
56.5k
      if (!mxResult->value.boolean)
1509
11
        break;
1510
56.5k
    }
1511
2.37M
    index++;
1512
2.37M
    mxCheckMetering();
1513
2.37M
  }
1514
56.5k
}
1515
1516
void fx_Array_prototype_fill(txMachine* the)
1517
734k
{
1518
734k
  txSlot* value;
1519
734k
  txSlot* array;
1520
734k
  if (mxArgc > 0)
1521
734k
    mxPushSlot(mxArgv(0));
1522
4
  else
1523
4
    mxPushUndefined();
1524
734k
  value = the->stack;
1525
734k
  array = fxCheckArray(the, mxThis, XS_MUTABLE);
1526
734k
  if (array)
1527
517k
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
1528
734k
  if (array) {
1529
517k
    txIndex length = array->value.array.length;
1530
517k
    txIndex start = (txIndex)fxArgToIndex(the, 1, 0, length);
1531
517k
    txIndex end = (txIndex)fxArgToIndex(the, 2, length, length);
1532
517k
    txSlot* address;
1533
517k
    txIndex size;
1534
517k
    if ((start == 0) && (end == length)) {
1535
511k
      fxSetIndexSize(the, array, length, XS_CHUNK);
1536
511k
      fxIndexArray(the, array);
1537
511k
    }
1538
517k
    address = array->value.array.address;
1539
517k
    size = (address) ? (((txChunk*)(((txByte*)address) - sizeof(txChunk)))->size) / sizeof(txSlot) : 0;
1540
517k
    if (length == size) {
1541
1.13M
      while (start < end) {
1542
613k
        txSlot* slot = array->value.array.address + start;
1543
613k
        if (slot->flag) {
1544
0
          mxPushSlot(value);
1545
0
          mxPushSlot(mxThis);
1546
0
          mxSetIndex(start);
1547
0
          mxPop();
1548
0
          mxMeterSome(1);
1549
0
        }
1550
613k
        else {
1551
613k
          slot->ID = XS_NO_ID;
1552
613k
          slot->kind = value->kind;
1553
613k
          slot->value = value->value;
1554
613k
          mxMeterSome(5);
1555
613k
        }
1556
613k
        start++;
1557
613k
        mxCheckMetering();
1558
613k
      }
1559
      
1560
517k
    }
1561
0
    else {
1562
0
      while (start < end) {
1563
0
        mxPushSlot(value);
1564
0
        mxPushSlot(mxThis);
1565
0
        mxSetIndex(start);
1566
0
        mxPop();
1567
0
        mxMeterSome(1);
1568
0
        start++;
1569
0
        mxCheckMetering();
1570
0
      }
1571
0
    }
1572
517k
  }
1573
217k
  else {
1574
217k
    txNumber length = fxGetArrayLength(the, mxThis);
1575
217k
    txNumber start = fxArgToIndex(the, 1, 0, length);
1576
217k
    txNumber end = fxArgToIndex(the, 2, length, length);
1577
217k
    txSlot* value = the->stack;
1578
772k
    while (start < end) {
1579
554k
      mxPushSlot(value);
1580
554k
      mxPushSlot(mxThis);
1581
554k
      mxPushNumber(start);
1582
554k
      mxSetAt();
1583
554k
      mxPop();
1584
554k
      start++;
1585
554k
      mxCheckMetering();
1586
554k
    }
1587
217k
  }
1588
734k
  mxPop();
1589
734k
  mxResult->kind = mxThis->kind;
1590
734k
  mxResult->value = mxThis->value;
1591
734k
}
1592
1593
void fx_Array_prototype_filter(txMachine* the)
1594
68
{
1595
68
  txIndex length = fxGetArrayLimit(the, mxThis);
1596
68
  txIndex index = 0;
1597
68
  txSlot* function = fxArgToCallback(the, 0);
1598
68
  txSlot* resultArray = fxCreateArraySpecies(the, 0);
1599
68
  txIndex resultLength = 0;
1600
68
  txSlot* item;
1601
68
  mxPushUndefined();
1602
68
  item = the->stack;
1603
68
  if (resultArray) {
1604
29
    txSlot* list = fxNewInstance(the);
1605
29
    txSlot* slot = list;
1606
29
    txSlot* resultSlot;
1607
1.14M
    while (index < length) {
1608
1.14M
      if (fxCallThisItem(the, function, index, item)) {
1609
196
        if (fxToBoolean(the, the->stack)) {
1610
109
          slot = fxNextSlotProperty(the, slot, item, XS_NO_ID, XS_NO_FLAG);
1611
109
          mxMeterSome(4);
1612
109
          resultLength++;
1613
109
        }
1614
196
        mxPop();
1615
196
      }
1616
1.14M
      index++;
1617
1.14M
      mxCheckMetering();
1618
1.14M
    }
1619
29
    fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK);
1620
29
    resultSlot = resultArray->value.array.address;
1621
29
    slot = list->next;
1622
29
    index = 0;
1623
138
    while (slot) {
1624
109
      *((txIndex*)resultSlot) = index;
1625
109
      resultSlot->ID = XS_NO_ID;
1626
109
      resultSlot->kind = slot->kind;
1627
109
      resultSlot->value = slot->value;
1628
109
      resultSlot++;
1629
109
      slot = slot->next;
1630
109
      index++;
1631
109
    }
1632
29
    mxPop();
1633
29
    mxMeterSome(-1);
1634
29
  }
1635
39
  else {
1636
278k
    while (index < length) {
1637
278k
      if (fxCallThisItem(the, function, index, item)) {
1638
599
        if (fxToBoolean(the, the->stack)) {
1639
81
          mxPushSlot(item);
1640
81
          mxPushSlot(mxResult);
1641
81
          mxDefineIndex(resultLength, 0, XS_GET_ONLY);
1642
81
          mxPop();
1643
81
          resultLength++;
1644
81
        }
1645
599
        mxPop();
1646
599
      }
1647
278k
      index++;
1648
278k
      mxCheckMetering();
1649
278k
    }
1650
39
  }
1651
68
  mxPop();
1652
68
}
1653
1654
void fx_Array_prototype_find(txMachine* the)
1655
50
{
1656
50
  txIndex length = fxGetArrayLimit(the, mxThis);
1657
50
  txIndex index = 0;
1658
50
  txSlot* function = fxArgToCallback(the, 0);
1659
50
  txSlot* item;
1660
50
  mxPushUndefined();
1661
50
  item = the->stack;
1662
118
  while (index < length) {
1663
81
    fxFindThisItem(the, function, index, item);
1664
81
    if (fxToBoolean(the, the->stack++)) {
1665
13
      mxResult->kind = item->kind;
1666
13
      mxResult->value = item->value;
1667
13
      break;
1668
13
    }
1669
68
    index++;
1670
68
  }
1671
50
  mxPop();
1672
50
}
1673
1674
void fx_Array_prototype_findIndex(txMachine* the)
1675
77
{
1676
77
  txIndex length = fxGetArrayLimit(the, mxThis);
1677
77
  txIndex index = 0;
1678
77
  txSlot* function = fxArgToCallback(the, 0);
1679
77
  fxInteger(the, mxResult, -1);
1680
141
  while (index < length) {
1681
77
    fxFindThisItem(the, function, index, C_NULL);
1682
77
    if (fxToBoolean(the, the->stack++)) {
1683
13
      fxUnsigned(the, mxResult, index);
1684
13
      break;
1685
13
    }
1686
64
    index++;
1687
64
  }
1688
77
}
1689
1690
void fx_Array_prototype_findLast(txMachine* the)
1691
50
{
1692
50
  txNumber index = fxGetArrayLength(the, mxThis);
1693
50
  txSlot* function = fxArgToCallback(the, 0);
1694
50
  txSlot* item;
1695
50
  mxPushUndefined();
1696
50
  item = the->stack;
1697
97
  while (index > 0) {
1698
60
    index--;
1699
60
    fxFindThisItem(the, function, index, item);
1700
60
    if (fxToBoolean(the, the->stack++)) {
1701
13
      mxResult->kind = item->kind;
1702
13
      mxResult->value = item->value;
1703
13
      break;
1704
13
    }
1705
60
  }
1706
50
  mxPop();
1707
50
}
1708
1709
void fx_Array_prototype_findLastIndex(txMachine* the)
1710
44
{
1711
44
  txNumber index = fxGetArrayLength(the, mxThis);
1712
44
  txSlot* function = fxArgToCallback(the, 0);
1713
44
  fxInteger(the, mxResult, -1);
1714
57.1k
  while (index > 0) {
1715
57.1k
    index--;
1716
57.1k
    fxFindThisItem(the, function, index, C_NULL);
1717
57.1k
    if (fxToBoolean(the, the->stack++)) {
1718
13
      fxUnsigned(the, mxResult, (txUnsigned)index);
1719
13
      break;
1720
13
    }
1721
57.1k
  }
1722
44
}
1723
1724
void fx_Array_prototype_flat(txMachine* the)
1725
62
{
1726
62
  txIndex length, depth = 1;
1727
62
  mxPushSlot(mxThis);
1728
62
  mxGetID(mxID(_length));
1729
62
  length = (txIndex)fxToLength(the, the->stack);
1730
62
  mxPop();
1731
62
  if ((mxArgc > 0) && !mxIsUndefined(mxArgv(0)))
1732
28
    depth = (txIndex)fxToLength(the, mxArgv(0));
1733
62
  fxCreateArraySpecies(the, 0);
1734
62
  fx_Array_prototype_flatAux(the, mxThis, length, 0, depth, C_NULL);
1735
62
}
1736
1737
txIndex fx_Array_prototype_flatAux(txMachine* the, txSlot* source, txIndex length, txIndex start, txIndex depth, txSlot* function)
1738
128
{
1739
128
  txSlot* item;
1740
128
  txIndex index = 0;
1741
481
  while (index < length) {
1742
353
    mxPushSlot(source);
1743
353
    if (fxHasIndex(the, index)) {
1744
242
      if (function) {
1745
        /* THIS */
1746
41
        if (mxArgc > 1)
1747
3
          mxPushSlot(mxArgv(1));
1748
38
        else
1749
38
          mxPushUndefined();
1750
        /* FUNCTION */
1751
41
        mxPushSlot(function);
1752
41
        mxCall();
1753
        /* ARGUMENTS */
1754
41
        mxPushSlot(source);
1755
41
        mxGetIndex(index);
1756
41
        mxPushUnsigned(index);
1757
41
        mxPushSlot(mxThis);
1758
41
        mxRunCount(3);
1759
41
      }
1760
201
      else {
1761
201
        mxPushSlot(source);
1762
201
        mxGetIndex(index);
1763
201
      }
1764
242
      item = the->stack;
1765
242
      if ((depth > 0) && mxIsReference(item) && fxIsArray(the, fxToInstance(the, item))) {
1766
64
        txIndex itemLength;
1767
64
        mxPushSlot(item);
1768
64
        mxGetID(mxID(_length));
1769
64
        itemLength = (txIndex)fxToLength(the, the->stack);
1770
64
        mxPop();
1771
64
        start = fx_Array_prototype_flatAux(the, item, itemLength, start, depth - 1, C_NULL);
1772
64
      }
1773
178
      else {
1774
178
        mxPushSlot(mxResult);
1775
178
        mxDefineIndex(start, 0, XS_GET_ONLY);
1776
178
        start++;
1777
178
      }
1778
242
    }
1779
353
    index++;
1780
353
  }
1781
128
  return start;
1782
128
}
1783
1784
void fx_Array_prototype_flatMap(txMachine* the)
1785
41
{
1786
41
  txIndex length = (txIndex)fxGetArrayLength(the, mxThis);
1787
41
  txSlot* function = fxArgToCallback(the, 0);
1788
41
  fxCreateArraySpecies(the, 0);
1789
41
  fx_Array_prototype_flatAux(the, mxThis, length, 0, 1, function);
1790
41
}
1791
1792
void fx_Array_prototype_forEach(txMachine* the)
1793
1.19k
{
1794
1.19k
  txIndex length = fxGetArrayLimit(the, mxThis);
1795
1.19k
  txIndex index = 0;
1796
1.19k
  txSlot* function = fxArgToCallback(the, 0);
1797
1.14M
  while (index < length) {
1798
1.14M
    if (fxCallThisItem(the, function, index, C_NULL))
1799
78.5k
      mxPop();
1800
1.14M
    index++;
1801
1.14M
    mxCheckMetering();
1802
1.14M
  }
1803
1.19k
}
1804
1805
void fx_Array_prototype_includes(txMachine* the)
1806
154k
{
1807
154k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
1808
154k
  txSlot* argument;
1809
154k
  if (mxArgc > 0)
1810
154k
    mxPushSlot(mxArgv(0));
1811
20
  else
1812
20
    mxPushUndefined();
1813
154k
  argument = the->stack;
1814
154k
  fxBoolean(the, mxResult, 0);
1815
154k
  if (array) {
1816
154k
    txIndex length = array->value.array.length;
1817
154k
    if (length) {
1818
154k
      txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length);
1819
454k
      while (index < length) {
1820
365k
        mxPushSlot(mxThis);
1821
365k
        mxGetIndex(index);
1822
365k
        if (fxIsSameValue(the, the->stack++, argument, 1)) {
1823
65.1k
          mxResult->value.boolean = 1;
1824
65.1k
          break;
1825
65.1k
        }
1826
300k
        index++;
1827
300k
        mxCheckMetering();
1828
300k
      }
1829
154k
    }
1830
154k
  }
1831
166
  else {
1832
166
    txNumber length = fxGetArrayLength(the, mxThis);
1833
166
    if (length) {
1834
132
      txNumber index = fxArgToIndex(the, 1, 0, length);
1835
2.09M
      while (index < length) {
1836
2.09M
        mxPushSlot(mxThis);
1837
2.09M
        mxPushNumber(index);
1838
2.09M
        mxGetAt();
1839
2.09M
        if (fxIsSameValue(the, the->stack++, argument, 1)) {
1840
68
          mxResult->value.boolean = 1;
1841
68
          break;
1842
68
        }
1843
2.09M
        index++;
1844
2.09M
        mxCheckMetering();
1845
2.09M
      }
1846
132
    }
1847
166
  }
1848
154k
  mxPop();
1849
154k
}
1850
1851
void fx_Array_prototype_indexOf(txMachine* the)
1852
43.9k
{
1853
43.9k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
1854
43.9k
  txSlot* argument;
1855
43.9k
  if (mxArgc > 0)
1856
42.0k
    mxPushSlot(mxArgv(0));
1857
1.90k
  else
1858
1.90k
    mxPushUndefined();
1859
43.9k
  argument = the->stack;
1860
43.9k
  fxInteger(the, mxResult, -1);
1861
43.9k
  if (array) {
1862
43.6k
    txIndex length = array->value.array.length;
1863
43.6k
    if (length) {
1864
42.0k
      txIndex index = (txIndex)fxArgToIndex(the, 1, 0, length);
1865
437k
      while (index < length) {
1866
400k
        mxPushSlot(mxThis);
1867
400k
        if (fxHasIndex(the, index)) {
1868
400k
          mxPushSlot(mxThis);
1869
400k
          mxGetIndex(index);
1870
400k
          if (fxIsSameSlot(the, the->stack++, argument)) {
1871
4.81k
            fxUnsigned(the, mxResult, index);
1872
4.81k
            break;
1873
4.81k
          }
1874
400k
        }
1875
395k
        index++;
1876
395k
        mxCheckMetering();
1877
395k
      }
1878
42.0k
    }
1879
43.6k
  }
1880
306
  else {
1881
306
    txNumber length = fxGetArrayLength(the, mxThis);
1882
306
    if (length) {
1883
285
      txNumber index = fxArgToIndex(the, 1, 0, length);
1884
3.18M
      while (index < length) {
1885
3.18M
        mxPushSlot(mxThis);
1886
3.18M
        mxPushNumber(index);
1887
3.18M
        if (mxHasAt()) {
1888
1.19k
          mxPushSlot(mxThis);
1889
1.19k
          mxPushNumber(index);
1890
1.19k
          mxGetAt();
1891
1.19k
          if (fxIsSameSlot(the, the->stack++, argument)) {
1892
86
            fxNumber(the, mxResult, index);
1893
86
            break;
1894
86
          }
1895
1.19k
        }
1896
3.18M
        index++;
1897
3.18M
        mxCheckMetering();
1898
3.18M
      }
1899
285
    }
1900
306
  }
1901
43.9k
  mxPop();
1902
43.9k
}
1903
1904
void fx_Array_prototype_join(txMachine* the)
1905
7.77M
{
1906
7.77M
  txIndex length = fxGetArrayLimit(the, mxThis);
1907
7.77M
  txIndex index = 0;
1908
7.77M
  txString string;
1909
7.77M
  txSlot* list = fxNewInstance(the);
1910
7.77M
  txSlot* slot = list;
1911
7.77M
  txBoolean comma = 0;
1912
7.77M
  txInteger size = 0;
1913
7.77M
  if ((mxArgc > 0) && (mxArgv(0)->kind != XS_UNDEFINED_KIND)) {
1914
26
    mxPushSlot(mxArgv(0));
1915
26
    string = fxToString(the, the->stack);
1916
26
    the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
1917
26
    the->stack->value.key.sum = mxStringLength(string);
1918
26
  }
1919
7.77M
  else {
1920
7.77M
    mxPushStringX(",");
1921
7.77M
    the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
1922
7.77M
    the->stack->value.key.sum = 1;
1923
7.77M
  }
1924
38.6M
  while (index < length) {
1925
30.8M
    if (comma) {
1926
23.4M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
1927
23.4M
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
1928
23.4M
    }
1929
7.41M
    else
1930
7.41M
      comma = 1;
1931
30.8M
    mxPushSlot(mxThis);
1932
30.8M
    mxGetIndex(index);
1933
30.8M
    if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) {
1934
16.1M
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
1935
16.1M
      string = fxToString(the, slot);
1936
16.1M
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
1937
16.1M
      slot->value.key.sum = mxStringLength(string);
1938
16.1M
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
1939
16.1M
    }
1940
30.8M
    mxPop();
1941
30.8M
    index++;
1942
1943
30.8M
    mxCheckMetering();
1944
30.8M
  }
1945
7.77M
  mxPop();
1946
7.77M
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
1947
7.77M
  slot = list->next;
1948
44.7M
  while (slot) {
1949
36.9M
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
1950
36.9M
    string += slot->value.key.sum;
1951
36.9M
    slot = slot->next;
1952
36.9M
  }
1953
7.77M
  *string = 0;
1954
7.77M
  mxResult->kind = XS_STRING_KIND;
1955
7.77M
  mxPop();
1956
7.77M
}
1957
1958
void fx_Array_prototype_keys(txMachine* the)
1959
7
{
1960
7
  txSlot* property;
1961
7
  fxToInstance(the, mxThis);
1962
7
  mxPush(mxArrayIteratorPrototype);
1963
7
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
1964
7
  property = fxNextIntegerProperty(the, property, 1, XS_NO_ID, XS_INTERNAL_FLAG);
1965
7
  mxPullSlot(mxResult);
1966
7
}
1967
1968
void fx_Array_prototype_lastIndexOf(txMachine* the)
1969
347k
{
1970
347k
  txSlot* array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
1971
347k
  txSlot* argument;
1972
347k
  if (mxArgc > 0)
1973
275k
    mxPushSlot(mxArgv(0));
1974
72.2k
  else
1975
72.2k
    mxPushUndefined();
1976
347k
  argument = the->stack;
1977
347k
  fxInteger(the, mxResult, -1);
1978
347k
  if (array) {
1979
235k
    txIndex length = array->value.array.length;
1980
235k
    if (length) {
1981
235k
      txIndex index = (txIndex)fxArgToLastIndex(the, 1, length, length);
1982
1.21M
      while (index > 0) {
1983
1.01M
        index--;
1984
1.01M
        mxPushSlot(mxThis);
1985
1.01M
        if (fxHasIndex(the, index)) {
1986
1.01M
          mxPushSlot(mxThis);
1987
1.01M
          mxGetIndex(index);
1988
1.01M
          if (fxIsSameSlot(the, the->stack++, argument)) {
1989
35.7k
            fxUnsigned(the, mxResult, index);
1990
35.7k
            break;
1991
35.7k
          }
1992
1.01M
        }
1993
984k
        mxCheckMetering();
1994
984k
      }
1995
235k
    }
1996
235k
  }
1997
112k
  else {
1998
112k
    txNumber length = fxGetArrayLength(the, mxThis);
1999
112k
    if (length) {
2000
112k
      txNumber index = fxArgToLastIndex(the, 1, length, length);
2001
3.63M
      while (index > 0) {
2002
3.53M
        index--;
2003
3.53M
        mxPushSlot(mxThis);
2004
3.53M
        mxPushNumber(index);
2005
3.53M
        if (mxHasAt()) {
2006
314k
          mxPushSlot(mxThis);
2007
314k
          mxPushNumber(index);
2008
314k
          mxGetAt();
2009
314k
          if (fxIsSameSlot(the, the->stack++, argument)) {
2010
20.4k
            fxNumber(the, mxResult, index);
2011
20.4k
            break;
2012
20.4k
          }
2013
314k
        }
2014
3.51M
        mxCheckMetering();
2015
3.51M
      }
2016
112k
    }
2017
112k
  }
2018
347k
  mxPop();
2019
347k
}
2020
2021
void fx_Array_prototype_map(txMachine* the)
2022
31.5k
{
2023
31.5k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2024
31.5k
  txSlot* function = fxArgToCallback(the, 0);
2025
31.5k
  txSlot* resultArray = fxCreateArraySpecies(the, LENGTH);
2026
31.5k
  txIndex length = (txIndex)LENGTH;
2027
31.5k
  txIndex index = 0;
2028
31.5k
  if (resultArray) {
2029
31.5k
    txIndex resultLength = 0;
2030
31.5k
    fxSetIndexSize(the, resultArray, length, XS_CHUNK);
2031
1.08M
    while (index < length) {
2032
1.05M
      if (fxCallThisItem(the, function, index, C_NULL)) {
2033
54.9k
        txSlot* slot = resultArray->value.array.address + resultLength;
2034
54.9k
        *((txIndex*)slot) = index;
2035
54.9k
        slot->ID = XS_NO_ID;
2036
54.9k
        slot->kind = the->stack->kind;
2037
54.9k
        slot->value = the->stack->value;
2038
54.9k
        resultLength++;
2039
54.9k
        mxMeterSome(2);
2040
54.9k
        mxPop();
2041
54.9k
      }
2042
1.05M
      index++;
2043
1.05M
      mxCheckMetering();
2044
1.05M
    }
2045
31.5k
    if (resultLength < length) {
2046
9
      fxSetIndexSize(the, resultArray, resultLength, XS_CHUNK);
2047
9
      resultArray->value.array.length = length;
2048
9
    }
2049
31.5k
  }
2050
24
  else {
2051
192
    while (index < length) {
2052
168
      if (fxCallThisItem(the, function, index, C_NULL)) {
2053
25
        mxPushSlot(mxResult);
2054
25
        mxDefineIndex(index, 0, XS_GET_ONLY);
2055
25
        mxPop();
2056
25
      }
2057
168
      index++;
2058
168
      mxCheckMetering();
2059
168
    }
2060
24
  }
2061
31.5k
}
2062
2063
void fx_Array_prototype_pop(txMachine* the)
2064
2.24k
{
2065
2.24k
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2066
2.24k
  if (array) {
2067
1.53k
    txIndex length = array->value.array.length;
2068
1.53k
    if (length > 0)
2069
249
      array = fxCheckArrayItems(the, array, length - 1, length);
2070
1.53k
  }
2071
2.24k
  if (array) {
2072
1.53k
    txIndex length = array->value.array.length;
2073
1.53k
    txSlot* address;
2074
1.53k
    mxMeterSome(2);
2075
1.53k
    if (length > 0) {
2076
249
      length--;
2077
249
      address = array->value.array.address + length;
2078
249
      mxResult->kind = address->kind;
2079
249
      mxResult->value = address->value;
2080
249
      fxSetIndexSize(the, array, length, XS_CHUNK);
2081
249
      mxMeterSome(8);
2082
249
    }
2083
1.53k
    mxMeterSome(4);
2084
1.53k
  }
2085
713
  else {
2086
713
    txNumber length = fxGetArrayLength(the, mxThis);
2087
713
    if (length > 0) {
2088
695
      length--;
2089
695
      mxPushSlot(mxThis);
2090
695
      mxPushNumber(length);
2091
695
      mxGetAt();
2092
695
      mxPullSlot(mxResult);
2093
695
      mxPushSlot(mxThis);
2094
695
      mxPushNumber(length);
2095
695
      mxDeleteAt();
2096
695
      mxPop();
2097
695
    }
2098
713
    mxPushNumber(length);
2099
713
    mxPushSlot(mxThis);
2100
713
    mxSetID(mxID(_length));
2101
713
    mxPop();
2102
713
  }
2103
2.24k
}
2104
2105
void fx_Array_prototype_push(txMachine* the)
2106
331k
{
2107
331k
  txIndex c = mxArgc, i = 0;
2108
331k
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2109
331k
  if (array) {
2110
327k
    txIndex length = array->value.array.length;
2111
327k
    txSlot* address;
2112
327k
    mxMeterSome(2);
2113
327k
    if (length + c < length)
2114
0
      mxRangeError("array overflow");
2115
327k
    fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK);
2116
327k
    address = array->value.array.address + length;
2117
656k
    while (i < c) {
2118
329k
      txSlot* argument = mxArgv(i);
2119
329k
      *((txIndex*)address) = length + i;
2120
329k
      address->ID = XS_NO_ID;
2121
329k
      address->kind = argument->kind;
2122
329k
      address->value = argument->value;
2123
329k
      address++;
2124
329k
      mxMeterSome(5);
2125
329k
      i++;
2126
329k
    }
2127
327k
    mxPushUnsigned(length + c);
2128
327k
    mxMeterSome(2);
2129
327k
  }
2130
3.67k
  else {
2131
3.67k
    txNumber length = fxGetArrayLength(the, mxThis);
2132
3.67k
    if (length + c > C_MAX_SAFE_INTEGER)
2133
10
      mxTypeError("unsafe integer");
2134
7.32k
    while (i < c) {
2135
3.65k
      mxPushSlot(mxArgv(i));
2136
3.65k
      mxPushSlot(mxThis);
2137
3.65k
      mxPushNumber(length + i);
2138
3.65k
      mxSetAt();
2139
3.65k
      mxPop();
2140
3.65k
      i++;
2141
3.65k
    }
2142
3.66k
    mxPushNumber(length + c);
2143
3.66k
    mxPushSlot(mxThis);
2144
3.66k
    mxSetID(mxID(_length));
2145
3.66k
  }
2146
331k
  mxPullSlot(mxResult);
2147
331k
}
2148
2149
void fx_Array_prototype_reduce(txMachine* the)
2150
45
{
2151
45
  txIndex length = fxGetArrayLimit(the, mxThis);
2152
45
  txIndex index = 0;
2153
45
  txSlot* function = fxArgToCallback(the, 0);
2154
45
  if (mxArgc > 1)
2155
22
    *mxResult = *mxArgv(1);
2156
23
  else {
2157
23
    txBoolean flag = 0;
2158
335
    while (!flag && (index < length)) {
2159
312
      mxPushSlot(mxThis);
2160
312
      if (fxHasIndex(the, index)) {
2161
11
        mxPushSlot(mxThis);
2162
11
        mxGetIndex(index);
2163
11
        mxPullSlot(mxResult);
2164
11
        flag = 1;
2165
11
      }
2166
312
      index++;
2167
312
    }
2168
23
    if (!flag)
2169
11
      mxTypeError("no initial value");
2170
23
  }
2171
6.71k
  while (index < length) {
2172
6.67k
    fxReduceThisItem(the, function, index);
2173
6.67k
    index++;
2174
6.67k
  }
2175
34
}
2176
2177
void fx_Array_prototype_reduceRight(txMachine* the)
2178
42
{
2179
42
  txIndex length = fxGetArrayLimit(the, mxThis);
2180
42
  txIndex index = length;
2181
42
  txSlot* function = fxArgToCallback(the, 0);
2182
42
  if (mxArgc > 1)
2183
30
    *mxResult = *mxArgv(1);
2184
12
  else {
2185
12
    txBoolean flag = 0;
2186
106
    while (!flag && (index > 0)) {
2187
94
      index--;
2188
94
      mxPushSlot(mxThis);
2189
94
      if (fxHasIndex(the, index)) {
2190
6
        mxPushSlot(mxThis);
2191
6
        mxGetIndex(index);
2192
6
        mxPullSlot(mxResult);
2193
6
        flag = 1;
2194
6
      }
2195
94
    }
2196
12
    if (!flag)
2197
5
      mxTypeError("no initial value");
2198
12
  }
2199
216
  while (index > 0) {
2200
179
    index--;
2201
179
    fxReduceThisItem(the, function, index);
2202
179
  }
2203
37
}
2204
2205
void fx_Array_prototype_reverse(txMachine* the)
2206
34
{
2207
34
  txSlot* lowerSlot;
2208
34
  txSlot* upperSlot;
2209
34
  txNumber length = fxGetArrayLength(the, mxThis);
2210
34
  txNumber middle = c_trunc(length / 2);
2211
34
  txNumber lower = 0;
2212
968
  while (lower != middle) {
2213
934
    txNumber upper = length - lower - 1;
2214
934
    mxPushSlot(mxThis);
2215
934
    mxPushNumber(lower);
2216
934
    if (mxHasAt()) {
2217
53
      mxPushSlot(mxThis);
2218
53
      mxPushNumber(lower);
2219
53
      mxGetAt();
2220
53
      lowerSlot = the->stack;
2221
53
    }
2222
881
    else
2223
881
      lowerSlot = C_NULL;
2224
934
    mxPushSlot(mxThis);
2225
934
    mxPushNumber(upper);
2226
934
    if (mxHasAt()) {
2227
58
      mxPushSlot(mxThis);
2228
58
      mxPushNumber(upper);
2229
58
      mxGetAt();
2230
58
      upperSlot = the->stack;
2231
58
    }
2232
876
    else
2233
876
      upperSlot = C_NULL;
2234
934
    if (upperSlot && lowerSlot) {
2235
44
      mxPushSlot(upperSlot);
2236
44
      mxPushSlot(mxThis);
2237
44
      mxPushNumber(lower);
2238
44
      mxSetAt();
2239
44
      mxPop();
2240
44
      mxPushSlot(lowerSlot);
2241
44
      mxPushSlot(mxThis);
2242
44
      mxPushNumber(upper);
2243
44
      mxSetAt();
2244
44
      mxPop();
2245
44
      mxPop();
2246
44
      mxPop();
2247
44
    }
2248
890
    else if (upperSlot) {
2249
13
      mxPushSlot(upperSlot);
2250
13
      mxPushSlot(mxThis);
2251
13
      mxPushNumber(lower);
2252
13
      mxSetAt();
2253
13
      mxPop();
2254
13
      mxPushSlot(mxThis);
2255
13
      mxPushNumber(upper);
2256
13
      mxDeleteAt();
2257
13
      mxPop();
2258
13
      mxPop();
2259
13
    }
2260
877
    else if (lowerSlot) {
2261
9
      mxPushSlot(mxThis);
2262
9
      mxPushNumber(lower);
2263
9
      mxDeleteAt();
2264
9
      mxPop();
2265
9
      mxPushSlot(lowerSlot);
2266
9
      mxPushSlot(mxThis);
2267
9
      mxPushNumber(upper);
2268
9
      mxSetAt();
2269
9
      mxPop();
2270
9
      mxPop();
2271
9
    }
2272
934
    lower++;
2273
934
    mxCheckMetering();
2274
934
  }
2275
34
  *mxResult = *mxThis;
2276
34
}
2277
2278
void fx_Array_prototype_shift(txMachine* the)
2279
128
{
2280
128
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2281
128
  if (array)
2282
68
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
2283
128
  if (array) {
2284
68
    txIndex length = array->value.array.length;
2285
68
    txSlot* address;
2286
68
    mxMeterSome(2);
2287
68
    if (length > 0) {
2288
57
      mxMeterSome(3);
2289
57
      address = array->value.array.address;
2290
57
      length--;
2291
57
      mxResult->kind = address->kind;
2292
57
      mxResult->value = address->value;
2293
57
      c_memmove(address, address + 1, length * sizeof(txSlot));
2294
57
      fxSetIndexSize(the, array, length, XS_CHUNK);
2295
57
      fxIndexArray(the, array);
2296
57
      mxMeterSome(length * 10);
2297
57
      mxMeterSome(3);
2298
57
    }
2299
68
    mxMeterSome(4);
2300
68
  }
2301
60
  else {
2302
60
    txNumber length = fxGetArrayLength(the, mxThis);
2303
60
    if (length > 0) {
2304
39
      txNumber index = 1;
2305
39
      mxPushSlot(mxThis);
2306
39
      mxGetIndex(0);
2307
39
      mxPullSlot(mxResult);
2308
1.47M
      while (index < length) {
2309
1.47M
        mxPushSlot(mxThis);
2310
1.47M
        mxPushNumber(index);
2311
1.47M
        if (mxHasAt()) {
2312
36
          mxPushSlot(mxThis);
2313
36
          mxPushNumber(index);
2314
36
          mxGetAt();
2315
36
          mxPushSlot(mxThis);
2316
36
          mxPushNumber(index - 1);
2317
36
          mxSetAt();
2318
36
          mxPop();
2319
36
        }
2320
1.47M
        else {
2321
1.47M
          mxPushSlot(mxThis);
2322
1.47M
          mxPushNumber(index - 1);
2323
1.47M
          mxDeleteAt();
2324
1.47M
          mxPop();
2325
1.47M
        }
2326
1.47M
        index++;
2327
1.47M
        mxCheckMetering();
2328
1.47M
      }
2329
39
      length--;
2330
39
      mxPushSlot(mxThis);
2331
39
      mxDeleteIndex((txIndex)length);
2332
39
      mxPop();
2333
39
    }
2334
60
    mxPushNumber(length);
2335
60
    mxPushSlot(mxThis);
2336
60
    mxSetID(mxID(_length));
2337
60
    mxPop();
2338
60
  }
2339
128
}
2340
2341
void fx_Array_prototype_slice(txMachine* the)
2342
18.2k
{
2343
18.2k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2344
18.2k
  txNumber START = fxArgToIndex(the, 0, 0, LENGTH);
2345
18.2k
  txNumber END = fxArgToIndex(the, 1, LENGTH, LENGTH);
2346
18.2k
  txNumber COUNT = (END > START) ? END - START : 0;
2347
18.2k
  txSlot* resultArray = fxCreateArraySpecies(the, COUNT);
2348
18.2k
  txSlot* array = C_NULL;
2349
18.2k
  if (resultArray)
2350
18.2k
    array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2351
18.2k
  if (array)
2352
18.1k
    array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)(START + COUNT));
2353
18.2k
  if (array) {
2354
17.1k
    txIndex start = (txIndex)START;
2355
17.1k
    txIndex count = (txIndex)COUNT;
2356
17.1k
    if (count) {
2357
16.1k
      fxSetIndexSize(the, resultArray, count, XS_CHUNK);
2358
16.1k
      c_memcpy(resultArray->value.array.address, array->value.array.address + start, count * sizeof(txSlot));
2359
16.1k
      fxIndexArray(the, resultArray);
2360
16.1k
      mxMeterSome(count * 10);
2361
16.1k
    }
2362
17.1k
    mxMeterSome(3);
2363
17.1k
  }
2364
1.04k
  else {
2365
1.04k
    txNumber INDEX = 0;
2366
1.46M
    while (START < END) {
2367
1.46M
      mxPushSlot(mxThis);
2368
1.46M
      mxPushNumber(START);
2369
1.46M
      if (mxHasAt()) {
2370
528
        mxPushSlot(mxThis);
2371
528
        mxPushNumber(START);
2372
528
        mxGetAt();
2373
528
        mxPushSlot(mxResult);
2374
528
        mxPushNumber(INDEX);
2375
528
        mxDefineAt(0, XS_GET_ONLY);
2376
528
        mxPop();
2377
528
      }
2378
1.46M
      INDEX++;
2379
1.46M
      START++;
2380
1.46M
      mxCheckMetering();
2381
1.46M
    }
2382
1.04k
    mxPushNumber(COUNT);
2383
1.04k
    mxPushSlot(mxResult);
2384
1.04k
    mxSetID(mxID(_length));
2385
1.04k
  }
2386
18.2k
}
2387
2388
void fx_Array_prototype_some(txMachine* the)
2389
2.96k
{
2390
2.96k
  txIndex length = fxGetArrayLimit(the, mxThis);
2391
2.96k
  txIndex index = 0;
2392
2.96k
  txSlot* function = fxArgToCallback(the, 0);
2393
2.96k
  mxResult->kind = XS_BOOLEAN_KIND;
2394
2.96k
  mxResult->value.boolean = 0;
2395
1.00M
  while (index < length) {
2396
1.00M
    if (fxCallThisItem(the, function, index, C_NULL)) {
2397
440
      mxResult->value.boolean = fxToBoolean(the, the->stack);
2398
440
      mxPop();
2399
440
      if (mxResult->value.boolean)
2400
97
        break;
2401
440
    }
2402
1.00M
    index++;
2403
1.00M
    mxCheckMetering();
2404
1.00M
  }
2405
2.96k
}
2406
2407
2408
void fx_Array_prototype_sort(txMachine* the)
2409
239k
{
2410
239k
  txSlot* function = C_NULL;
2411
239k
  /*txSlot* array =*/ fxCheckArray(the, mxThis, XS_MUTABLE);
2412
239k
  if (mxArgc > 0) {
2413
66
    txSlot* slot = mxArgv(0);
2414
66
    if (slot->kind != XS_UNDEFINED_KIND) {
2415
63
      if (fxIsCallable(the, slot))
2416
21
        function = slot;
2417
42
      else
2418
42
        mxTypeError("compare: not a function");
2419
63
    }
2420
66
  }
2421
//  if (function)
2422
239k
    fxSortArrayItems(the, function, C_NULL, fxGetArrayLength(the, mxThis), mxThis);
2423
//  else {
2424
//    if (array)
2425
//      array = fxCheckArrayItems(the, array, 0, array->value.array.length);
2426
//    fxSortArrayItems(the, function, array, fxGetArrayLength(the, mxThis), mxThis);
2427
//  }
2428
239k
  mxResult->kind = mxThis->kind;
2429
239k
  mxResult->value = mxThis->value;
2430
239k
}
2431
2432
void fx_Array_prototype_splice(txMachine* the)
2433
240k
{
2434
240k
  txIndex c = (txIndex)mxArgc;
2435
240k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2436
240k
  txNumber START = fxArgToIndex(the, 0, 0, LENGTH);
2437
240k
  txNumber INSERTIONS, DELETIONS;
2438
240k
  txSlot* resultArray;
2439
240k
  txSlot* array = C_NULL;
2440
240k
  if (c == 0) {
2441
15
    INSERTIONS = 0;
2442
15
    DELETIONS = 0;
2443
15
  }
2444
240k
  else if (c == 1) {
2445
6.21k
    INSERTIONS = 0;
2446
6.21k
    DELETIONS = LENGTH - START;
2447
6.21k
  }
2448
234k
  else {
2449
234k
    INSERTIONS = c - 2;
2450
234k
    DELETIONS = fxArgToRange(the, 1, 0, 0, LENGTH - START);
2451
234k
  }
2452
240k
  if (LENGTH + INSERTIONS - DELETIONS > C_MAX_SAFE_INTEGER)
2453
11
    mxTypeError("unsafe integer");
2454
240k
  resultArray = fxCreateArraySpecies(the, DELETIONS);
2455
240k
  if (resultArray)
2456
240k
    array = fxCheckArray(the, mxThis, XS_MUTABLE);
2457
240k
  if (array) {
2458
228k
    if (INSERTIONS == DELETIONS)
2459
198k
      array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)(START + DELETIONS));
2460
30.3k
    else
2461
30.3k
      array = fxCheckArrayItems(the, array, (txIndex)START, (txIndex)LENGTH);
2462
228k
  }
2463
240k
  if (array) {
2464
228k
    txSlot* address;
2465
228k
    txIndex length = (txIndex)LENGTH;
2466
228k
    txIndex start = (txIndex)START;
2467
228k
    txIndex insertions = (txIndex)INSERTIONS;
2468
228k
    txIndex deletions = (txIndex)DELETIONS;
2469
228k
    txIndex index;
2470
228k
    if (LENGTH + INSERTIONS - DELETIONS > 0xFFFFFFFF)
2471
0
      mxTypeError("array overflow");
2472
228k
    fxSetIndexSize(the, resultArray, deletions, XS_CHUNK);
2473
228k
    c_memcpy(resultArray->value.array.address, array->value.array.address + start, deletions * sizeof(txSlot));
2474
228k
    fxIndexArray(the, resultArray);
2475
228k
    mxMeterSome(deletions * 10);
2476
228k
    mxMeterSome(4);
2477
228k
    if (insertions < deletions) {
2478
30.3k
      c_memmove(array->value.array.address + start + insertions, array->value.array.address + start + deletions, (length - (start + deletions)) * sizeof(txSlot));
2479
30.3k
      fxSetIndexSize(the, array, length - (deletions - insertions), XS_CHUNK);
2480
30.3k
      mxMeterSome((length - (start + deletions)) * 10);
2481
30.3k
      mxMeterSome((deletions - insertions) * 4);
2482
30.3k
    }
2483
198k
    else if (insertions > deletions) {
2484
5
      fxSetIndexSize(the, array, length + (insertions - deletions), XS_CHUNK);
2485
5
      c_memmove(array->value.array.address + start + insertions, array->value.array.address + start + deletions, (length - (start + deletions)) * sizeof(txSlot));
2486
5
      mxMeterSome((length - (start + deletions)) * 10);
2487
5
    }
2488
228k
    address = array->value.array.address + start;
2489
228k
    index = 2;
2490
228k
    while (index < c) {
2491
35
      txSlot* argument = mxArgv(index);
2492
35
      address->ID = XS_NO_ID;
2493
35
      address->kind = argument->kind;
2494
35
      address->value = argument->value;
2495
35
      address++;
2496
35
      mxMeterSome(5);
2497
35
      index++;
2498
35
      mxCheckMetering();
2499
35
    }
2500
228k
    fxIndexArray(the, array);
2501
228k
    mxMeterSome(4);
2502
228k
  }
2503
12.3k
  else { 
2504
12.3k
    txNumber INDEX = 0;
2505
18.0k
    while (INDEX < DELETIONS) {
2506
5.69k
      txNumber FROM = START + INDEX;
2507
5.69k
      mxPushSlot(mxThis);
2508
5.69k
      mxPushNumber(FROM);
2509
5.69k
      if (mxHasAt()) {
2510
858
        mxPushSlot(mxThis);
2511
858
        mxPushNumber(FROM);
2512
858
        mxGetAt();
2513
858
        mxPushSlot(mxResult);
2514
858
        mxPushNumber(INDEX);
2515
858
        mxDefineAt(0, XS_GET_ONLY);
2516
858
        mxPop();
2517
858
      }
2518
5.69k
      INDEX++;
2519
5.69k
      mxCheckMetering();
2520
5.69k
    }
2521
12.3k
    mxPushNumber(DELETIONS);
2522
12.3k
    mxPushSlot(mxResult);
2523
12.3k
    mxSetID(mxID(_length));
2524
12.3k
    mxPop();
2525
12.3k
    if (INSERTIONS < DELETIONS) {
2526
3.73k
      INDEX = START;
2527
2.91M
      while (INDEX < (LENGTH - DELETIONS)) {
2528
2.90M
        fxMoveThisItem(the, INDEX + DELETIONS, INDEX + INSERTIONS);
2529
2.90M
        INDEX++;
2530
2.90M
        mxCheckMetering();
2531
2.90M
      }
2532
3.73k
      INDEX = LENGTH;
2533
9.34k
      while (INDEX > (LENGTH - DELETIONS + INSERTIONS)) {
2534
5.60k
        mxPushSlot(mxThis);
2535
5.60k
        mxPushNumber(INDEX - 1);
2536
5.60k
        mxDeleteAt();
2537
5.60k
        mxPop();
2538
5.60k
        INDEX--;
2539
5.60k
        mxCheckMetering();
2540
5.60k
      }
2541
3.73k
    }
2542
8.64k
    else if (INSERTIONS > DELETIONS) {
2543
25
      INDEX = LENGTH - DELETIONS;
2544
2.62M
      while (INDEX > START) {
2545
2.62M
        fxMoveThisItem(the, INDEX + DELETIONS - 1, INDEX + INSERTIONS - 1);
2546
2.62M
        INDEX--;
2547
2.62M
        mxCheckMetering();
2548
2.62M
      }
2549
25
    }
2550
12.3k
    INDEX = 0;
2551
12.4k
    while (INDEX < INSERTIONS) {
2552
55
      mxPushSlot(mxArgv(2 + (txInteger)INDEX));
2553
55
      mxPushSlot(mxThis);
2554
55
      mxPushNumber(START + INDEX);
2555
55
      mxSetAt();
2556
55
      mxPop();
2557
55
      INDEX++;
2558
55
      mxCheckMetering();
2559
55
    }
2560
12.3k
    mxPushNumber(LENGTH - DELETIONS + INSERTIONS);
2561
12.3k
    mxPushSlot(mxThis);
2562
12.3k
    mxSetID(mxID(_length));
2563
12.3k
    mxPop();
2564
12.3k
  }
2565
240k
}
2566
2567
void fx_Array_prototype_toLocaleString(txMachine* the)
2568
108
{
2569
108
  txIndex length = fxGetArrayLimit(the, mxThis);
2570
108
  txIndex index = 0;
2571
108
  txString string;
2572
108
  txSlot* list = fxNewInstance(the);
2573
108
  txSlot* slot = list;
2574
108
  txBoolean comma = 0;
2575
108
  txInteger size = 0;
2576
    
2577
108
  mxPushStringX(",");
2578
108
  the->stack->kind += XS_KEY_KIND - XS_STRING_KIND;
2579
108
  the->stack->value.key.sum = 1;
2580
233
  while (index < length) {
2581
125
    if (comma) {
2582
24
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2583
24
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2584
24
    }
2585
101
    else
2586
101
      comma = 1;
2587
125
    mxPushSlot(mxThis);
2588
125
    mxGetIndex(index);
2589
125
    if ((the->stack->kind != XS_UNDEFINED_KIND) && (the->stack->kind != XS_NULL_KIND)) {
2590
44
      mxDub();
2591
44
      mxGetID(mxID(_toLocaleString));
2592
44
      mxCall();
2593
44
      mxRunCount(0);
2594
44
      slot = fxNextSlotProperty(the, slot, the->stack, XS_NO_ID, XS_NO_FLAG);
2595
44
      string = fxToString(the, slot);
2596
44
      slot->kind += XS_KEY_KIND - XS_STRING_KIND;
2597
44
      slot->value.key.sum = mxStringLength(string);
2598
44
      size = fxAddChunkSizes(the, size, slot->value.key.sum);
2599
44
    }
2600
125
    mxPop();
2601
125
    index++;
2602
    
2603
125
    mxCheckMetering();
2604
125
  }
2605
108
  string = mxResult->value.string = fxNewChunk(the, fxAddChunkSizes(the, size, 1));
2606
108
  slot = list->next;
2607
163
  while (slot) {
2608
55
    c_memcpy(string, slot->value.key.string, slot->value.key.sum);
2609
55
    string += slot->value.key.sum;
2610
55
    slot = slot->next;
2611
55
  }
2612
108
  *string = 0;
2613
108
  mxResult->kind = XS_STRING_KIND;
2614
108
  mxPop();
2615
108
}
2616
2617
void fx_Array_prototype_toReversed(txMachine* the)
2618
11
{
2619
11
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2620
11
  txIndex length, to, from;
2621
11
  if (LENGTH > 0xFFFFFFFF)
2622
1
    mxRangeError("array overflow");
2623
10
  length = (txIndex)LENGTH;
2624
10
  fxNewArray(the, length);
2625
10
  mxPullSlot(mxResult);
2626
10
  from = length - 1;
2627
10
  to = 0;
2628
76
  while (to < length) {
2629
66
    mxPushSlot(mxThis);
2630
66
    mxPushUnsigned(from);
2631
66
    mxGetAt();
2632
66
    mxPushSlot(mxResult);
2633
66
    mxPushUnsigned(to);
2634
66
    mxDefineAt(0, XS_GET_ONLY);
2635
66
    mxPop();
2636
66
    from--;
2637
66
    to++;
2638
66
    mxCheckMetering();
2639
66
  }
2640
10
}
2641
2642
void fx_Array_prototype_toSorted(txMachine* the)
2643
78.4k
{
2644
78.4k
  txSlot* function = C_NULL;
2645
78.4k
  txNumber LENGTH;
2646
78.4k
  if (mxArgc > 0) {
2647
78.4k
    txSlot* slot = mxArgv(0);
2648
78.4k
    if (slot->kind != XS_UNDEFINED_KIND) {
2649
44.0k
      if (fxIsCallable(the, slot))
2650
3
        function = slot;
2651
44.0k
      else
2652
44.0k
        mxTypeError("compare: not a function");
2653
44.0k
    }
2654
78.4k
  }
2655
34.4k
  LENGTH = fxGetArrayLength(the, mxThis);
2656
34.4k
  if (LENGTH > 0xFFFFFFFF)
2657
1
    mxRangeError("array overflow");
2658
34.4k
  fxNewArray(the, (txIndex)LENGTH);
2659
34.4k
  mxPullSlot(mxResult);
2660
34.4k
  fxSortArrayItems(the, function, C_NULL, LENGTH, mxResult);
2661
34.4k
}
2662
2663
void fx_Array_prototype_toSpliced(txMachine* the)
2664
866k
{
2665
866k
  txIndex c = (txIndex)mxArgc, i;
2666
866k
  txNumber LENGTH = fxGetArrayLength(the, mxThis);
2667
866k
  txNumber START = fxArgToIndex(the, 0, 0, LENGTH);
2668
866k
  txNumber INSERTIONS, SKIP, RESULT_LENGTH;
2669
866k
  txSlot* array = C_NULL;
2670
866k
  if (c == 0) {
2671
377k
    INSERTIONS = 0;
2672
377k
    SKIP = 0;
2673
377k
  }
2674
488k
  else if (c == 1) {
2675
294k
    INSERTIONS = 0;
2676
294k
    SKIP = LENGTH - START;
2677
294k
  }
2678
193k
  else {
2679
193k
    INSERTIONS = c - 2;
2680
193k
    SKIP = fxArgToRange(the, 1, 0, 0, LENGTH - START);
2681
193k
  }
2682
866k
  RESULT_LENGTH = LENGTH + INSERTIONS - SKIP;
2683
866k
  if (RESULT_LENGTH > C_MAX_SAFE_INTEGER)
2684
9
    mxTypeError("unsafe integer");
2685
866k
  if (RESULT_LENGTH > 0xFFFFFFFF)
2686
27
    mxRangeError("array overflow");
2687
866k
  array = fxCheckArray(the, mxThis, XS_IMMUTABLE);
2688
866k
  if (array)
2689
357k
    array = fxCheckArrayItems(the, array, (txIndex)0, (txIndex)START);
2690
866k
  if (array)
2691
357k
    array = fxCheckArrayItems(the, array, (txIndex)(START + SKIP), (txIndex)LENGTH);
2692
866k
  if (array) {
2693
357k
    txIndex length = (txIndex)LENGTH;
2694
357k
    txIndex start = (txIndex)START;
2695
357k
    txIndex skip = (txIndex)SKIP;
2696
357k
    txIndex rest = length - (start + skip);
2697
357k
    txSlot* resultArray;
2698
357k
    txSlot* resultAddress;
2699
357k
    txSlot* address;
2700
357k
    fxNewArray(the, (txIndex)RESULT_LENGTH);
2701
357k
    mxPullSlot(mxResult);
2702
357k
    resultArray = mxResult->value.reference->next;
2703
357k
    resultAddress = resultArray->value.array.address;
2704
357k
    address = array->value.array.address;
2705
357k
    if (start > 0) {
2706
124k
      c_memcpy(resultAddress, address, start * sizeof(txSlot));
2707
124k
      mxMeterSome(start * 10);
2708
124k
      resultAddress += start;
2709
124k
      address += start;
2710
124k
    }
2711
357k
    for (i = 2; i < c; i++) {
2712
30
      txSlot* argument = mxArgv(i);
2713
30
      resultAddress->ID = XS_NO_ID;
2714
30
      resultAddress->kind = argument->kind;
2715
30
      resultAddress->value = argument->value;
2716
30
      resultAddress++;
2717
30
      mxMeterSome(5);
2718
30
      mxCheckMetering();
2719
30
    }
2720
357k
    address += skip;
2721
357k
    if (rest > 0) {
2722
107k
      c_memcpy(resultAddress, address, rest * sizeof(txSlot));
2723
107k
      mxMeterSome(rest * 10);
2724
107k
    }
2725
357k
    fxIndexArray(the, resultArray);
2726
357k
    mxMeterSome(4);
2727
357k
  }
2728
508k
  else {
2729
508k
    txNumber from = 0;
2730
508k
    txNumber to = 0;
2731
508k
    fxNewArray(the, 0);
2732
508k
    mxPullSlot(mxResult);
2733
1.03M
    while (from < START) {
2734
521k
      mxPushSlot(mxThis);
2735
521k
      mxPushUnsigned(from);
2736
521k
      mxGetAt();
2737
521k
      mxPushSlot(mxResult);
2738
521k
      mxPushUnsigned(to);
2739
521k
      mxDefineAt(0, XS_GET_ONLY);
2740
521k
      mxPop();
2741
521k
      from++;
2742
521k
      to++;
2743
521k
      mxCheckMetering();
2744
521k
    }
2745
508k
    for (i = 2; i < c; i++) {
2746
44
      mxPushSlot(mxArgv(i));
2747
44
      mxPushSlot(mxResult);
2748
44
      mxPushNumber(to);
2749
44
      mxDefineAt(0, XS_GET_ONLY);
2750
44
      mxPop();
2751
44
      to++;
2752
44
      mxCheckMetering();
2753
44
    }
2754
508k
    from += SKIP;
2755
1.31M
    while (from < LENGTH) {
2756
809k
      mxPushSlot(mxThis);
2757
809k
      mxPushUnsigned(from);
2758
809k
      mxGetAt();
2759
809k
      mxPushSlot(mxResult);
2760
809k
      mxPushUnsigned(to);
2761
809k
      mxDefineAt(0, XS_GET_ONLY);
2762
809k
      mxPop();
2763
809k
      from++;
2764
809k
      to++;
2765
809k
      mxCheckMetering();
2766
809k
    }
2767
508k
  }
2768
866k
}
2769
2770
void fx_Array_prototype_toString(txMachine* the)
2771
7.79M
{
2772
7.79M
  mxPushSlot(mxThis);
2773
7.79M
  mxDub();
2774
7.79M
  mxGetID(mxID(_join));
2775
7.79M
  if (fxIsCallable(the, the->stack)) {
2776
7.79M
    mxCall();
2777
7.79M
    mxRunCount(0);
2778
7.79M
    mxPullSlot(mxResult);
2779
7.79M
  }
2780
47
  else {
2781
47
    mxPop();
2782
47
    mxPop();
2783
47
    fx_Object_prototype_toString(the);
2784
47
  }
2785
7.79M
}
2786
2787
void fx_Array_prototype_unshift(txMachine* the)
2788
85
{
2789
85
  txIndex c = mxArgc, i;
2790
85
  txSlot* array = fxCheckArray(the, mxThis, XS_MUTABLE);
2791
85
  if (array)
2792
16
    array = fxCheckArrayItems(the, array, 0, array->value.array.length);
2793
85
  if (array) {
2794
16
    txSlot* address;
2795
16
    txIndex length = array->value.array.length;
2796
16
    if (length + c < length)
2797
0
      mxRangeError("array overflow");
2798
16
    if (c > 0) {
2799
12
      fxSetIndexSize(the, array, length + c, XS_GROWABLE_CHUNK);
2800
12
      address = array->value.array.address;
2801
12
      c_memmove(address + c, address, length * sizeof(txSlot));
2802
12
      mxMeterSome(length * 10);
2803
12
      i = 0;
2804
31
      while (i < c) {
2805
19
        txSlot* argument = mxArgv(i);
2806
19
        address->ID = XS_NO_ID;
2807
19
        address->kind = argument->kind;
2808
19
        address->value = argument->value;
2809
19
        address++;
2810
19
        mxMeterSome(4);
2811
19
        i++;
2812
19
        mxCheckMetering();
2813
19
      }
2814
12
      fxIndexArray(the, array);
2815
12
    }
2816
16
    mxPushUnsigned(length + c);
2817
16
    mxMeterSome(2);
2818
16
  }
2819
69
  else {
2820
69
    txNumber length = fxGetArrayLength(the, mxThis);
2821
69
    txNumber index = length;
2822
69
    if (c > 0) {
2823
38
      if (length + c > C_MAX_SAFE_INTEGER)
2824
10
        mxTypeError("unsafe integer");
2825
19.9k
      while (index > 0) {
2826
19.8k
        fxMoveThisItem(the, index - 1, index + c - 1);
2827
19.8k
        index--;
2828
19.8k
        mxCheckMetering();
2829
19.8k
      }
2830
28
      i = 0;
2831
53
      while (i < c) {
2832
25
        mxPushSlot(mxArgv(i));
2833
25
        mxPushSlot(mxThis);
2834
25
        mxSetIndex(i);
2835
25
        mxPop();
2836
25
        i++;
2837
25
        mxCheckMetering();
2838
25
      }
2839
28
    }
2840
59
    mxPushNumber(length + c);
2841
59
    mxPushSlot(mxThis);
2842
59
    mxSetID(mxID(_length));
2843
59
  }
2844
75
  mxPullSlot(mxResult);
2845
75
}
2846
2847
void fx_Array_prototype_values(txMachine* the)
2848
324k
{
2849
324k
  txSlot* property;
2850
324k
  fxToInstance(the, mxThis);
2851
324k
  mxPush(mxArrayIteratorPrototype);
2852
324k
  property = fxLastProperty(the, fxNewIteratorInstance(the, mxThis, mxID(_Array)));
2853
324k
  property = fxNextIntegerProperty(the, property, 0, XS_NO_ID, XS_INTERNAL_FLAG);
2854
324k
  mxPullSlot(mxResult);
2855
324k
}
2856
2857
void fx_Array_prototype_with(txMachine* the)
2858
28.9k
{
2859
28.9k
  txNumber LENGTH = fxGetArrayLength(the, mxThis), INDEX;
2860
28.9k
  txIndex length, index, i;
2861
28.9k
  if (LENGTH > 0xFFFFFFFF)
2862
1
    mxRangeError("array overflow");
2863
28.9k
  INDEX = fxArgToRelativeIndex(the, 0, 0, LENGTH);
2864
28.9k
  if ((INDEX < 0) || (LENGTH <= INDEX))
2865
31
    mxRangeError("invalid index");
2866
28.9k
  length = (txIndex)LENGTH;
2867
28.9k
  fxNewArray(the, length);
2868
28.9k
  mxPullSlot(mxResult);
2869
28.9k
  index = (txIndex)INDEX;
2870
28.9k
  i = 0;
2871
44.0k
  while (i < index) {
2872
15.0k
    mxPushSlot(mxThis);
2873
15.0k
    mxPushUnsigned(i);
2874
15.0k
    mxGetAt();
2875
15.0k
    mxPushSlot(mxResult);
2876
15.0k
    mxPushUnsigned(i);
2877
15.0k
    mxDefineAt(0, XS_GET_ONLY);
2878
15.0k
    mxPop();
2879
15.0k
    i++;
2880
15.0k
    mxCheckMetering();
2881
15.0k
  }
2882
28.9k
  if (mxArgc > 1)
2883
2.08k
    mxPushSlot(mxArgv(1));
2884
26.8k
  else
2885
26.8k
    mxPushUndefined();
2886
28.9k
  mxPushSlot(mxResult);
2887
28.9k
  mxPushUnsigned(i);
2888
28.9k
  mxDefineAt(0, XS_GET_ONLY);
2889
28.9k
  mxPop();
2890
28.9k
  i++;
2891
1.17M
  while (i < length) {
2892
1.14M
    mxPushSlot(mxThis);
2893
1.14M
    mxPushUnsigned(i);
2894
1.14M
    mxGetAt();
2895
1.14M
    mxPushSlot(mxResult);
2896
1.14M
    mxPushUnsigned(i);
2897
1.14M
    mxDefineAt(0, XS_GET_ONLY);
2898
1.14M
    mxPop();
2899
1.14M
    i++;
2900
1.14M
    mxCheckMetering();
2901
1.14M
  }
2902
28.9k
}
2903
2904
void fx_ArrayIterator_prototype_next(txMachine* the)
2905
929k
{
2906
929k
  txSlot* iterator = fxCheckIteratorInstance(the, mxThis, mxID(_Array));
2907
929k
  txSlot* result = iterator->next;
2908
929k
  txSlot* iterable = result->next;
2909
929k
  txSlot* index = iterable->next;
2910
929k
  txSlot* value = fxCheckIteratorResult(the, result);
2911
929k
  txSlot* done = value->next;
2912
929k
  if (!done->value.boolean) {
2913
929k
    txInteger kind = index->next->value.integer;
2914
929k
    txIndex length = fxGetArrayLimit(the, iterable);
2915
929k
    txIndex i = (txIndex)index->value.integer;
2916
929k
    if (i < length) {
2917
619k
      switch(kind) {
2918
619k
      case 0: 
2919
619k
        mxPushSlot(iterable);
2920
619k
        mxGetIndex(i);
2921
619k
        mxPullSlot(value);
2922
619k
        break;
2923
6
      case 1:
2924
6
        mxPushUnsigned(i);
2925
6
        mxPullSlot(value);
2926
6
        break;
2927
6
      case 2:
2928
6
        mxPushUnsigned(i);
2929
6
        mxPushSlot(iterable);
2930
6
        mxGetIndex(i);
2931
6
        fxConstructArrayEntry(the, value);
2932
6
        break;
2933
619k
      }
2934
619k
            index->value.integer = i + 1;
2935
619k
    }
2936
310k
    else {
2937
310k
      value->kind = XS_UNDEFINED_KIND;
2938
310k
      done->value.boolean = 1;
2939
310k
    }
2940
929k
  }
2941
929k
  mxResult->kind = result->kind;
2942
929k
  mxResult->value = result->value;
2943
929k
}
2944