1f0d8c737550796131cc50397d979074d38198d7
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGOperations.h"
28
29 #include "ArrayConstructor.h"
30 #include "ButterflyInlines.h"
31 #include "ClonedArguments.h"
32 #include "CodeBlock.h"
33 #include "CommonSlowPaths.h"
34 #include "DFGDriver.h"
35 #include "DFGJITCode.h"
36 #include "DFGOSRExit.h"
37 #include "DFGThunks.h"
38 #include "DFGToFTLDeferredCompilationCallback.h"
39 #include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
40 #include "DFGWorklist.h"
41 #include "DefinePropertyAttributes.h"
42 #include "DirectArguments.h"
43 #include "FTLForOSREntryJITCode.h"
44 #include "FTLOSREntry.h"
45 #include "FrameTracers.h"
46 #include "HasOwnPropertyCache.h"
47 #include "HostCallReturnValue.h"
48 #include "Interpreter.h"
49 #include "JIT.h"
50 #include "JITExceptions.h"
51 #include "JSArrayInlines.h"
52 #include "JSCInlines.h"
53 #include "JSFixedArray.h"
54 #include "JSGenericTypedArrayViewConstructorInlines.h"
55 #include "JSGlobalObjectFunctions.h"
56 #include "JSLexicalEnvironment.h"
57 #include "JSMap.h"
58 #include "JSPropertyNameEnumerator.h"
59 #include "JSSet.h"
60 #include "ObjectConstructor.h"
61 #include "Operations.h"
62 #include "ParseInt.h"
63 #include "RegExpObject.h"
64 #include "Repatch.h"
65 #include "ScopedArguments.h"
66 #include "StringConstructor.h"
67 #include "SuperSampler.h"
68 #include "Symbol.h"
69 #include "TypeProfilerLog.h"
70 #include "TypedArrayInlines.h"
71 #include "VMInlines.h"
72 #include <wtf/InlineASM.h>
73
74 #if ENABLE(JIT)
75 #if ENABLE(DFG_JIT)
76
77 namespace JSC { namespace DFG {
78
79 template<bool strict, bool direct>
80 static inline void putByVal(ExecState* exec, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
81 {
82     ASSERT(isIndex(index));
83     if (direct) {
84         RELEASE_ASSERT(baseValue.isObject());
85         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
86         return;
87     }
88     if (baseValue.isObject()) {
89         JSObject* object = asObject(baseValue);
90         if (object->canSetIndexQuickly(index)) {
91             object->setIndexQuickly(vm, index, value);
92             return;
93         }
94
95         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
96         return;
97     }
98
99     baseValue.putByIndex(exec, index, value, strict);
100 }
101
102 template<bool strict, bool direct>
103 ALWAYS_INLINE static void putByValInternal(ExecState* exec, VM& vm, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
104 {
105     auto scope = DECLARE_THROW_SCOPE(vm);
106
107     JSValue baseValue = JSValue::decode(encodedBase);
108     JSValue property = JSValue::decode(encodedProperty);
109     JSValue value = JSValue::decode(encodedValue);
110
111     if (LIKELY(property.isUInt32())) {
112         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
113         ASSERT(isIndex(property.asUInt32()));
114         scope.release();
115         putByVal<strict, direct>(exec, vm, baseValue, property.asUInt32(), value);
116         return;
117     }
118
119     if (property.isDouble()) {
120         double propertyAsDouble = property.asDouble();
121         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
122         if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
123             scope.release();
124             putByVal<strict, direct>(exec, vm, baseValue, propertyAsUInt32, value);
125             return;
126         }
127     }
128
129     // Don't put to an object if toString throws an exception.
130     auto propertyName = property.toPropertyKey(exec);
131     RETURN_IF_EXCEPTION(scope, void());
132
133     PutPropertySlot slot(baseValue, strict);
134     if (direct) {
135         RELEASE_ASSERT(baseValue.isObject());
136         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
137             scope.release();
138             asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
139             return;
140         }
141         asObject(baseValue)->putDirect(vm, propertyName, value, slot);
142         return;
143     }
144     scope.release();
145     baseValue.put(exec, propertyName, value, slot);
146 }
147
148 template<bool strict, bool direct>
149 ALWAYS_INLINE static void putByValCellInternal(ExecState* exec, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
150 {
151     PutPropertySlot slot(base, strict);
152     if (direct) {
153         RELEASE_ASSERT(base->isObject());
154         if (std::optional<uint32_t> index = parseIndex(propertyName))
155             asObject(base)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
156         else
157             asObject(base)->putDirect(vm, propertyName, value, slot);
158         return;
159     }
160     base->putInline(exec, propertyName, value, slot);
161 }
162
163 template<bool strict, bool direct>
164 ALWAYS_INLINE static void putByValCellStringInternal(ExecState* exec, VM& vm, JSCell* base, JSString* property, JSValue value)
165 {
166     auto scope = DECLARE_THROW_SCOPE(vm);
167
168     auto propertyName = property->toIdentifier(exec);
169     RETURN_IF_EXCEPTION(scope, void());
170
171     scope.release();
172     putByValCellInternal<strict, direct>(exec, vm, base, propertyName, value);
173 }
174
175 template<typename ViewClass>
176 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
177 {
178     VM& vm = exec->vm();
179     NativeCallFrameTracer tracer(&vm, exec);
180     auto scope = DECLARE_THROW_SCOPE(vm);
181
182     if (size < 0) {
183         throwException(exec, scope, createRangeError(exec, ASCIILiteral("Requested length is negative")));
184         return 0;
185     }
186     
187     if (vector)
188         return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
189
190     scope.release();
191     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
192 }
193
194 template <bool strict>
195 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
196 {
197     JSValue baseValue = JSValue::decode(encodedBase);
198     JSValue thisVal = JSValue::decode(encodedThis);
199     JSValue putValue = JSValue::decode(encodedValue);
200     PutPropertySlot slot(thisVal, strict);
201     baseValue.putInline(exec, ident, putValue, slot);
202 }
203
204 static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
205 {
206     int asInt = static_cast<int>(input);
207     if (static_cast<double>(asInt) == input)
208         return JSValue::encode(jsNumber(asInt));
209     return JSValue::encode(jsNumber(input));
210 }
211
212 ALWAYS_INLINE static JSValue getByValObject(ExecState* exec, VM& vm, JSObject* base, PropertyName propertyName)
213 {
214     Structure& structure = *base->structure(vm);
215     if (JSCell::canUseFastGetOwnProperty(structure)) {
216         if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
217             return result;
218     }
219     return base->get(exec, propertyName);
220 }
221
222 extern "C" {
223
224 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
225 {
226     VM* vm = &exec->vm();
227     NativeCallFrameTracer tracer(vm, exec);
228
229     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
230 }
231
232 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
233 {
234     VM* vm = &exec->vm();
235     NativeCallFrameTracer tracer(vm, exec);
236
237     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
238 }
239
240 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
241 {
242     VM& vm = exec->vm();
243     NativeCallFrameTracer tracer(&vm, exec);
244     auto scope = DECLARE_THROW_SCOPE(vm);
245     if (constructor->type() == JSFunctionType) {
246         auto rareData = jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity);
247         RETURN_IF_EXCEPTION(scope, nullptr);
248         Structure* structure = rareData->objectAllocationProfile()->structure();
249         JSObject* result = constructEmptyObject(exec, structure);
250         if (structure->hasPolyProto()) {
251             JSObject* prototype = jsCast<JSFunction*>(constructor)->prototypeForConstruction(vm, exec);
252             result->putDirect(vm, knownPolyProtoOffset, prototype);
253             prototype->didBecomePrototype();
254             ASSERT_WITH_MESSAGE(!hasIndexedProperties(result->indexingType()), "We rely on JSFinalObject not starting out with an indexing type otherwise we would potentially need to convert to slow put storage");
255         }
256         return result;
257     }
258
259     JSValue proto = constructor->get(exec, vm.propertyNames->prototype);
260     RETURN_IF_EXCEPTION(scope, nullptr);
261     if (proto.isObject())
262         return constructEmptyObject(exec, asObject(proto));
263     return constructEmptyObject(exec);
264 }
265
266 JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
267 {
268     VM* vm = &exec->vm();
269     NativeCallFrameTracer tracer(vm, exec);
270
271     JSValue value = JSValue::decode(encodedTarget);
272     ASSERT(!value.isObject());
273
274     if (value.isUndefinedOrNull())
275         return constructEmptyObject(exec, globalObject->objectPrototype());
276     return value.toObject(exec, globalObject);
277 }
278
279 JSCell* JIT_OPERATION operationToObject(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget, UniquedStringImpl* errorMessage)
280 {
281     VM* vm = &exec->vm();
282     NativeCallFrameTracer tracer(vm, exec);
283     auto scope = DECLARE_THROW_SCOPE(*vm);
284
285     JSValue value = JSValue::decode(encodedTarget);
286     ASSERT(!value.isObject());
287
288     if (UNLIKELY(value.isUndefinedOrNull())) {
289         if (errorMessage->length()) {
290             throwVMTypeError(exec, scope, errorMessage);
291             return nullptr;
292         }
293     }
294
295     scope.release();
296     return value.toObject(exec, globalObject);
297 }
298
299 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
300 {
301     VM* vm = &exec->vm();
302     NativeCallFrameTracer tracer(vm, exec);
303     auto scope = DECLARE_THROW_SCOPE(*vm);
304
305     JSValue op1 = JSValue::decode(encodedOp1);
306     JSValue op2 = JSValue::decode(encodedOp2);
307
308     int32_t a = op1.toInt32(exec);
309     RETURN_IF_EXCEPTION(scope, encodedJSValue());
310     scope.release();
311     int32_t b = op2.toInt32(exec);
312     return JSValue::encode(jsNumber(a & b));
313 }
314
315 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
316 {
317     VM* vm = &exec->vm();
318     NativeCallFrameTracer tracer(vm, exec);
319     auto scope = DECLARE_THROW_SCOPE(*vm);
320
321     JSValue op1 = JSValue::decode(encodedOp1);
322     JSValue op2 = JSValue::decode(encodedOp2);
323
324     int32_t a = op1.toInt32(exec);
325     RETURN_IF_EXCEPTION(scope, encodedJSValue());
326     scope.release();
327     int32_t b = op2.toInt32(exec);
328     return JSValue::encode(jsNumber(a | b));
329 }
330
331 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
332 {
333     VM* vm = &exec->vm();
334     NativeCallFrameTracer tracer(vm, exec);
335     auto scope = DECLARE_THROW_SCOPE(*vm);
336
337     JSValue op1 = JSValue::decode(encodedOp1);
338     JSValue op2 = JSValue::decode(encodedOp2);
339
340     int32_t a = op1.toInt32(exec);
341     RETURN_IF_EXCEPTION(scope, encodedJSValue());
342     scope.release();
343     int32_t b = op2.toInt32(exec);
344     return JSValue::encode(jsNumber(a ^ b));
345 }
346
347 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
348 {
349     VM* vm = &exec->vm();
350     NativeCallFrameTracer tracer(vm, exec);
351     auto scope = DECLARE_THROW_SCOPE(*vm);
352
353     JSValue op1 = JSValue::decode(encodedOp1);
354     JSValue op2 = JSValue::decode(encodedOp2);
355
356     int32_t a = op1.toInt32(exec);
357     RETURN_IF_EXCEPTION(scope, encodedJSValue());
358     scope.release();
359     uint32_t b = op2.toUInt32(exec);
360     return JSValue::encode(jsNumber(a << (b & 0x1f)));
361 }
362
363 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
364 {
365     VM* vm = &exec->vm();
366     NativeCallFrameTracer tracer(vm, exec);
367     auto scope = DECLARE_THROW_SCOPE(*vm);
368
369     JSValue op1 = JSValue::decode(encodedOp1);
370     JSValue op2 = JSValue::decode(encodedOp2);
371
372     int32_t a = op1.toInt32(exec);
373     RETURN_IF_EXCEPTION(scope, encodedJSValue());
374     scope.release();
375     uint32_t b = op2.toUInt32(exec);
376     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
377 }
378
379 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
380 {
381     VM* vm = &exec->vm();
382     NativeCallFrameTracer tracer(vm, exec);
383     auto scope = DECLARE_THROW_SCOPE(*vm);
384
385     JSValue op1 = JSValue::decode(encodedOp1);
386     JSValue op2 = JSValue::decode(encodedOp2);
387
388     uint32_t a = op1.toUInt32(exec);
389     RETURN_IF_EXCEPTION(scope, encodedJSValue());
390     scope.release();
391     uint32_t b = op2.toUInt32(exec);
392     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
393 }
394
395 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
396 {
397     VM* vm = &exec->vm();
398     NativeCallFrameTracer tracer(vm, exec);
399     
400     JSValue op1 = JSValue::decode(encodedOp1);
401     JSValue op2 = JSValue::decode(encodedOp2);
402     
403     ASSERT(!op1.isNumber() || !op2.isNumber());
404     
405     if (op1.isString() && !op2.isObject())
406         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
407
408     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
409 }
410
411 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
412 {
413     VM* vm = &exec->vm();
414     NativeCallFrameTracer tracer(vm, exec);
415     auto scope = DECLARE_THROW_SCOPE(*vm);
416
417     JSValue op1 = JSValue::decode(encodedOp1);
418     JSValue op2 = JSValue::decode(encodedOp2);
419
420     double a = op1.toNumber(exec);
421     RETURN_IF_EXCEPTION(scope, encodedJSValue());
422     scope.release();
423     double b = op2.toNumber(exec);
424     return JSValue::encode(jsNumber(a / b));
425 }
426
427 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
428 {
429     VM* vm = &exec->vm();
430     NativeCallFrameTracer tracer(vm, exec);
431     auto scope = DECLARE_THROW_SCOPE(*vm);
432
433     JSValue op1 = JSValue::decode(encodedOp1);
434     double a = op1.toNumber(exec);
435     RETURN_IF_EXCEPTION(scope, PNaN);
436     return fabs(a);
437 }
438
439 int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
440 {
441     VM* vm = &exec->vm();
442     NativeCallFrameTracer tracer(vm, exec);
443     auto scope = DECLARE_THROW_SCOPE(*vm);
444
445     JSValue op1 = JSValue::decode(encodedOp1);
446     uint32_t value = op1.toUInt32(exec);
447     RETURN_IF_EXCEPTION(scope, 0);
448     return clz32(value);
449 }
450
451 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
452 {
453     VM* vm = &exec->vm();
454     NativeCallFrameTracer tracer(vm, exec);
455     auto scope = DECLARE_THROW_SCOPE(*vm);
456
457     JSValue op1 = JSValue::decode(encodedOp1);
458     double a = op1.toNumber(exec);
459     RETURN_IF_EXCEPTION(scope, PNaN);
460     return static_cast<float>(a);
461 }
462
463 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
464 double JIT_OPERATION operationArith##capitalizedName(ExecState* exec, EncodedJSValue encodedOp1) \
465 { \
466     VM* vm = &exec->vm(); \
467     NativeCallFrameTracer tracer(vm, exec); \
468     auto scope = DECLARE_THROW_SCOPE(*vm); \
469     JSValue op1 = JSValue::decode(encodedOp1); \
470     double result = op1.toNumber(exec); \
471     RETURN_IF_EXCEPTION(scope, PNaN); \
472     return JSC::Math::lowerName(result); \
473 }
474     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
475 #undef DFG_ARITH_UNARY
476
477 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
478 {
479     VM* vm = &exec->vm();
480     NativeCallFrameTracer tracer(vm, exec);
481     auto scope = DECLARE_THROW_SCOPE(*vm);
482
483     JSValue op1 = JSValue::decode(encodedOp1);
484     double a = op1.toNumber(exec);
485     RETURN_IF_EXCEPTION(scope, PNaN);
486     return sqrt(a);
487 }
488
489 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
490 {
491     VM* vm = &exec->vm();
492     NativeCallFrameTracer tracer(vm, exec);
493     auto scope = DECLARE_THROW_SCOPE(*vm);
494
495     JSValue argument = JSValue::decode(encodedArgument);
496     double valueOfArgument = argument.toNumber(exec);
497     RETURN_IF_EXCEPTION(scope, encodedJSValue());
498     return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
499 }
500
501 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
502 {
503     VM* vm = &exec->vm();
504     NativeCallFrameTracer tracer(vm, exec);
505     auto scope = DECLARE_THROW_SCOPE(*vm);
506
507     JSValue argument = JSValue::decode(encodedArgument);
508     double valueOfArgument = argument.toNumber(exec);
509     RETURN_IF_EXCEPTION(scope, encodedJSValue());
510     return JSValue::encode(jsNumber(floor(valueOfArgument)));
511 }
512
513 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
514 {
515     VM* vm = &exec->vm();
516     NativeCallFrameTracer tracer(vm, exec);
517     auto scope = DECLARE_THROW_SCOPE(*vm);
518
519     JSValue argument = JSValue::decode(encodedArgument);
520     double valueOfArgument = argument.toNumber(exec);
521     RETURN_IF_EXCEPTION(scope, encodedJSValue());
522     return JSValue::encode(jsNumber(ceil(valueOfArgument)));
523 }
524
525 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
526 {
527     VM* vm = &exec->vm();
528     NativeCallFrameTracer tracer(vm, exec);
529     auto scope = DECLARE_THROW_SCOPE(*vm);
530
531     JSValue argument = JSValue::decode(encodedArgument);
532     double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
533     RETURN_IF_EXCEPTION(scope, encodedJSValue());
534     return JSValue::encode(jsNumber(truncatedValueOfArgument));
535 }
536
537 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
538 {
539     VM& vm = exec->vm();
540     NativeCallFrameTracer tracer(&vm, exec);
541     
542     if (base->isObject()) {
543         JSObject* object = asObject(base);
544         if (object->canGetIndexQuickly(index))
545             return JSValue::encode(object->getIndexQuickly(index));
546     }
547
548     if (isJSString(base) && asString(base)->canGetIndex(index))
549         return JSValue::encode(asString(base)->getIndex(exec, index));
550
551     return JSValue::encode(JSValue(base).get(exec, index));
552 }
553
554 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
555 {
556     VM& vm = exec->vm();
557     NativeCallFrameTracer tracer(&vm, exec);
558     auto scope = DECLARE_THROW_SCOPE(vm);
559
560     JSValue baseValue = JSValue::decode(encodedBase);
561     JSValue property = JSValue::decode(encodedProperty);
562
563     if (LIKELY(baseValue.isCell())) {
564         JSCell* base = baseValue.asCell();
565
566         if (property.isUInt32()) {
567             scope.release();
568             return getByVal(exec, base, property.asUInt32());
569         }
570         if (property.isDouble()) {
571             double propertyAsDouble = property.asDouble();
572             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
573             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) {
574                 scope.release();
575                 return getByVal(exec, base, propertyAsUInt32);
576             }
577         } else if (property.isString()) {
578             Structure& structure = *base->structure(vm);
579             if (JSCell::canUseFastGetOwnProperty(structure)) {
580                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
581                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
582                         return JSValue::encode(result);
583                 }
584             }
585         }
586     }
587
588     baseValue.requireObjectCoercible(exec);
589     RETURN_IF_EXCEPTION(scope, encodedJSValue());
590     auto propertyName = property.toPropertyKey(exec);
591     RETURN_IF_EXCEPTION(scope, encodedJSValue());
592     scope.release();
593     return JSValue::encode(baseValue.get(exec, propertyName));
594 }
595
596 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
597 {
598     VM& vm = exec->vm();
599     NativeCallFrameTracer tracer(&vm, exec);
600     auto scope = DECLARE_THROW_SCOPE(vm);
601
602     JSValue property = JSValue::decode(encodedProperty);
603
604     if (property.isUInt32()) {
605         scope.release();
606         return getByVal(exec, base, property.asUInt32());
607     }
608     if (property.isDouble()) {
609         double propertyAsDouble = property.asDouble();
610         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
611         if (propertyAsUInt32 == propertyAsDouble) {
612             scope.release();
613             return getByVal(exec, base, propertyAsUInt32);
614         }
615     } else if (property.isString()) {
616         Structure& structure = *base->structure(vm);
617         if (JSCell::canUseFastGetOwnProperty(structure)) {
618             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
619                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
620                     return JSValue::encode(result);
621             }
622         }
623     }
624
625     auto propertyName = property.toPropertyKey(exec);
626     RETURN_IF_EXCEPTION(scope, encodedJSValue());
627     scope.release();
628     return JSValue::encode(JSValue(base).get(exec, propertyName));
629 }
630
631 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
632 {
633     VM* vm = &exec->vm();
634     NativeCallFrameTracer tracer(vm, exec);
635     
636     if (index < 0) {
637         // Go the slowest way possible because negative indices don't use indexed storage.
638         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
639     }
640
641     // Use this since we know that the value is out of bounds.
642     return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
643 }
644
645 EncodedJSValue JIT_OPERATION operationGetByValObjectInt(ExecState* exec, JSObject* base, int32_t index)
646 {
647     return getByValCellInt(exec, base, index);
648 }
649
650 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
651 {
652     return getByValCellInt(exec, base, index);
653 }
654
655 EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState* exec, JSCell* base, JSCell* string)
656 {
657     VM& vm = exec->vm();
658     NativeCallFrameTracer tracer(&vm, exec);
659
660     auto scope = DECLARE_THROW_SCOPE(vm);
661
662     auto propertyName = asString(string)->toIdentifier(exec);
663     RETURN_IF_EXCEPTION(scope, encodedJSValue());
664
665     scope.release();
666     return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
667 }
668
669 EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState* exec, JSCell* base, JSCell* symbol)
670 {
671     VM& vm = exec->vm();
672     NativeCallFrameTracer tracer(&vm, exec);
673
674     return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
675 }
676
677 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
678 {
679     VM& vm = exec->vm();
680     NativeCallFrameTracer tracer(&vm, exec);
681     
682     putByValInternal<true, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
683 }
684
685 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
686 {
687     VM& vm = exec->vm();
688     NativeCallFrameTracer tracer(&vm, exec);
689     
690     putByValInternal<false, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
691 }
692
693 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
694 {
695     VM& vm = exec->vm();
696     NativeCallFrameTracer tracer(&vm, exec);
697     
698     putByValInternal<true, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
699 }
700
701 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
702 {
703     VM& vm = exec->vm();
704     NativeCallFrameTracer tracer(&vm, exec);
705     
706     putByValInternal<false, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
707 }
708
709 void JIT_OPERATION operationPutByValCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
710 {
711     VM& vm = exec->vm();
712     NativeCallFrameTracer tracer(&vm, exec);
713
714     putByValCellStringInternal<true, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
715 }
716
717 void JIT_OPERATION operationPutByValCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
718 {
719     VM& vm = exec->vm();
720     NativeCallFrameTracer tracer(&vm, exec);
721
722     putByValCellStringInternal<false, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
723 }
724
725 void JIT_OPERATION operationPutByValCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
726 {
727     VM& vm = exec->vm();
728     NativeCallFrameTracer tracer(&vm, exec);
729
730     putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
731 }
732
733 void JIT_OPERATION operationPutByValCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
734 {
735     VM& vm = exec->vm();
736     NativeCallFrameTracer tracer(&vm, exec);
737
738     putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
739 }
740
741 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
742 {
743     VM& vm = exec->vm();
744     NativeCallFrameTracer tracer(&vm, exec);
745     
746     if (index >= 0) {
747         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
748         return;
749     }
750     
751     PutPropertySlot slot(array, true);
752     array->methodTable(vm)->put(
753         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
754 }
755
756 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
757 {
758     VM* vm = &exec->vm();
759     NativeCallFrameTracer tracer(vm, exec);
760     
761     if (index >= 0) {
762         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
763         return;
764     }
765     
766     PutPropertySlot slot(array, false);
767     array->methodTable(*vm)->put(
768         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
769 }
770
771 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
772 {
773     VM* vm = &exec->vm();
774     NativeCallFrameTracer tracer(vm, exec);
775     
776     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
777     
778     if (index >= 0) {
779         array->putByIndexInline(exec, index, jsValue, true);
780         return;
781     }
782     
783     PutPropertySlot slot(array, true);
784     array->methodTable(*vm)->put(
785         array, exec, Identifier::from(exec, index), jsValue, slot);
786 }
787
788 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
789 {
790     VM* vm = &exec->vm();
791     NativeCallFrameTracer tracer(vm, exec);
792     
793     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
794     
795     if (index >= 0) {
796         array->putByIndexInline(exec, index, jsValue, false);
797         return;
798     }
799     
800     PutPropertySlot slot(array, false);
801     array->methodTable(*vm)->put(
802         array, exec, Identifier::from(exec, index), jsValue, slot);
803 }
804
805 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
806 {
807     VM& vm = exec->vm();
808     NativeCallFrameTracer tracer(&vm, exec);
809     
810     putByValInternal<true, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
811 }
812
813 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
814 {
815     VM& vm = exec->vm();
816     NativeCallFrameTracer tracer(&vm, exec);
817     
818     putByValInternal<false, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
819 }
820
821 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
822 {
823     VM& vm = exec->vm();
824     NativeCallFrameTracer tracer(&vm, exec);
825     
826     putByValInternal<true, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
827 }
828
829 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
830 {
831     VM& vm = exec->vm();
832     NativeCallFrameTracer tracer(&vm, exec);
833     
834     putByValInternal<false, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
835 }
836
837 void JIT_OPERATION operationPutByValDirectCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
838 {
839     VM& vm = exec->vm();
840     NativeCallFrameTracer tracer(&vm, exec);
841
842     putByValCellStringInternal<true, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
843 }
844
845 void JIT_OPERATION operationPutByValDirectCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
846 {
847     VM& vm = exec->vm();
848     NativeCallFrameTracer tracer(&vm, exec);
849
850     putByValCellStringInternal<false, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
851 }
852
853 void JIT_OPERATION operationPutByValDirectCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
854 {
855     VM& vm = exec->vm();
856     NativeCallFrameTracer tracer(&vm, exec);
857
858     putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
859 }
860
861 void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
862 {
863     VM& vm = exec->vm();
864     NativeCallFrameTracer tracer(&vm, exec);
865
866     putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
867 }
868
869 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
870 {
871     VM& vm = exec->vm();
872     NativeCallFrameTracer tracer(&vm, exec);
873     if (index >= 0) {
874         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
875         return;
876     }
877     
878     PutPropertySlot slot(array, true);
879     array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
880 }
881
882 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
883 {
884     VM& vm = exec->vm();
885     NativeCallFrameTracer tracer(&vm, exec);
886     
887     if (index >= 0) {
888         array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
889         return;
890     }
891     
892     PutPropertySlot slot(array, false);
893     array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
894 }
895
896 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
897 {
898     VM* vm = &exec->vm();
899     NativeCallFrameTracer tracer(vm, exec);
900     
901     array->pushInline(exec, JSValue::decode(encodedValue));
902     return JSValue::encode(jsNumber(array->length()));
903 }
904
905 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
906 {
907     VM* vm = &exec->vm();
908     NativeCallFrameTracer tracer(vm, exec);
909     
910     array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, value));
911     return JSValue::encode(jsNumber(array->length()));
912 }
913
914 EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
915 {
916     VM& vm = exec->vm();
917     NativeCallFrameTracer tracer(&vm, exec);
918     auto scope = DECLARE_THROW_SCOPE(vm);
919
920     // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
921     // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
922     // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure
923     // that there is no indexed accessors in this object and its prototype chain.
924     //
925     // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length
926     // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless
927     // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain.
928     RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType()));
929
930     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
931     for (int32_t i = 0; i < elementCount; ++i) {
932         array->pushInline(exec, JSValue::decode(values[i]));
933         RETURN_IF_EXCEPTION(scope, encodedJSValue());
934     }
935     return JSValue::encode(jsNumber(array->length()));
936 }
937
938 EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
939 {
940     VM& vm = exec->vm();
941     NativeCallFrameTracer tracer(&vm, exec);
942     auto scope = DECLARE_THROW_SCOPE(vm);
943
944     // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
945     // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
946     // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure
947     // that there is no indexed accessors in this object and its prototype chain.
948     ASSERT(array->indexingType() == ArrayWithDouble);
949
950     double* values = static_cast<double*>(buffer);
951     for (int32_t i = 0; i < elementCount; ++i) {
952         array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, values[i]));
953         RETURN_IF_EXCEPTION(scope, encodedJSValue());
954     }
955     return JSValue::encode(jsNumber(array->length()));
956 }
957
958 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
959 {
960     VM* vm = &exec->vm();
961     NativeCallFrameTracer tracer(vm, exec);
962     
963     return JSValue::encode(array->pop(exec));
964 }
965         
966 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
967 {
968     VM* vm = &exec->vm();
969     NativeCallFrameTracer tracer(vm, exec);
970     
971     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
972     
973     return JSValue::encode(array->pop(exec));
974 }
975         
976 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
977 {
978     SuperSamplerScope superSamplerScope(false);
979     
980     VM& vm = globalObject->vm();
981     NativeCallFrameTracer tracer(&vm, exec);
982     
983     return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
984 }
985         
986 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
987 {
988     SuperSamplerScope superSamplerScope(false);
989     
990     VM& vm = globalObject->vm();
991     NativeCallFrameTracer tracer(&vm, exec);
992     auto scope = DECLARE_THROW_SCOPE(vm);
993     
994     JSValue argument = JSValue::decode(encodedArgument);
995
996     JSString* input = argument.toStringOrNull(exec);
997     EXCEPTION_ASSERT(!!scope.exception() == !input);
998     if (!input)
999         return encodedJSValue();
1000     scope.release();
1001     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
1002 }
1003         
1004 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1005 {
1006     SuperSamplerScope superSamplerScope(false);
1007     
1008     VM& vm = globalObject->vm();
1009     NativeCallFrameTracer tracer(&vm, exec);
1010     auto scope = DECLARE_THROW_SCOPE(vm);
1011
1012     JSValue base = JSValue::decode(encodedBase);
1013     JSValue argument = JSValue::decode(encodedArgument);
1014     
1015     if (!base.inherits(vm, RegExpObject::info()))
1016         return throwVMTypeError(exec, scope);
1017
1018     JSString* input = argument.toStringOrNull(exec);
1019     EXCEPTION_ASSERT(!!scope.exception() == !input);
1020     if (!input)
1021         return JSValue::encode(jsUndefined());
1022     scope.release();
1023     return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
1024 }
1025
1026 EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
1027 {
1028     VM& vm = exec->vm();
1029     NativeCallFrameTracer tracer(&vm, exec);
1030
1031     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1032         // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1033         return parseIntResult(parseInt(view, 0));
1034     });
1035 }
1036
1037 EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(ExecState* exec, JSString* string)
1038 {
1039     VM& vm = exec->vm();
1040     NativeCallFrameTracer tracer(&vm, exec);
1041     auto scope = DECLARE_THROW_SCOPE(vm);
1042
1043     auto viewWithString = string->viewWithUnderlyingString(exec);
1044     RETURN_IF_EXCEPTION(scope, { });
1045
1046     // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1047     return parseIntResult(parseInt(viewWithString.view, 0));
1048 }
1049
1050 EncodedJSValue JIT_OPERATION operationParseIntString(ExecState* exec, JSString* string, int32_t radix)
1051 {
1052     VM& vm = exec->vm();
1053     NativeCallFrameTracer tracer(&vm, exec);
1054     auto scope = DECLARE_THROW_SCOPE(vm);
1055
1056     auto viewWithString = string->viewWithUnderlyingString(exec);
1057     RETURN_IF_EXCEPTION(scope, { });
1058
1059     return parseIntResult(parseInt(viewWithString.view, radix));
1060 }
1061
1062 EncodedJSValue JIT_OPERATION operationParseIntGeneric(ExecState* exec, EncodedJSValue value, int32_t radix)
1063 {
1064     VM& vm = exec->vm();
1065     NativeCallFrameTracer tracer(&vm, exec);
1066
1067     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1068         return parseIntResult(parseInt(view, radix));
1069     });
1070 }
1071         
1072 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1073 {
1074     SuperSamplerScope superSamplerScope(false);
1075     
1076     VM& vm = globalObject->vm();
1077     NativeCallFrameTracer tracer(&vm, exec);
1078
1079     return regExpObject->testInline(exec, globalObject, input);
1080 }
1081
1082 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1083 {
1084     SuperSamplerScope superSamplerScope(false);
1085     
1086     VM& vm = globalObject->vm();
1087     NativeCallFrameTracer tracer(&vm, exec);
1088
1089     JSValue argument = JSValue::decode(encodedArgument);
1090
1091     JSString* input = argument.toStringOrNull(exec);
1092     if (!input)
1093         return false;
1094     return regExpObject->testInline(exec, globalObject, input);
1095 }
1096
1097 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1098 {
1099     SuperSamplerScope superSamplerScope(false);
1100     
1101     VM& vm = globalObject->vm();
1102     NativeCallFrameTracer tracer(&vm, exec);
1103     auto scope = DECLARE_THROW_SCOPE(vm);
1104
1105     JSValue base = JSValue::decode(encodedBase);
1106     JSValue argument = JSValue::decode(encodedArgument);
1107
1108     if (!base.inherits(vm, RegExpObject::info())) {
1109         throwTypeError(exec, scope);
1110         return false;
1111     }
1112
1113     JSString* input = argument.toStringOrNull(exec);
1114     EXCEPTION_ASSERT(!!scope.exception() == !input);
1115     if (!input)
1116         return false;
1117     scope.release();
1118     return asRegExpObject(base)->test(exec, globalObject, input);
1119 }
1120
1121 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1122 {
1123     VM* vm = &exec->vm();
1124     NativeCallFrameTracer tracer(vm, exec);
1125     
1126     JSValue op1 = JSValue::decode(encodedOp1);
1127     JSValue op2 = JSValue::decode(encodedOp2);
1128     
1129     ASSERT(op1.isCell());
1130     ASSERT(op2.isCell());
1131     
1132     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1133 }
1134
1135 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1136 {
1137     VM* vm = &exec->vm();
1138     NativeCallFrameTracer tracer(vm, exec);
1139
1140     JSValue src1 = JSValue::decode(encodedOp1);
1141     JSValue src2 = JSValue::decode(encodedOp2);
1142     
1143     return JSValue::strictEqual(exec, src1, src2);
1144 }
1145
1146 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1147 {
1148     VM* vm = &exec->vm();
1149     NativeCallFrameTracer tracer(vm, exec);
1150     
1151     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1152 }
1153
1154 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
1155 {
1156     VM* vm = &exec->vm();
1157     NativeCallFrameTracer tracer(vm, exec);
1158
1159     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
1160 }
1161
1162 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
1163 {
1164     VM& vm = exec->vm();
1165     NativeCallFrameTracer tracer(&vm, exec);
1166
1167     JSValue baseValue = JSValue::decode(encodedBase);
1168     JSValue thisVal = JSValue::decode(encodedThis);
1169     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1170     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
1171     return JSValue::encode(result);
1172 }
1173
1174 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1175 {
1176     VM& vm = exec->vm();
1177     NativeCallFrameTracer tracer(&vm, exec);
1178     auto scope = DECLARE_THROW_SCOPE(vm);
1179
1180     JSValue baseValue = JSValue::decode(encodedBase);
1181     JSValue thisVal = JSValue::decode(encodedThis);
1182     JSValue subscript = JSValue::decode(encodedSubscript);
1183
1184     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1185         Structure& structure = *baseValue.asCell()->structure(vm);
1186         if (JSCell::canUseFastGetOwnProperty(structure)) {
1187             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1188                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1189                     return JSValue::encode(result);
1190             }
1191         }
1192     }
1193     
1194     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1195     if (subscript.isUInt32()) {
1196         uint32_t i = subscript.asUInt32();
1197         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1198             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
1199         
1200         scope.release();
1201         return JSValue::encode(baseValue.get(exec, i, slot));
1202     }
1203
1204     baseValue.requireObjectCoercible(exec);
1205     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1206
1207     auto property = subscript.toPropertyKey(exec);
1208     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1209     scope.release();
1210     return JSValue::encode(baseValue.get(exec, property, slot));
1211 }
1212
1213 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1214 {
1215     VM& vm = exec->vm();
1216     NativeCallFrameTracer tracer(&vm, exec);
1217
1218     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1219 }
1220
1221 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1222 {
1223     VM& vm = exec->vm();
1224     NativeCallFrameTracer tracer(&vm, exec);
1225
1226     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1227 }
1228
1229 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1230 {
1231     VM& vm = exec->vm();
1232     NativeCallFrameTracer tracer(&vm, exec);
1233     auto scope = DECLARE_THROW_SCOPE(vm);
1234
1235     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1236     RETURN_IF_EXCEPTION(scope, void());
1237     scope.release();
1238     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1239 }
1240
1241 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1242 {
1243     VM& vm = exec->vm();
1244     NativeCallFrameTracer tracer(&vm, exec);
1245     auto scope = DECLARE_THROW_SCOPE(vm);
1246
1247     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1248     RETURN_IF_EXCEPTION(scope, void());
1249     scope.release();
1250     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1251 }
1252
1253 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1254 {
1255     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1256     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1257     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1258         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1259     else
1260         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1261 }
1262
1263 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1264 {
1265     VM& vm = exec->vm();
1266     NativeCallFrameTracer tracer(&vm, exec);
1267     auto scope = DECLARE_THROW_SCOPE(vm);
1268
1269     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1270     RETURN_IF_EXCEPTION(scope, void());
1271     scope.release();
1272     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1273 }
1274
1275 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1276 {
1277     VM& vm = exec->vm();
1278     NativeCallFrameTracer tracer(&vm, exec);
1279     auto scope = DECLARE_THROW_SCOPE(vm);
1280
1281     Identifier propertyName = property->toIdentifier(exec);
1282     RETURN_IF_EXCEPTION(scope, void());
1283     scope.release();
1284     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1285 }
1286
1287 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1288 {
1289     VM& vm = exec->vm();
1290     NativeCallFrameTracer tracer(&vm, exec);
1291     defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1292 }
1293
1294 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1295 {
1296     VM& vm = exec->vm();
1297     NativeCallFrameTracer tracer(&vm, exec);
1298     defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1299 }
1300
1301 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1302 {
1303     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1304     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1305     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1306         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1307     else
1308         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1309 }
1310
1311 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1312 {
1313     VM& vm = exec->vm();
1314     NativeCallFrameTracer tracer(&vm, exec);
1315     auto scope = DECLARE_THROW_SCOPE(vm);
1316
1317     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1318     RETURN_IF_EXCEPTION(scope, void());
1319     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1320 }
1321
1322 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1323 {
1324     VM& vm = exec->vm();
1325     NativeCallFrameTracer tracer(&vm, exec);
1326     auto scope = DECLARE_THROW_SCOPE(vm);
1327
1328     Identifier propertyName = property->toIdentifier(exec);
1329     RETURN_IF_EXCEPTION(scope, void());
1330     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1331 }
1332
1333 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1334 {
1335     VM& vm = exec->vm();
1336     NativeCallFrameTracer tracer(&vm, exec);
1337     defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
1338 }
1339
1340 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1341 {
1342     VM& vm = exec->vm();
1343     NativeCallFrameTracer tracer(&vm, exec);
1344     defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1345 }
1346
1347 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1348 {
1349     VM* vm = &exec->vm();
1350     NativeCallFrameTracer tracer(vm, exec);
1351     
1352     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1353 }
1354
1355 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1356 {
1357     VM* vm = &exec->vm();
1358     NativeCallFrameTracer tracer(vm, exec);
1359     
1360     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1361 }
1362
1363 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1364 {
1365     VM& vm = exec->vm();
1366     NativeCallFrameTracer tracer(&vm, exec);
1367     auto scope = DECLARE_THROW_SCOPE(vm);
1368
1369     if (UNLIKELY(size < 0))
1370         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1371
1372     JSArray* result;
1373     if (butterfly)
1374         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1375     else
1376         result = JSArray::create(vm, arrayStructure, size);
1377     return bitwise_cast<char*>(result);
1378 }
1379
1380 char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
1381 {
1382     VM& vm = exec->vm();
1383     NativeCallFrameTracer tracer(&vm, exec);
1384     auto scope = DECLARE_THROW_SCOPE(vm);
1385
1386     if (UNLIKELY(size < 0))
1387         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1388
1389     JSArray* result;
1390     if (butterfly)
1391         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1392     else {
1393         result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
1394         ASSERT(result);
1395     }
1396     return bitwise_cast<char*>(result);
1397 }
1398
1399 JSCell* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, JSCell* fixedArray, size_t size)
1400 {
1401     VM& vm = exec->vm();
1402     NativeCallFrameTracer tracer(&vm, exec);
1403     return constructArray(exec, arrayStructure, jsCast<JSFixedArray*>(fixedArray)->values(), size);
1404 }
1405
1406 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1407     ExecState* exec, Structure* structure, int32_t length, char* vector)
1408 {
1409     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1410 }
1411
1412 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1413     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1414 {
1415     VM& vm = exec->vm();
1416     NativeCallFrameTracer tracer(&vm, exec);
1417     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1418 }
1419
1420 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1421     ExecState* exec, Structure* structure, int32_t length, char* vector)
1422 {
1423     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1424 }
1425
1426 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1427     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1428 {
1429     VM& vm = exec->vm();
1430     NativeCallFrameTracer tracer(&vm, exec);
1431     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1432 }
1433
1434 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1435     ExecState* exec, Structure* structure, int32_t length, char* vector)
1436 {
1437     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1438 }
1439
1440 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1441     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1442 {
1443     VM& vm = exec->vm();
1444     NativeCallFrameTracer tracer(&vm, exec);
1445     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1446 }
1447
1448 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1449     ExecState* exec, Structure* structure, int32_t length, char* vector)
1450 {
1451     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1452 }
1453
1454 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1455     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1456 {
1457     VM& vm = exec->vm();
1458     NativeCallFrameTracer tracer(&vm, exec);
1459     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1460 }
1461
1462 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1463     ExecState* exec, Structure* structure, int32_t length, char* vector)
1464 {
1465     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1466 }
1467
1468 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1469     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1470 {
1471     VM& vm = exec->vm();
1472     NativeCallFrameTracer tracer(&vm, exec);
1473     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1474 }
1475
1476 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1477     ExecState* exec, Structure* structure, int32_t length, char* vector)
1478 {
1479     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1480 }
1481
1482 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1483     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1484 {
1485     VM& vm = exec->vm();
1486     NativeCallFrameTracer tracer(&vm, exec);
1487     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1488 }
1489
1490 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1491     ExecState* exec, Structure* structure, int32_t length, char* vector)
1492 {
1493     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1494 }
1495
1496 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1497     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1498 {
1499     VM& vm = exec->vm();
1500     NativeCallFrameTracer tracer(&vm, exec);
1501     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1502 }
1503
1504 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1505     ExecState* exec, Structure* structure, int32_t length, char* vector)
1506 {
1507     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1508 }
1509
1510 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1511     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1512 {
1513     VM& vm = exec->vm();
1514     NativeCallFrameTracer tracer(&vm, exec);
1515     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1516 }
1517
1518 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1519     ExecState* exec, Structure* structure, int32_t length, char* vector)
1520 {
1521     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1522 }
1523
1524 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1525     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1526 {
1527     VM& vm = exec->vm();
1528     NativeCallFrameTracer tracer(&vm, exec);
1529     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1530 }
1531
1532 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1533 {
1534     JSValue initialValue = JSValue::decode(initialValueEncoded);
1535     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1536     VM& vm = exec->vm();
1537     NativeCallFrameTracer tracer(&vm, exec);
1538     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1539 }
1540
1541 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1542 {
1543     VM& vm = exec->vm();
1544     NativeCallFrameTracer target(&vm, exec);
1545     DirectArguments* result = DirectArguments::create(
1546         vm, structure, length, std::max(length, minCapacity));
1547     // The caller will store to this object without barriers. Most likely, at this point, this is
1548     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1549     // since the GC should be allowed to do crazy (like pretenuring, for example).
1550     vm.heap.writeBarrier(result);
1551     return result;
1552 }
1553
1554 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1555 {
1556     VM& vm = exec->vm();
1557     NativeCallFrameTracer target(&vm, exec);
1558     
1559     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1560     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1561     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1562     
1563     return ScopedArguments::createByCopyingFrom(
1564         vm, structure, argumentStart, length, callee, table, scope);
1565 }
1566
1567 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1568 {
1569     VM& vm = exec->vm();
1570     NativeCallFrameTracer target(&vm, exec);
1571     return ClonedArguments::createByCopyingFrom(
1572         exec, structure, argumentStart, length, callee);
1573 }
1574
1575 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1576 {
1577     VM& vm = exec->vm();
1578     NativeCallFrameTracer target(&vm, exec);
1579     
1580     DeferGCForAWhile deferGC(vm.heap);
1581     
1582     CodeBlock* codeBlock;
1583     if (inlineCallFrame)
1584         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1585     else
1586         codeBlock = exec->codeBlock();
1587     
1588     unsigned length = argumentCount - 1;
1589     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1590     DirectArguments* result = DirectArguments::create(
1591         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1592     
1593     result->callee().set(vm, result, callee);
1594     
1595     Register* arguments =
1596         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1597         CallFrame::argumentOffset(0);
1598     for (unsigned i = length; i--;)
1599         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1600     
1601     return result;
1602 }
1603
1604 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1605 {
1606     VM& vm = exec->vm();
1607     NativeCallFrameTracer target(&vm, exec);
1608     
1609     DeferGCForAWhile deferGC(vm.heap);
1610     
1611     CodeBlock* codeBlock;
1612     if (inlineCallFrame)
1613         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1614     else
1615         codeBlock = exec->codeBlock();
1616     
1617     unsigned length = argumentCount - 1;
1618     ClonedArguments* result = ClonedArguments::createEmpty(
1619         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1620     
1621     Register* arguments =
1622         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1623         CallFrame::argumentOffset(0);
1624     for (unsigned i = length; i--;)
1625         result->putDirectIndex(exec, i, arguments[i].jsValue());
1626
1627     
1628     return result;
1629 }
1630
1631 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1632 {
1633     VM* vm = &exec->vm();
1634     NativeCallFrameTracer tracer(vm, exec);
1635
1636     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1637     Structure* structure = globalObject->restParameterStructure();
1638     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1639     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1640     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1641 }
1642
1643 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1644 {
1645     VM& vm = exec->vm();
1646     NativeCallFrameTracer tracer(&vm, exec);
1647
1648     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1649     
1650     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1651         return false;
1652     if (object->type() == JSFunctionType)
1653         return false;
1654     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1655         CallData callData;
1656         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1657             return false;
1658     }
1659     
1660     return true;
1661 }
1662
1663 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1664 {
1665     VM& vm = exec->vm();
1666     NativeCallFrameTracer tracer(&vm, exec);
1667
1668     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1669     
1670     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1671         return false;
1672     if (object->type() == JSFunctionType)
1673         return true;
1674     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1675         CallData callData;
1676         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1677             return true;
1678     }
1679     
1680     return false;
1681 }
1682
1683 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1684 {
1685     VM& vm = exec->vm();
1686     NativeCallFrameTracer tracer(&vm, exec);
1687
1688     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1689     
1690     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1691         return vm.smallStrings.undefinedString();
1692     if (object->type() == JSFunctionType)
1693         return vm.smallStrings.functionString();
1694     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1695         CallData callData;
1696         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1697             return vm.smallStrings.functionString();
1698     }
1699     
1700     return vm.smallStrings.objectString();
1701 }
1702
1703 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1704 {
1705     VM& vm = exec->vm();
1706     NativeCallFrameTracer tracer(&vm, exec);
1707
1708     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1709     
1710     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1711         return static_cast<int32_t>(TypeofType::Undefined);
1712     if (object->type() == JSFunctionType)
1713         return static_cast<int32_t>(TypeofType::Function);
1714     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1715         CallData callData;
1716         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1717             return static_cast<int32_t>(TypeofType::Function);
1718     }
1719     
1720     return static_cast<int32_t>(TypeofType::Object);
1721 }
1722
1723 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1724 {
1725     VM& vm = exec->vm();
1726     NativeCallFrameTracer tracer(&vm, exec);
1727
1728     return reinterpret_cast<char*>(
1729         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1730 }
1731
1732 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1733 {
1734     VM& vm = exec->vm();
1735     NativeCallFrameTracer tracer(&vm, exec);
1736
1737     return reinterpret_cast<char*>(
1738         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1739 }
1740
1741 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1742 {
1743     VM& vm = exec->vm();
1744     NativeCallFrameTracer tracer(&vm, exec);
1745
1746     ASSERT(!object->structure()->outOfLineCapacity());
1747     return reinterpret_cast<char*>(
1748         object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1749 }
1750
1751 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1752 {
1753     VM& vm = exec->vm();
1754     NativeCallFrameTracer tracer(&vm, exec);
1755
1756     return reinterpret_cast<char*>(
1757         object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize));
1758 }
1759
1760 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1761 {
1762     VM& vm = exec->vm();
1763     NativeCallFrameTracer tracer(&vm, exec);
1764     
1765     if (!cell->isObject())
1766         return 0;
1767     
1768     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1769 }
1770
1771 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1772 {
1773     VM& vm = exec->vm();
1774     NativeCallFrameTracer tracer(&vm, exec);
1775     
1776     if (!cell->isObject())
1777         return 0;
1778     
1779     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1780 }
1781
1782 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1783 {
1784     VM& vm = exec->vm();
1785     NativeCallFrameTracer tracer(&vm, exec);
1786     
1787     if (!cell->isObject())
1788         return 0;
1789     
1790     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1791 }
1792
1793 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1794 {
1795     VM& vm = exec->vm();
1796     NativeCallFrameTracer tracer(&vm, exec);
1797     
1798     if (!cell->isObject())
1799         return 0;
1800
1801     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1802 }
1803
1804 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
1805 {
1806     VM& vm = exec->vm();
1807     NativeCallFrameTracer tracer(&vm, exec);
1808     JSValue baseValue = JSValue::decode(encodedBaseValue);
1809     if (baseValue.isUndefinedOrNull())
1810         return JSValue::encode(jsBoolean(false));
1811
1812     JSObject* base = baseValue.toObject(exec);
1813     if (!base)
1814         return JSValue::encode(JSValue());
1815     return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
1816 }
1817
1818 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
1819 {
1820     VM& vm = exec->vm();
1821     NativeCallFrameTracer tracer(&vm, exec);
1822     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1823     if (UNLIKELY(subscript < 0)) {
1824         // Go the slowest way possible because negative indices don't use indexed storage.
1825         return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
1826     }
1827     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
1828 }
1829
1830 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, EncodedJSValue encodedBase)
1831 {
1832     VM& vm = exec->vm();
1833     NativeCallFrameTracer tracer(&vm, exec);
1834     auto scope = DECLARE_THROW_SCOPE(vm);
1835
1836     JSValue base = JSValue::decode(encodedBase);
1837     if (base.isUndefinedOrNull())
1838         return JSPropertyNameEnumerator::create(vm);
1839
1840     JSObject* baseObject = base.toObject(exec);
1841     RETURN_IF_EXCEPTION(scope, { });
1842
1843     scope.release();
1844     return propertyNameEnumerator(exec, baseObject);
1845 }
1846
1847 JSCell* JIT_OPERATION operationGetPropertyEnumeratorCell(ExecState* exec, JSCell* cell)
1848 {
1849     VM& vm = exec->vm();
1850     NativeCallFrameTracer tracer(&vm, exec);
1851     auto scope = DECLARE_THROW_SCOPE(vm);
1852
1853     JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
1854     RETURN_IF_EXCEPTION(scope, { });
1855
1856     scope.release();
1857     return propertyNameEnumerator(exec, base);
1858 }
1859
1860 JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
1861 {
1862     VM& vm = exec->vm();
1863     NativeCallFrameTracer tracer(&vm, exec);
1864     return jsString(exec, Identifier::from(exec, index).string());
1865 }
1866
1867 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1868 {
1869     VM& vm = exec->vm();
1870     NativeCallFrameTracer tracer(&vm, exec);
1871
1872     return string->value(exec).impl();
1873 }
1874
1875 JSCell* JIT_OPERATION operationStringSubstr(ExecState* exec, JSCell* cell, int32_t from, int32_t span)
1876 {
1877     VM& vm = exec->vm();
1878     NativeCallFrameTracer tracer(&vm, exec);
1879     auto scope = DECLARE_THROW_SCOPE(vm);
1880
1881     auto string = jsCast<JSString*>(cell)->value(exec);
1882     RETURN_IF_EXCEPTION(scope, nullptr);
1883     return jsSubstring(exec, string, from, span);
1884 }
1885
1886 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
1887 {
1888     VM& vm = exec->vm();
1889     NativeCallFrameTracer tracer(&vm, exec);
1890
1891     auto scope = DECLARE_THROW_SCOPE(vm);
1892
1893     const String& inputString = string->value(exec);
1894     RETURN_IF_EXCEPTION(scope, nullptr);
1895     if (!inputString.length())
1896         return vm.smallStrings.emptyString();
1897
1898     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
1899     if (lowercasedString.impl() == inputString.impl())
1900         return string;
1901     scope.release();
1902     return jsString(exec, lowercasedString);
1903 }
1904
1905 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
1906 {
1907     VM& vm = exec->vm();
1908     NativeCallFrameTracer tracer(&vm, exec);
1909
1910     auto scope = DECLARE_THROW_SCOPE(vm);
1911
1912     if (radix < 2 || radix > 36) {
1913         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1914         return nullptr;
1915     }
1916
1917     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1918 }
1919
1920 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
1921 {
1922     VM& vm = exec->vm();
1923     NativeCallFrameTracer tracer(&vm, exec);
1924
1925     auto scope = DECLARE_THROW_SCOPE(vm);
1926
1927     if (radix < 2 || radix > 36) {
1928         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1929         return nullptr;
1930     }
1931
1932     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1933 }
1934
1935 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
1936 {
1937     VM& vm = exec->vm();
1938     NativeCallFrameTracer tracer(&vm, exec);
1939
1940     auto scope = DECLARE_THROW_SCOPE(vm);
1941
1942     if (radix < 2 || radix > 36) {
1943         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1944         return nullptr;
1945     }
1946
1947     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1948 }
1949
1950 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
1951 {
1952     VM& vm = exec->vm();
1953     NativeCallFrameTracer tracer(&vm, exec);
1954
1955     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1956 }
1957
1958 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
1959 {
1960     VM& vm = exec->vm();
1961     NativeCallFrameTracer tracer(&vm, exec);
1962
1963     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1964 }
1965
1966 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
1967 {
1968     VM& vm = exec->vm();
1969     NativeCallFrameTracer tracer(&vm, exec);
1970
1971     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1972 }
1973
1974 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1975 {
1976     VM& vm = exec->vm();
1977     NativeCallFrameTracer tracer(&vm, exec);
1978     
1979     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1980 }
1981
1982 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1983 {
1984     VM& vm = exec->vm();
1985     NativeCallFrameTracer tracer(&vm, exec);
1986     
1987     return StringObject::create(vm, structure, string);
1988 }
1989
1990 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1991 {
1992     VM& vm = exec->vm();
1993     NativeCallFrameTracer tracer(&vm, exec);
1994     
1995     return JSValue(cell).toString(exec);
1996 }
1997
1998 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1999 {
2000     VM& vm = exec->vm();
2001     NativeCallFrameTracer tracer(&vm, exec);
2002
2003     return JSValue::decode(value).toString(exec);
2004 }
2005
2006 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
2007 {
2008     VM& vm = exec->vm();
2009     NativeCallFrameTracer tracer(&vm, exec);
2010
2011     return stringConstructor(exec, cell);
2012 }
2013
2014 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
2015 {
2016     VM& vm = exec->vm();
2017     NativeCallFrameTracer tracer(&vm, exec);
2018
2019     return stringConstructor(exec, JSValue::decode(value));
2020 }
2021
2022 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
2023 {
2024     VM& vm = exec->vm();
2025     NativeCallFrameTracer tracer(&vm, exec);
2026
2027     return jsString(exec, left, right);
2028 }
2029
2030 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
2031 {
2032     VM& vm = exec->vm();
2033     NativeCallFrameTracer tracer(&vm, exec);
2034
2035     return jsString(exec, a, b, c);
2036 }
2037
2038 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
2039 {
2040     VM& vm = exec->vm();
2041     NativeCallFrameTracer tracer(&vm, exec);
2042     auto scope = DECLARE_THROW_SCOPE(vm);
2043
2044     ASSERT(!JSValue::decode(a).isSymbol());
2045     ASSERT(!JSValue::decode(b).isSymbol());
2046     JSString* str1 = JSValue::decode(a).toString(exec);
2047     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2048     JSString* str2 = JSValue::decode(b).toString(exec);
2049     scope.assertNoException();
2050
2051     scope.release();
2052     return jsString(exec, str1, str2);
2053 }
2054     
2055 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2056 {
2057     VM& vm = exec->vm();
2058     NativeCallFrameTracer tracer(&vm, exec);
2059     auto scope = DECLARE_THROW_SCOPE(vm);
2060
2061     ASSERT(!JSValue::decode(a).isSymbol());
2062     ASSERT(!JSValue::decode(b).isSymbol());
2063     ASSERT(!JSValue::decode(c).isSymbol());
2064     JSString* str1 = JSValue::decode(a).toString(exec);
2065     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2066     JSString* str2 = JSValue::decode(b).toString(exec);
2067     scope.assertNoException();
2068     JSString* str3 = JSValue::decode(c).toString(exec);
2069     scope.assertNoException();
2070
2071     scope.release();
2072     return jsString(exec, str1, str2, str3);
2073 }
2074
2075 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
2076     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
2077 {
2078     VM& vm = exec->vm();
2079     NativeCallFrameTracer tracer(&vm, exec);
2080
2081     CodeBlock* codeBlock = exec->codeBlock();
2082     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2083     JSValue value = JSValue::decode(encodedValue);
2084     ASSERT(value.isDouble());
2085     double asDouble = value.asDouble();
2086     int32_t asInt32 = static_cast<int32_t>(asDouble);
2087     if (asDouble == asInt32)
2088         return table.ctiForValue(asInt32).executableAddress<char*>();
2089     return table.ctiDefault.executableAddress<char*>();
2090 }
2091
2092 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
2093 {
2094     VM& vm = exec->vm();
2095     NativeCallFrameTracer tracer(&vm, exec);
2096
2097     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress<char*>();
2098 }
2099
2100 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
2101 {
2102     VM& vm = exec->vm();
2103     NativeCallFrameTracer tracer(&vm, exec);
2104
2105     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
2106 }
2107
2108 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2109 {
2110     return codePointCompare(a, b) < 0;
2111 }
2112
2113 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2114 {
2115     return codePointCompare(a, b) <= 0;
2116 }
2117
2118 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2119 {
2120     return codePointCompare(a, b) > 0;
2121 }
2122
2123 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2124 {
2125     return codePointCompare(a, b) >= 0;
2126 }
2127
2128 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
2129 {
2130     VM& vm = exec->vm();
2131     NativeCallFrameTracer tracer(&vm, exec);
2132
2133     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2134 }
2135
2136 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
2137 {
2138     VM& vm = exec->vm();
2139     NativeCallFrameTracer tracer(&vm, exec);
2140
2141     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2142 }
2143
2144 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
2145 {
2146     VM& vm = exec->vm();
2147     NativeCallFrameTracer tracer(&vm, exec);
2148
2149     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2150 }
2151
2152 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
2153 {
2154     VM& vm = exec->vm();
2155     NativeCallFrameTracer tracer(&vm, exec);
2156
2157     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2158 }
2159
2160 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
2161 {
2162     VM& vm = exec->vm();
2163     NativeCallFrameTracer tracer(&vm, exec);
2164
2165     set->touch(vm, "Executed NotifyWrite");
2166 }
2167
2168 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2169 {
2170     VM& vm = exec->vm();
2171     NativeCallFrameTracer tracer(&vm, exec);
2172     auto scope = DECLARE_THROW_SCOPE(vm);
2173     throwStackOverflowError(exec, scope);
2174 }
2175
2176 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
2177 {
2178     VM& vm = exec->vm();
2179     NativeCallFrameTracer tracer(&vm, exec);
2180     JSValue arguments = JSValue::decode(encodedArguments);
2181     
2182     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2183 }
2184
2185 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2186 {
2187     VM& vm = exec->vm();
2188     NativeCallFrameTracer tracer(&vm, exec);
2189     auto scope = DECLARE_THROW_SCOPE(vm);
2190
2191     JSValue key = JSValue::decode(encodedKey);
2192     Identifier propertyName = key.toPropertyKey(exec);
2193     RETURN_IF_EXCEPTION(scope, false);
2194
2195     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2196     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2197     RETURN_IF_EXCEPTION(scope, false);
2198
2199     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2200     ASSERT(hasOwnPropertyCache);
2201     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2202     return result;
2203 }
2204
2205 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2206 {
2207     VM& vm = exec->vm();
2208     NativeCallFrameTracer tracer(&vm, exec);
2209     auto scope = DECLARE_THROW_SCOPE(vm);
2210
2211     int32_t length = butterfly->publicLength();
2212     auto data = butterfly->contiguous().data();
2213     for (; index < length; ++index) {
2214         JSValue value = data[index].get();
2215         if (!value || !value.isString())
2216             continue;
2217         auto* string = asString(value);
2218         if (string == searchElement)
2219             return index;
2220         if (string->equal(exec, searchElement))
2221             return index;
2222         RETURN_IF_EXCEPTION(scope, { });
2223     }
2224     return -1;
2225 }
2226
2227 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2228 {
2229     VM& vm = exec->vm();
2230     NativeCallFrameTracer tracer(&vm, exec);
2231     auto scope = DECLARE_THROW_SCOPE(vm);
2232
2233     JSValue searchElement = JSValue::decode(encodedValue);
2234
2235     int32_t length = butterfly->publicLength();
2236     auto data = butterfly->contiguous().data();
2237     for (; index < length; ++index) {
2238         JSValue value = data[index].get();
2239         if (!value)
2240             continue;
2241         if (JSValue::strictEqual(exec, searchElement, value))
2242             return index;
2243         RETURN_IF_EXCEPTION(scope, { });
2244     }
2245     return -1;
2246 }
2247
2248 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2249 {
2250     VM& vm = exec->vm();
2251     NativeCallFrameTracer tracer(&vm, exec);
2252
2253     JSValue searchElement = JSValue::decode(encodedValue);
2254
2255     if (!searchElement.isNumber())
2256         return -1;
2257     double number = searchElement.asNumber();
2258
2259     int32_t length = butterfly->publicLength();
2260     const double* data = butterfly->contiguousDouble().data();
2261     for (; index < length; ++index) {
2262         // This comparison ignores NaN.
2263         if (data[index] == number)
2264             return index;
2265     }
2266     return -1;
2267 }
2268
2269 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
2270 {
2271     VM& vm = exec->vm();
2272     NativeCallFrameTracer tracer(&vm, exec);
2273     JSValue arguments = JSValue::decode(encodedArguments);
2274     
2275     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2276     
2277     for (int32_t i = length; i < mandatoryMinimum; ++i)
2278         exec->r(firstElementDest + i) = jsUndefined();
2279 }
2280
2281 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2282 {
2283     return fmod(a, b);
2284 }
2285
2286 #if USE(JSVALUE32_64)
2287 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2288 {
2289     return globalObject->weakRandomNumber();
2290 }
2291 #endif
2292
2293 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2294 {
2295     VM* vm = &exec->vm();
2296     NativeCallFrameTracer tracer(vm, exec);
2297     return JSC::stringFromCharCode(exec, op1);
2298 }
2299
2300 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2301 {
2302     VM* vm = &exec->vm();
2303     NativeCallFrameTracer tracer(vm, exec);
2304     JSValue charValue = JSValue::decode(encodedValue);
2305     int32_t chInt = charValue.toUInt32(exec);
2306     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2307 }
2308
2309 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2310 {
2311     JSValue value = JSValue::decode(encodedValue);
2312     if (!value.isDouble())
2313         return JSValue::notInt52;
2314     return tryConvertToInt52(value.asDouble());
2315 }
2316
2317 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2318 {
2319     return tryConvertToInt52(value);
2320 }
2321
2322 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
2323 {
2324     VM* vm = &exec->vm();
2325     NativeCallFrameTracer tracer(vm, exec);
2326     if (JSObject::defaultHasInstance(exec, value, proto))
2327         return 1;
2328     return 0;
2329 }
2330
2331 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2332 {
2333     VM& vm = exec->vm();
2334     NativeCallFrameTracer tracer(&vm, exec);
2335
2336     if (!butterfly
2337         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2338         IndexingHeader header;
2339         header.setVectorLength(length);
2340         header.setPublicLength(0);
2341         
2342         butterfly = Butterfly::create(
2343             vm, nullptr, 0, structure->outOfLineCapacity(),
2344             hasIndexedProperties(structure->indexingType()), header,
2345             length * sizeof(EncodedJSValue));
2346     }
2347
2348     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2349     result->butterfly(); // Ensure that the butterfly is in to-space.
2350     return bitwise_cast<char*>(result);
2351 }
2352
2353 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2354 {
2355     VM& vm = exec->vm();
2356     NativeCallFrameTracer tracer(&vm, exec);
2357     
2358     if (!butterfly) {
2359         butterfly = Butterfly::create(
2360             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2361     }
2362     
2363     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2364     result->butterfly(); // Ensure that the butterfly is in to-space.
2365     return result;
2366 }
2367
2368 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2369 {
2370     VM& vm = exec->vm();
2371     NativeCallFrameTracer tracer(&vm, exec);
2372
2373     IndexingHeader header;
2374     header.setVectorLength(length);
2375     header.setPublicLength(0);
2376     if (butterfly)
2377         *butterfly->indexingHeader() = header;
2378     else {
2379         butterfly = Butterfly::create(
2380             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2381             sizeof(EncodedJSValue) * length);
2382     }
2383     
2384     // Paradoxically this may allocate a JSArray. That's totally cool.
2385     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2386     result->butterfly(); // Ensure that the butterfly is in to-space.
2387     return result;
2388 }
2389
2390 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2391 {
2392     VM& vm = exec->vm();
2393     NativeCallFrameTracer tracer(&vm, exec);
2394     auto scope = DECLARE_THROW_SCOPE(vm);
2395
2396     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2397     Checked<unsigned, RecordOverflow> checkedLength = 0;
2398     for (unsigned i = 0; i < numItems; i++) {
2399         JSValue value = JSValue::decode(values[i]);
2400         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2401             checkedLength += array->size();
2402         else
2403             ++checkedLength;
2404     }
2405
2406     if (UNLIKELY(checkedLength.hasOverflowed())) {
2407         throwOutOfMemoryError(exec, scope);
2408         return nullptr;
2409     }
2410
2411     unsigned length = checkedLength.unsafeGet();
2412     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2413     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2414
2415     JSArray* result = JSArray::tryCreate(vm, structure, length);
2416     if (UNLIKELY(!result)) {
2417         throwOutOfMemoryError(exec, scope);
2418         return nullptr;
2419     }
2420     RETURN_IF_EXCEPTION(scope, nullptr);
2421
2422     unsigned index = 0;
2423     for (unsigned i = 0; i < numItems; i++) {
2424         JSValue value = JSValue::decode(values[i]);
2425         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2426             // We are spreading.
2427             for (unsigned i = 0; i < array->size(); i++) {
2428                 result->putDirectIndex(exec, index, array->get(i));
2429                 RETURN_IF_EXCEPTION(scope, nullptr);
2430                 ++index;
2431             }
2432         } else {
2433             // We are not spreading.
2434             result->putDirectIndex(exec, index, value);
2435             RETURN_IF_EXCEPTION(scope, nullptr);
2436             ++index;
2437         }
2438     }
2439
2440     return result;
2441 }
2442
2443 JSCell* operationCreateFixedArray(ExecState* exec, unsigned length)
2444 {
2445     VM& vm = exec->vm();
2446     NativeCallFrameTracer tracer(&vm, exec);
2447     auto scope = DECLARE_THROW_SCOPE(vm);
2448
2449     if (JSFixedArray* result = JSFixedArray::tryCreate(vm, vm.fixedArrayStructure.get(), length))
2450         return result;
2451
2452     throwOutOfMemoryError(exec, scope);
2453     return nullptr;
2454 }
2455
2456 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2457 {
2458     VM& vm = exec->vm();
2459     NativeCallFrameTracer tracer(&vm, exec);
2460
2461     auto throwScope = DECLARE_THROW_SCOPE(vm);
2462
2463     if (isJSArray(iterable)) {
2464         JSArray* array = jsCast<JSArray*>(iterable);
2465         if (array->isIteratorProtocolFastAndNonObservable()) {
2466             throwScope.release();
2467             return JSFixedArray::createFromArray(exec, vm, array);
2468         }
2469     }
2470
2471     // FIXME: we can probably make this path faster by having our caller JS code call directly into
2472     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2473
2474     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2475     JSArray* array;
2476     {
2477         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2478         CallData callData;
2479         CallType callType = JSC::getCallData(iterationFunction, callData);
2480         ASSERT(callType != CallType::None);
2481
2482         MarkedArgumentBuffer arguments;
2483         arguments.append(iterable);
2484         ASSERT(!arguments.hasOverflowed());
2485         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2486         RETURN_IF_EXCEPTION(throwScope, nullptr);
2487         array = jsCast<JSArray*>(arrayResult);
2488     }
2489
2490     throwScope.release();
2491     return JSFixedArray::createFromArray(exec, vm, array);
2492 }
2493
2494 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2495 {
2496     VM& vm = exec->vm();
2497     NativeCallFrameTracer tracer(&vm, exec);
2498
2499     ASSERT(isJSArray(cell));
2500     JSArray* array = jsCast<JSArray*>(cell);
2501     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2502
2503     return JSFixedArray::createFromArray(exec, vm, array);
2504 }
2505
2506 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2507 {
2508     VM& vm = exec->vm();
2509     NativeCallFrameTracer tracer(&vm, exec);
2510
2511     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
2512 }
2513
2514 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2515 {
2516     VM& vm = exec->vm();
2517     NativeCallFrameTracer tracer(&vm, exec);
2518         
2519     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2520     return JSValue::encode(resolvedScope);
2521 }
2522     
2523 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2524 {
2525     VM& vm = exec->vm();
2526     NativeCallFrameTracer tracer(&vm, exec);
2527
2528     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2529     return resolvedScope;
2530 }
2531
2532 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2533 {
2534     VM& vm = exec->vm();
2535     NativeCallFrameTracer tracer(&vm, exec);
2536     auto throwScope = DECLARE_THROW_SCOPE(vm);
2537
2538     Identifier ident = Identifier::fromUid(exec, impl);
2539     throwScope.release();
2540     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2541         if (!found) {
2542             GetPutInfo getPutInfo(getPutInfoBits);
2543             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2544                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2545             return jsUndefined();
2546         }
2547
2548         if (scope->isGlobalLexicalEnvironment()) {
2549             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2550             JSValue result = slot.getValue(exec, ident);
2551             if (result == jsTDZValue()) {
2552                 throwException(exec, throwScope, createTDZError(exec));
2553                 return jsUndefined();
2554             }
2555             return result;
2556         }
2557
2558         return slot.getValue(exec, ident);
2559     }));
2560 }
2561
2562 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2563 {
2564     VM& vm = exec->vm();
2565     NativeCallFrameTracer tracer(&vm, exec);
2566     auto throwScope = DECLARE_THROW_SCOPE(vm);
2567
2568     const Identifier& ident = Identifier::fromUid(exec, impl);
2569     GetPutInfo getPutInfo(getPutInfoBits);
2570     bool hasProperty = scope->hasProperty(exec, ident);
2571     RETURN_IF_EXCEPTION(throwScope, void());
2572     if (hasProperty
2573         && scope->isGlobalLexicalEnvironment()
2574         && !isInitialization(getPutInfo.initializationMode())) {
2575         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2576         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2577         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2578         if (slot.getValue(exec, ident) == jsTDZValue()) {
2579             throwException(exec, throwScope, createTDZError(exec));
2580             return;
2581         }
2582     }
2583
2584     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2585         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2586         return;
2587     }
2588
2589     CodeOrigin origin = exec->codeOrigin();
2590     bool strictMode;
2591     if (origin.inlineCallFrame)
2592         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2593     else
2594         strictMode = exec->codeBlock()->isStrictMode();
2595     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2596     throwScope.release();
2597     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2598 }
2599
2600 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2601 {
2602     VM& vm = exec->vm();
2603     NativeCallFrameTracer tracer(&vm, exec);
2604
2605     return jsMapHash(exec, vm, JSValue::decode(input));
2606 }
2607
2608 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2609 {
2610     VM& vm = exec->vm();
2611     NativeCallFrameTracer tracer(&vm, exec);
2612     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
2613     if (!bucket)
2614         return vm.sentinelMapBucket.get();
2615     return *bucket;
2616 }
2617
2618 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2619 {
2620     VM& vm = exec->vm();
2621     NativeCallFrameTracer tracer(&vm, exec);
2622     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
2623     if (!bucket)
2624         return vm.sentinelSetBucket.get();
2625     return *bucket;
2626 }
2627
2628 void JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
2629 {
2630     VM& vm = exec->vm();
2631     NativeCallFrameTracer tracer(&vm, exec);
2632     jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
2633 }
2634
2635 void JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
2636 {
2637     VM& vm = exec->vm();
2638     NativeCallFrameTracer tracer(&vm, exec);
2639     jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
2640 }
2641
2642 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
2643 {
2644     VM& vm = exec->vm();
2645     NativeCallFrameTracer tracer(&vm, exec);
2646     return JSValue::encode(thisObject->getPrototype(vm, exec));
2647 }
2648
2649 EncodedJSValue JIT_OPERATION operationGetPrototypeOf(ExecState* exec, EncodedJSValue encodedValue)
2650 {
2651     VM& vm = exec->vm();
2652     NativeCallFrameTracer tracer(&vm, exec);
2653     auto scope = DECLARE_THROW_SCOPE(vm);
2654
2655     JSValue thisValue = JSValue::decode(encodedValue).toThis(exec, StrictMode);
2656     if (thisValue.isUndefinedOrNull())
2657         return throwVMError(exec, scope, createNotAnObjectError(exec, thisValue));
2658
2659     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
2660     if (!thisObject) {
2661         JSObject* prototype = thisValue.synthesizePrototype(exec);
2662         EXCEPTION_ASSERT(!!scope.exception() == !prototype);
2663         if (UNLIKELY(!prototype))
2664             return JSValue::encode(JSValue());
2665         return JSValue::encode(prototype);
2666     }
2667
2668     scope.release();
2669     return JSValue::encode(thisObject->getPrototype(vm, exec));
2670 }
2671
2672 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2673 {
2674     VM& vm = exec->vm();
2675     NativeCallFrameTracer tracer(&vm, exec);
2676     auto scope = DECLARE_THROW_SCOPE(vm);
2677     scope.throwException(exec, JSValue::decode(valueToThrow));
2678 }
2679
2680 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2681 {
2682     VM& vm = exec->vm();
2683     NativeCallFrameTracer tracer(&vm, exec);
2684     auto scope = DECLARE_THROW_SCOPE(vm);
2685     String errorMessage = message->value(exec);
2686     scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2687 }
2688
2689 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
2690 {
2691     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2692     // really be profitable.
2693     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2694     
2695     sanitizeStackForVM(codeBlock->vm());
2696
2697     if (Options::verboseOSR())
2698         dataLog(*codeBlock, ": Entered reoptimize\n");
2699     // We must be called with the baseline code block.
2700     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2701
2702     // If I am my own replacement, then reoptimization has already been triggered.
2703     // This can happen in recursive functions.
2704     if (codeBlock->replacement() == codeBlock) {
2705         if (Options::verboseOSR())
2706             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2707         return;
2708     }
2709     
2710     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2711     // to check our logic.
2712     ASSERT(codeBlock->hasOptimizedReplacement());
2713     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2714     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2715     
2716     bool didTryToEnterIntoInlinedLoops = false;
2717     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2718         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2719             didTryToEnterIntoInlinedLoops = true;
2720             break;
2721         }
2722     }
2723
2724     // In order to trigger reoptimization, one of two things must have happened:
2725     // 1) We exited more than some number of times.
2726     // 2) We exited and got stuck in a loop, and now we're exiting again.
2727     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2728     bool didGetStuckInLoop =
2729         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2730         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2731     
2732     if (!didExitABunch && !didGetStuckInLoop) {
2733         if (Options::verboseOSR())
2734             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2735         codeBlock->optimizeAfterLongWarmUp();
2736         return;
2737     }
2738
2739     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2740 }
2741
2742 #if ENABLE(FTL_JIT)
2743 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2744 {
2745     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2746         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2747         if (Options::verboseOSR())
2748             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2749         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2750         return false;
2751     }
2752
2753     if (!codeBlock->hasOptimizedReplacement()
2754         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2755         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2756         if (Options::verboseOSR())
2757             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2758         return false;
2759     }
2760     return true;
2761 }
2762
2763 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2764 {
2765     if (codeBlock->codeType() == GlobalCode) {
2766         // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2767         // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2768         // later want to run faster code. Deferring for warm-up seems safest.
2769         jitCode->optimizeAfterWarmUp(codeBlock);
2770         return;
2771     }
2772     
2773     Worklist::State worklistState;
2774     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2775         worklistState = worklist->completeAllReadyPlansForVM(
2776             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2777     } else
2778         worklistState = Worklist::NotKnown;
2779     
2780     if (worklistState == Worklist::Compiling) {
2781         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2782         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2783             codeBlock, CompilationDeferred);
2784         return;
2785     }
2786     
2787     if (codeBlock->hasOptimizedReplacement()) {
2788         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2789         // That's great, we've compiled the code - next time we call this function,
2790         // we'll enter that replacement.
2791         jitCode->optimizeSoon(codeBlock);
2792         return;
2793     }
2794     
2795     if (worklistState == Worklist::Compiled) {
2796         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2797         // This means that we finished compiling, but failed somehow; in that case the
2798         // thresholds will be set appropriately.
2799         if (Options::verboseOSR())
2800             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2801         return;
2802     }
2803
2804     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2805     // We need to compile the code.
2806     compile(
2807         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2808         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2809
2810     // If we reached here, the counter has not be reset. Do that now.
2811     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2812         codeBlock, CompilationDeferred);
2813 }
2814
2815 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2816 {
2817     VM* vm = &exec->vm();
2818     NativeCallFrameTracer tracer(vm, exec);
2819     DeferGCForAWhile deferGC(vm->heap);
2820     CodeBlock* codeBlock = exec->codeBlock();
2821     
2822     sanitizeStackForVM(vm);
2823
2824     if (codeBlock->jitType() != JITCode::DFGJIT) {
2825         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2826         RELEASE_ASSERT_NOT_REACHED();
2827     }
2828     
2829     JITCode* jitCode = codeBlock->jitCode()->dfg();
2830     
2831     if (Options::verboseOSR()) {
2832         dataLog(
2833             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2834             jitCode->tierUpCounter, "\n");
2835     }
2836
2837     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2838         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2839
2840     if (codeBlock->hasOptimizedReplacement()) {
2841         if (jitCode->tierUpEntryTriggers.isEmpty()) {
2842             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2843             // There is nothing more we can do, the only way this will be entered
2844             // is through the function entry point.
2845             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2846             return;
2847         }
2848         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2849             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2850             // There is only one outer loop and its trigger must have been set
2851             // when the plan completed.
2852             // Exiting the inner loop is useless, we can ignore the counter and leave
2853             // the trigger do its job.
2854             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2855             return;
2856         }
2857     }
2858 }
2859
2860 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
2861 {
2862     VM* vm = &exec->vm();
2863     CodeBlock* codeBlock = exec->codeBlock();
2864
2865     // Resolve any pending plan for OSR Enter on this function.
2866     Worklist::State worklistState;
2867     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2868         worklistState = worklist->completeAllReadyPlansForVM(
2869             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2870     } else
2871         worklistState = Worklist::NotKnown;
2872
2873     JITCode* jitCode = codeBlock->jitCode()->dfg();
2874
2875     // The following is only true for triggerTierUpNowInLoop, which can never
2876     // be an OSR entry.
2877     bool canOSRFromHere = originBytecodeIndex == osrEntryBytecodeIndex;
2878     
2879     bool triggeredSlowPathToStartCompilation = false;
2880     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
2881     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
2882         switch (tierUpEntryTriggers->value) {
2883         case JITCode::TriggerReason::DontTrigger:
2884             // The trigger isn't set, we entered because the counter reached its
2885             // threshold.
2886             break;
2887
2888         case JITCode::TriggerReason::CompilationDone:
2889             // The trigger was set because compilation completed. Don't unset it
2890             // so that further DFG executions OSR enters as well.
2891             RELEASE_ASSERT(canOSRFromHere);
2892             break;
2893
2894         case JITCode::TriggerReason::StartCompilation:
2895             // We were asked to enter as soon as possible and start compiling an
2896             // entry for the current bytecode location. Unset this trigger so we
2897             // don't continually enter.
2898             RELEASE_ASSERT(canOSRFromHere);
2899             tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
2900             triggeredSlowPathToStartCompilation = true;
2901             break;
2902         }
2903     }
2904
2905     if (worklistState == Worklist::Compiling) {
2906         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2907         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2908             codeBlock, CompilationDeferred);
2909         return nullptr;
2910     }
2911
2912     if (worklistState == Worklist::Compiled) {
2913         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2914         // This means that compilation failed and we already set the thresholds.
2915         if (Options::verboseOSR())
2916             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2917         return nullptr;
2918     }
2919
2920     // If we can OSR Enter, do it right away.
2921     if (canOSRFromHere) {
2922         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
2923         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2924             if (Options::verboseOSR())
2925                 dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
2926             if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
2927                 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
2928                 return static_cast<char*>(address);
2929             }
2930         }
2931     }
2932
2933     // - If we don't have an FTL code block, then try to compile one.
2934     // - If we do have an FTL code block, then try to enter for a while.
2935     // - If we couldn't enter for a while, then trigger OSR entry.
2936
2937     if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
2938         return nullptr;
2939
2940     if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
2941         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2942
2943         if (!codeBlock->hasOptimizedReplacement())
2944             return nullptr;
2945
2946         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2947             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2948             jitCode->osrEntryRetry++;
2949             return nullptr;
2950         }
2951     } else
2952         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2953
2954     // It's time to try to compile code for OSR entry.
2955     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2956         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2957             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2958             jitCode->osrEntryRetry++;
2959             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2960                 codeBlock, CompilationDeferred);
2961             return nullptr;
2962         }
2963
2964         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
2965         entryCode->countEntryFailure();
2966         if (entryCode->entryFailureCount() <
2967             Options::ftlOSREntryFailureCountForReoptimization()) {
2968             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2969             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2970                 codeBlock, CompilationDeferred);
2971             return nullptr;
2972         }
2973
2974         // OSR entry failed. Oh no! This implies that we need to retry. We retry
2975         // without exponential backoff and we only do this for the entry code block.
2976         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2977         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2978         jitCode->clearOSREntryBlock();
2979         jitCode->osrEntryRetry = 0;
2980         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
2981         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2982             codeBlock, CompilationDeferred);
2983         return nullptr;
2984     }
2985
2986     if (!canOSRFromHere) {
2987         // We can't OSR from here, or even start a compilation because doing so
2988         // calls jitCode->reconstruct which would get the wrong state.
2989         if (Options::verboseOSR())
2990             dataLog("Non-OSR-able bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryBytecodeIndex, "'s trigger and backing off.\n");
2991         jitCode->tierUpEntryTriggers.set(osrEntryBytecodeIndex, JITCode::TriggerReason::StartCompilation);
2992         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2993         return nullptr;
2994     }
2995
2996     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2997
2998     if (!triggeredSlowPathToStartCompilation) {
2999         auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
3000         if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
3001             for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
3002                 if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
3003                     // Ask an enclosing loop to compile, instead of doing so here.
3004                     if (Options::verboseOSR())
3005                         dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
3006                     jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
3007                     jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3008                     return nullptr;
3009                 }
3010             }
3011         }
3012     }
3013
3014     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
3015     // something.
3016     auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
3017     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
3018     JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
3019
3020     Operands<JSValue> mustHandleValues;
3021     jitCode->reconstruct(
3022         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
3023     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
3024
3025     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
3026     CompilationResult forEntryResult = compile(
3027         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
3028         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
3029
3030     if (jitCode->neverExecutedEntry)
3031         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3032
3033     if (forEntryResult != CompilationSuccessful) {
3034         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
3035         jitCode->setOptimizationThresholdBasedOnCompilationResult(
3036             codeBlock, CompilationDeferred);
3037         return nullptr;
3038     }
3039     
3040     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
3041     // It's possible that the for-entry compile already succeeded. In that case OSR
3042     // entry will succeed unless we ran out of stack. It's not clear what we should do.
3043     // We signal to try again after a while if that happens.
3044     if (Options::verboseOSR())
3045         dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
3046     void* address = FTL::prepareOSREntry(
3047         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
3048     return static_cast<char*>(address);
3049 }
3050
3051 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
3052 {
3053     VM* vm = &exec->vm();
3054     NativeCallFrameTracer tracer(vm, exec);
3055     DeferGCForAWhile deferGC(vm->heap);
3056     CodeBlock* codeBlock = exec->codeBlock();
3057
3058     sanitizeStackForVM(vm);
3059
3060     if (codeBlock->jitType() != JITCode::DFGJIT) {
3061         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3062         RELEASE_ASSERT_NOT_REACHED();
3063     }
3064
3065     JITCode* jitCode = codeBlock->jitCode()->dfg();
3066
3067     if (Options::verboseOSR()) {
3068         dataLog(
3069             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
3070             jitCode->tierUpCounter, "\n");
3071     }
3072
3073     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
3074     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
3075         && !tierUpHierarchyEntry->value.isEmpty()) {
3076         tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
3077     } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
3078         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3079
3080     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
3081     if (codeBlock->hasOptimizedReplacement()) {
3082         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
3083         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3084     }
3085 }
3086
3087 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
3088 {
3089     VM* vm = &exec->vm();
3090     NativeCallFrameTracer tracer(vm, exec);
3091     DeferGCForAWhile deferGC(vm->heap);
3092     CodeBlock* codeBlock = exec->codeBlock();
3093
3094     sanitizeStackForVM(vm);
3095
3096     if (codeBlock->jitType() != JITCode::DFGJIT) {
3097         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3098         RELEASE_ASSERT_NOT_REACHED();
3099     }
3100
3101     JITCode* jitCode = codeBlock->jitCode()->dfg();
3102     jitCode->tierUpEntrySeen.add(bytecodeIndex);
3103
3104     if (Options::verboseOSR()) {
3105         dataLog(
3106             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
3107             jitCode->tierUpCounter, "\n");
3108     }
3109
3110     return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
3111 }
3112
3113 #endif // ENABLE(FTL_JIT)
3114
3115 } // extern "C"
3116 } } // namespace JSC::DFG
3117
3118 #endif // ENABLE(DFG_JIT)
3119
3120 #endif // ENABLE(JIT)