[DFG][FTL] operationHasIndexedProperty does not consider negative int32_t
[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 "JSSet.h"
59 #include "JSWeakMap.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 operationWeakMapGet(ExecState* exec, JSCell* weakMap, JSCell* object, int32_t hash)
1027 {
1028     VM& vm = exec->vm();
1029     NativeCallFrameTracer tracer(&vm, exec);
1030     return JSValue::encode(jsCast<JSWeakMap*>(weakMap)->inlineGet(asObject(object), hash));
1031 }
1032
1033 EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
1034 {
1035     VM& vm = exec->vm();
1036     NativeCallFrameTracer tracer(&vm, exec);
1037
1038     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1039         // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1040         return parseIntResult(parseInt(view, 0));
1041     });
1042 }
1043
1044 EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(ExecState* exec, JSString* string)
1045 {
1046     VM& vm = exec->vm();
1047     NativeCallFrameTracer tracer(&vm, exec);
1048     auto scope = DECLARE_THROW_SCOPE(vm);
1049
1050     auto viewWithString = string->viewWithUnderlyingString(exec);
1051     RETURN_IF_EXCEPTION(scope, { });
1052
1053     // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1054     return parseIntResult(parseInt(viewWithString.view, 0));
1055 }
1056
1057 EncodedJSValue JIT_OPERATION operationParseIntString(ExecState* exec, JSString* string, int32_t radix)
1058 {
1059     VM& vm = exec->vm();
1060     NativeCallFrameTracer tracer(&vm, exec);
1061     auto scope = DECLARE_THROW_SCOPE(vm);
1062
1063     auto viewWithString = string->viewWithUnderlyingString(exec);
1064     RETURN_IF_EXCEPTION(scope, { });
1065
1066     return parseIntResult(parseInt(viewWithString.view, radix));
1067 }
1068
1069 EncodedJSValue JIT_OPERATION operationParseIntGeneric(ExecState* exec, EncodedJSValue value, int32_t radix)
1070 {
1071     VM& vm = exec->vm();
1072     NativeCallFrameTracer tracer(&vm, exec);
1073
1074     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1075         return parseIntResult(parseInt(view, radix));
1076     });
1077 }
1078         
1079 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1080 {
1081     SuperSamplerScope superSamplerScope(false);
1082     
1083     VM& vm = globalObject->vm();
1084     NativeCallFrameTracer tracer(&vm, exec);
1085
1086     return regExpObject->testInline(exec, globalObject, input);
1087 }
1088
1089 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1090 {
1091     SuperSamplerScope superSamplerScope(false);
1092     
1093     VM& vm = globalObject->vm();
1094     NativeCallFrameTracer tracer(&vm, exec);
1095
1096     JSValue argument = JSValue::decode(encodedArgument);
1097
1098     JSString* input = argument.toStringOrNull(exec);
1099     if (!input)
1100         return false;
1101     return regExpObject->testInline(exec, globalObject, input);
1102 }
1103
1104 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1105 {
1106     SuperSamplerScope superSamplerScope(false);
1107     
1108     VM& vm = globalObject->vm();
1109     NativeCallFrameTracer tracer(&vm, exec);
1110     auto scope = DECLARE_THROW_SCOPE(vm);
1111
1112     JSValue base = JSValue::decode(encodedBase);
1113     JSValue argument = JSValue::decode(encodedArgument);
1114
1115     if (!base.inherits(vm, RegExpObject::info())) {
1116         throwTypeError(exec, scope);
1117         return false;
1118     }
1119
1120     JSString* input = argument.toStringOrNull(exec);
1121     EXCEPTION_ASSERT(!!scope.exception() == !input);
1122     if (!input)
1123         return false;
1124     scope.release();
1125     return asRegExpObject(base)->test(exec, globalObject, input);
1126 }
1127
1128 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1129 {
1130     VM* vm = &exec->vm();
1131     NativeCallFrameTracer tracer(vm, exec);
1132     
1133     JSValue op1 = JSValue::decode(encodedOp1);
1134     JSValue op2 = JSValue::decode(encodedOp2);
1135     
1136     ASSERT(op1.isCell());
1137     ASSERT(op2.isCell());
1138     
1139     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1140 }
1141
1142 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1143 {
1144     VM* vm = &exec->vm();
1145     NativeCallFrameTracer tracer(vm, exec);
1146
1147     JSValue src1 = JSValue::decode(encodedOp1);
1148     JSValue src2 = JSValue::decode(encodedOp2);
1149     
1150     return JSValue::strictEqual(exec, src1, src2);
1151 }
1152
1153 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1154 {
1155     VM* vm = &exec->vm();
1156     NativeCallFrameTracer tracer(vm, exec);
1157     
1158     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1159 }
1160
1161 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
1162 {
1163     VM* vm = &exec->vm();
1164     NativeCallFrameTracer tracer(vm, exec);
1165
1166     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
1167 }
1168
1169 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
1170 {
1171     VM& vm = exec->vm();
1172     NativeCallFrameTracer tracer(&vm, exec);
1173
1174     JSValue baseValue = JSValue::decode(encodedBase);
1175     JSValue thisVal = JSValue::decode(encodedThis);
1176     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1177     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
1178     return JSValue::encode(result);
1179 }
1180
1181 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1182 {
1183     VM& vm = exec->vm();
1184     NativeCallFrameTracer tracer(&vm, exec);
1185     auto scope = DECLARE_THROW_SCOPE(vm);
1186
1187     JSValue baseValue = JSValue::decode(encodedBase);
1188     JSValue thisVal = JSValue::decode(encodedThis);
1189     JSValue subscript = JSValue::decode(encodedSubscript);
1190
1191     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1192         Structure& structure = *baseValue.asCell()->structure(vm);
1193         if (JSCell::canUseFastGetOwnProperty(structure)) {
1194             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1195                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1196                     return JSValue::encode(result);
1197             }
1198         }
1199     }
1200     
1201     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1202     if (subscript.isUInt32()) {
1203         uint32_t i = subscript.asUInt32();
1204         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1205             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
1206         
1207         scope.release();
1208         return JSValue::encode(baseValue.get(exec, i, slot));
1209     }
1210
1211     baseValue.requireObjectCoercible(exec);
1212     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1213
1214     auto property = subscript.toPropertyKey(exec);
1215     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1216     scope.release();
1217     return JSValue::encode(baseValue.get(exec, property, slot));
1218 }
1219
1220 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1221 {
1222     VM& vm = exec->vm();
1223     NativeCallFrameTracer tracer(&vm, exec);
1224
1225     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1226 }
1227
1228 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1229 {
1230     VM& vm = exec->vm();
1231     NativeCallFrameTracer tracer(&vm, exec);
1232
1233     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1234 }
1235
1236 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1237 {
1238     VM& vm = exec->vm();
1239     NativeCallFrameTracer tracer(&vm, exec);
1240     auto scope = DECLARE_THROW_SCOPE(vm);
1241
1242     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1243     RETURN_IF_EXCEPTION(scope, void());
1244     scope.release();
1245     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1246 }
1247
1248 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1249 {
1250     VM& vm = exec->vm();
1251     NativeCallFrameTracer tracer(&vm, exec);
1252     auto scope = DECLARE_THROW_SCOPE(vm);
1253
1254     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1255     RETURN_IF_EXCEPTION(scope, void());
1256     scope.release();
1257     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1258 }
1259
1260 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1261 {
1262     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1263     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1264     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1265         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1266     else
1267         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1268 }
1269
1270 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1271 {
1272     VM& vm = exec->vm();
1273     NativeCallFrameTracer tracer(&vm, exec);
1274     auto scope = DECLARE_THROW_SCOPE(vm);
1275
1276     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1277     RETURN_IF_EXCEPTION(scope, void());
1278     scope.release();
1279     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1280 }
1281
1282 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1283 {
1284     VM& vm = exec->vm();
1285     NativeCallFrameTracer tracer(&vm, exec);
1286     auto scope = DECLARE_THROW_SCOPE(vm);
1287
1288     Identifier propertyName = property->toIdentifier(exec);
1289     RETURN_IF_EXCEPTION(scope, void());
1290     scope.release();
1291     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1292 }
1293
1294 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1295 {
1296     VM& vm = exec->vm();
1297     NativeCallFrameTracer tracer(&vm, exec);
1298     defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1299 }
1300
1301 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1302 {
1303     VM& vm = exec->vm();
1304     NativeCallFrameTracer tracer(&vm, exec);
1305     defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1306 }
1307
1308 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1309 {
1310     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1311     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1312     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1313         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1314     else
1315         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1316 }
1317
1318 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1319 {
1320     VM& vm = exec->vm();
1321     NativeCallFrameTracer tracer(&vm, exec);
1322     auto scope = DECLARE_THROW_SCOPE(vm);
1323
1324     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1325     RETURN_IF_EXCEPTION(scope, void());
1326     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1327 }
1328
1329 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1330 {
1331     VM& vm = exec->vm();
1332     NativeCallFrameTracer tracer(&vm, exec);
1333     auto scope = DECLARE_THROW_SCOPE(vm);
1334
1335     Identifier propertyName = property->toIdentifier(exec);
1336     RETURN_IF_EXCEPTION(scope, void());
1337     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1338 }
1339
1340 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* 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(&vm, property), getter, setter, attributes);
1345 }
1346
1347 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1348 {
1349     VM& vm = exec->vm();
1350     NativeCallFrameTracer tracer(&vm, exec);
1351     defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1352 }
1353
1354 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1355 {
1356     VM* vm = &exec->vm();
1357     NativeCallFrameTracer tracer(vm, exec);
1358     
1359     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1360 }
1361
1362 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1363 {
1364     VM* vm = &exec->vm();
1365     NativeCallFrameTracer tracer(vm, exec);
1366     
1367     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1368 }
1369
1370 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1371 {
1372     VM& vm = exec->vm();
1373     NativeCallFrameTracer tracer(&vm, exec);
1374     auto scope = DECLARE_THROW_SCOPE(vm);
1375
1376     if (UNLIKELY(size < 0))
1377         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1378
1379     JSArray* result;
1380     if (butterfly)
1381         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1382     else
1383         result = JSArray::create(vm, arrayStructure, size);
1384     return bitwise_cast<char*>(result);
1385 }
1386
1387 char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
1388 {
1389     VM& vm = exec->vm();
1390     NativeCallFrameTracer tracer(&vm, exec);
1391     auto scope = DECLARE_THROW_SCOPE(vm);
1392
1393     if (UNLIKELY(size < 0))
1394         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1395
1396     JSArray* result;
1397     if (butterfly)
1398         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1399     else {
1400         result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
1401         ASSERT(result);
1402     }
1403     return bitwise_cast<char*>(result);
1404 }
1405
1406 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1407 {
1408     VM& vm = exec->vm();
1409     NativeCallFrameTracer tracer(&vm, exec);
1410     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1411 }
1412
1413 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1414     ExecState* exec, Structure* structure, int32_t length, char* vector)
1415 {
1416     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1417 }
1418
1419 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1420     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1421 {
1422     VM& vm = exec->vm();
1423     NativeCallFrameTracer tracer(&vm, exec);
1424     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1425 }
1426
1427 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1428     ExecState* exec, Structure* structure, int32_t length, char* vector)
1429 {
1430     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1431 }
1432
1433 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1434     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1435 {
1436     VM& vm = exec->vm();
1437     NativeCallFrameTracer tracer(&vm, exec);
1438     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1439 }
1440
1441 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1442     ExecState* exec, Structure* structure, int32_t length, char* vector)
1443 {
1444     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1445 }
1446
1447 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1448     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1449 {
1450     VM& vm = exec->vm();
1451     NativeCallFrameTracer tracer(&vm, exec);
1452     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1453 }
1454
1455 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1456     ExecState* exec, Structure* structure, int32_t length, char* vector)
1457 {
1458     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1459 }
1460
1461 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1462     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1463 {
1464     VM& vm = exec->vm();
1465     NativeCallFrameTracer tracer(&vm, exec);
1466     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1467 }
1468
1469 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1470     ExecState* exec, Structure* structure, int32_t length, char* vector)
1471 {
1472     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1473 }
1474
1475 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1476     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1477 {
1478     VM& vm = exec->vm();
1479     NativeCallFrameTracer tracer(&vm, exec);
1480     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1481 }
1482
1483 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1484     ExecState* exec, Structure* structure, int32_t length, char* vector)
1485 {
1486     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1487 }
1488
1489 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1490     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1491 {
1492     VM& vm = exec->vm();
1493     NativeCallFrameTracer tracer(&vm, exec);
1494     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1495 }
1496
1497 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1498     ExecState* exec, Structure* structure, int32_t length, char* vector)
1499 {
1500     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1501 }
1502
1503 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1504     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1505 {
1506     VM& vm = exec->vm();
1507     NativeCallFrameTracer tracer(&vm, exec);
1508     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1509 }
1510
1511 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1512     ExecState* exec, Structure* structure, int32_t length, char* vector)
1513 {
1514     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1515 }
1516
1517 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1518     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1519 {
1520     VM& vm = exec->vm();
1521     NativeCallFrameTracer tracer(&vm, exec);
1522     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1523 }
1524
1525 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1526     ExecState* exec, Structure* structure, int32_t length, char* vector)
1527 {
1528     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1529 }
1530
1531 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1532     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1533 {
1534     VM& vm = exec->vm();
1535     NativeCallFrameTracer tracer(&vm, exec);
1536     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1537 }
1538
1539 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1540 {
1541     JSValue initialValue = JSValue::decode(initialValueEncoded);
1542     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1543     VM& vm = exec->vm();
1544     NativeCallFrameTracer tracer(&vm, exec);
1545     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1546 }
1547
1548 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1549 {
1550     VM& vm = exec->vm();
1551     NativeCallFrameTracer target(&vm, exec);
1552     DirectArguments* result = DirectArguments::create(
1553         vm, structure, length, std::max(length, minCapacity));
1554     // The caller will store to this object without barriers. Most likely, at this point, this is
1555     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1556     // since the GC should be allowed to do crazy (like pretenuring, for example).
1557     vm.heap.writeBarrier(result);
1558     return result;
1559 }
1560
1561 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1562 {
1563     VM& vm = exec->vm();
1564     NativeCallFrameTracer target(&vm, exec);
1565     
1566     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1567     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1568     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1569     
1570     return ScopedArguments::createByCopyingFrom(
1571         vm, structure, argumentStart, length, callee, table, scope);
1572 }
1573
1574 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1575 {
1576     VM& vm = exec->vm();
1577     NativeCallFrameTracer target(&vm, exec);
1578     return ClonedArguments::createByCopyingFrom(
1579         exec, structure, argumentStart, length, callee);
1580 }
1581
1582 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1583 {
1584     VM& vm = exec->vm();
1585     NativeCallFrameTracer target(&vm, exec);
1586     
1587     DeferGCForAWhile deferGC(vm.heap);
1588     
1589     CodeBlock* codeBlock;
1590     if (inlineCallFrame)
1591         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1592     else
1593         codeBlock = exec->codeBlock();
1594     
1595     unsigned length = argumentCount - 1;
1596     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1597     DirectArguments* result = DirectArguments::create(
1598         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1599     
1600     result->callee().set(vm, result, callee);
1601     
1602     Register* arguments =
1603         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1604         CallFrame::argumentOffset(0);
1605     for (unsigned i = length; i--;)
1606         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1607     
1608     return result;
1609 }
1610
1611 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1612 {
1613     VM& vm = exec->vm();
1614     NativeCallFrameTracer target(&vm, exec);
1615     
1616     DeferGCForAWhile deferGC(vm.heap);
1617     
1618     CodeBlock* codeBlock;
1619     if (inlineCallFrame)
1620         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1621     else
1622         codeBlock = exec->codeBlock();
1623     
1624     unsigned length = argumentCount - 1;
1625     ClonedArguments* result = ClonedArguments::createEmpty(
1626         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1627     
1628     Register* arguments =
1629         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1630         CallFrame::argumentOffset(0);
1631     for (unsigned i = length; i--;)
1632         result->putDirectIndex(exec, i, arguments[i].jsValue());
1633
1634     
1635     return result;
1636 }
1637
1638 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1639 {
1640     VM* vm = &exec->vm();
1641     NativeCallFrameTracer tracer(vm, exec);
1642
1643     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1644     Structure* structure = globalObject->restParameterStructure();
1645     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1646     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1647     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1648 }
1649
1650 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1651 {
1652     VM& vm = exec->vm();
1653     NativeCallFrameTracer tracer(&vm, exec);
1654
1655     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1656     
1657     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1658         return false;
1659     if (object->type() == JSFunctionType)
1660         return false;
1661     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1662         CallData callData;
1663         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1664             return false;
1665     }
1666     
1667     return true;
1668 }
1669
1670 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1671 {
1672     VM& vm = exec->vm();
1673     NativeCallFrameTracer tracer(&vm, exec);
1674
1675     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1676     
1677     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1678         return false;
1679     if (object->type() == JSFunctionType)
1680         return true;
1681     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1682         CallData callData;
1683         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1684             return true;
1685     }
1686     
1687     return false;
1688 }
1689
1690 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1691 {
1692     VM& vm = exec->vm();
1693     NativeCallFrameTracer tracer(&vm, exec);
1694
1695     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1696     
1697     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1698         return vm.smallStrings.undefinedString();
1699     if (object->type() == JSFunctionType)
1700         return vm.smallStrings.functionString();
1701     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1702         CallData callData;
1703         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1704             return vm.smallStrings.functionString();
1705     }
1706     
1707     return vm.smallStrings.objectString();
1708 }
1709
1710 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1711 {
1712     VM& vm = exec->vm();
1713     NativeCallFrameTracer tracer(&vm, exec);
1714
1715     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1716     
1717     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1718         return static_cast<int32_t>(TypeofType::Undefined);
1719     if (object->type() == JSFunctionType)
1720         return static_cast<int32_t>(TypeofType::Function);
1721     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1722         CallData callData;
1723         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1724             return static_cast<int32_t>(TypeofType::Function);
1725     }
1726     
1727     return static_cast<int32_t>(TypeofType::Object);
1728 }
1729
1730 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1731 {
1732     VM& vm = exec->vm();
1733     NativeCallFrameTracer tracer(&vm, exec);
1734
1735     return reinterpret_cast<char*>(
1736         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1737 }
1738
1739 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1740 {
1741     VM& vm = exec->vm();
1742     NativeCallFrameTracer tracer(&vm, exec);
1743
1744     return reinterpret_cast<char*>(
1745         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1746 }
1747
1748 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1749 {
1750     VM& vm = exec->vm();
1751     NativeCallFrameTracer tracer(&vm, exec);
1752
1753     ASSERT(!object->structure()->outOfLineCapacity());
1754     return reinterpret_cast<char*>(
1755         object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1756 }
1757
1758 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1759 {
1760     VM& vm = exec->vm();
1761     NativeCallFrameTracer tracer(&vm, exec);
1762
1763     return reinterpret_cast<char*>(
1764         object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize));
1765 }
1766
1767 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1768 {
1769     VM& vm = exec->vm();
1770     NativeCallFrameTracer tracer(&vm, exec);
1771     
1772     if (!cell->isObject())
1773         return 0;
1774     
1775     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1776 }
1777
1778 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1779 {
1780     VM& vm = exec->vm();
1781     NativeCallFrameTracer tracer(&vm, exec);
1782     
1783     if (!cell->isObject())
1784         return 0;
1785     
1786     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1787 }
1788
1789 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1790 {
1791     VM& vm = exec->vm();
1792     NativeCallFrameTracer tracer(&vm, exec);
1793     
1794     if (!cell->isObject())
1795         return 0;
1796     
1797     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1798 }
1799
1800 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1801 {
1802     VM& vm = exec->vm();
1803     NativeCallFrameTracer tracer(&vm, exec);
1804     
1805     if (!cell->isObject())
1806         return 0;
1807
1808     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1809 }
1810
1811 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
1812 {
1813     VM& vm = exec->vm();
1814     NativeCallFrameTracer tracer(&vm, exec);
1815     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1816     if (UNLIKELY(subscript < 0)) {
1817         // Go the slowest way possible because negative indices don't use indexed storage.
1818         return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
1819     }
1820     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType))));
1821 }
1822
1823 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1824 {
1825     VM& vm = exec->vm();
1826     NativeCallFrameTracer tracer(&vm, exec);
1827
1828     return string->value(exec).impl();
1829 }
1830
1831 JSCell* JIT_OPERATION operationStringSubstr(ExecState* exec, JSCell* cell, int32_t from, int32_t span)
1832 {
1833     VM& vm = exec->vm();
1834     NativeCallFrameTracer tracer(&vm, exec);
1835     auto scope = DECLARE_THROW_SCOPE(vm);
1836
1837     auto string = jsCast<JSString*>(cell)->value(exec);
1838     RETURN_IF_EXCEPTION(scope, nullptr);
1839     return jsSubstring(exec, string, from, span);
1840 }
1841
1842 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
1843 {
1844     VM& vm = exec->vm();
1845     NativeCallFrameTracer tracer(&vm, exec);
1846
1847     auto scope = DECLARE_THROW_SCOPE(vm);
1848
1849     const String& inputString = string->value(exec);
1850     RETURN_IF_EXCEPTION(scope, nullptr);
1851     if (!inputString.length())
1852         return vm.smallStrings.emptyString();
1853
1854     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
1855     if (lowercasedString.impl() == inputString.impl())
1856         return string;
1857     scope.release();
1858     return jsString(exec, lowercasedString);
1859 }
1860
1861 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
1862 {
1863     VM& vm = exec->vm();
1864     NativeCallFrameTracer tracer(&vm, exec);
1865
1866     auto scope = DECLARE_THROW_SCOPE(vm);
1867
1868     if (radix < 2 || radix > 36) {
1869         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1870         return nullptr;
1871     }
1872
1873     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1874 }
1875
1876 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
1877 {
1878     VM& vm = exec->vm();
1879     NativeCallFrameTracer tracer(&vm, exec);
1880
1881     auto scope = DECLARE_THROW_SCOPE(vm);
1882
1883     if (radix < 2 || radix > 36) {
1884         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1885         return nullptr;
1886     }
1887
1888     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1889 }
1890
1891 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
1892 {
1893     VM& vm = exec->vm();
1894     NativeCallFrameTracer tracer(&vm, exec);
1895
1896     auto scope = DECLARE_THROW_SCOPE(vm);
1897
1898     if (radix < 2 || radix > 36) {
1899         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1900         return nullptr;
1901     }
1902
1903     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1904 }
1905
1906 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
1907 {
1908     VM& vm = exec->vm();
1909     NativeCallFrameTracer tracer(&vm, exec);
1910
1911     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1912 }
1913
1914 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
1915 {
1916     VM& vm = exec->vm();
1917     NativeCallFrameTracer tracer(&vm, exec);
1918
1919     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1920 }
1921
1922 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
1923 {
1924     VM& vm = exec->vm();
1925     NativeCallFrameTracer tracer(&vm, exec);
1926
1927     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1928 }
1929
1930 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1931 {
1932     VM& vm = exec->vm();
1933     NativeCallFrameTracer tracer(&vm, exec);
1934     
1935     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1936 }
1937
1938 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1939 {
1940     VM& vm = exec->vm();
1941     NativeCallFrameTracer tracer(&vm, exec);
1942     
1943     return StringObject::create(vm, structure, string);
1944 }
1945
1946 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1947 {
1948     VM& vm = exec->vm();
1949     NativeCallFrameTracer tracer(&vm, exec);
1950     
1951     return JSValue(cell).toString(exec);
1952 }
1953
1954 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1955 {
1956     VM& vm = exec->vm();
1957     NativeCallFrameTracer tracer(&vm, exec);
1958
1959     return JSValue::decode(value).toString(exec);
1960 }
1961
1962 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1963 {
1964     VM& vm = exec->vm();
1965     NativeCallFrameTracer tracer(&vm, exec);
1966
1967     return stringConstructor(exec, cell);
1968 }
1969
1970 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1971 {
1972     VM& vm = exec->vm();
1973     NativeCallFrameTracer tracer(&vm, exec);
1974
1975     return stringConstructor(exec, JSValue::decode(value));
1976 }
1977
1978 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1979 {
1980     VM& vm = exec->vm();
1981     NativeCallFrameTracer tracer(&vm, exec);
1982
1983     return jsString(exec, left, right);
1984 }
1985
1986 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1987 {
1988     VM& vm = exec->vm();
1989     NativeCallFrameTracer tracer(&vm, exec);
1990
1991     return jsString(exec, a, b, c);
1992 }
1993
1994 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1995 {
1996     VM& vm = exec->vm();
1997     NativeCallFrameTracer tracer(&vm, exec);
1998     auto scope = DECLARE_THROW_SCOPE(vm);
1999
2000     ASSERT(!JSValue::decode(a).isSymbol());
2001     ASSERT(!JSValue::decode(b).isSymbol());
2002     JSString* str1 = JSValue::decode(a).toString(exec);
2003     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2004     JSString* str2 = JSValue::decode(b).toString(exec);
2005     scope.assertNoException();
2006
2007     scope.release();
2008     return jsString(exec, str1, str2);
2009 }
2010     
2011 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2012 {
2013     VM& vm = exec->vm();
2014     NativeCallFrameTracer tracer(&vm, exec);
2015     auto scope = DECLARE_THROW_SCOPE(vm);
2016
2017     ASSERT(!JSValue::decode(a).isSymbol());
2018     ASSERT(!JSValue::decode(b).isSymbol());
2019     ASSERT(!JSValue::decode(c).isSymbol());
2020     JSString* str1 = JSValue::decode(a).toString(exec);
2021     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2022     JSString* str2 = JSValue::decode(b).toString(exec);
2023     scope.assertNoException();
2024     JSString* str3 = JSValue::decode(c).toString(exec);
2025     scope.assertNoException();
2026
2027     scope.release();
2028     return jsString(exec, str1, str2, str3);
2029 }
2030
2031 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
2032     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
2033 {
2034     VM& vm = exec->vm();
2035     NativeCallFrameTracer tracer(&vm, exec);
2036
2037     CodeBlock* codeBlock = exec->codeBlock();
2038     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2039     JSValue value = JSValue::decode(encodedValue);
2040     ASSERT(value.isDouble());
2041     double asDouble = value.asDouble();
2042     int32_t asInt32 = static_cast<int32_t>(asDouble);
2043     if (asDouble == asInt32)
2044         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
2045     return static_cast<char*>(table.ctiDefault.executableAddress());
2046 }
2047
2048 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
2049 {
2050     VM& vm = exec->vm();
2051     NativeCallFrameTracer tracer(&vm, exec);
2052
2053     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
2054 }
2055
2056 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
2057 {
2058     VM& vm = exec->vm();
2059     NativeCallFrameTracer tracer(&vm, exec);
2060
2061     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
2062 }
2063
2064 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2065 {
2066     return codePointCompare(a, b) < 0;
2067 }
2068
2069 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2070 {
2071     return codePointCompare(a, b) <= 0;
2072 }
2073
2074 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2075 {
2076     return codePointCompare(a, b) > 0;
2077 }
2078
2079 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2080 {
2081     return codePointCompare(a, b) >= 0;
2082 }
2083
2084 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
2085 {
2086     VM& vm = exec->vm();
2087     NativeCallFrameTracer tracer(&vm, exec);
2088
2089     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2090 }
2091
2092 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
2093 {
2094     VM& vm = exec->vm();
2095     NativeCallFrameTracer tracer(&vm, exec);
2096
2097     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2098 }
2099
2100 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
2101 {
2102     VM& vm = exec->vm();
2103     NativeCallFrameTracer tracer(&vm, exec);
2104
2105     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2106 }
2107
2108 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
2109 {
2110     VM& vm = exec->vm();
2111     NativeCallFrameTracer tracer(&vm, exec);
2112
2113     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2114 }
2115
2116 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
2117 {
2118     VM& vm = exec->vm();
2119     NativeCallFrameTracer tracer(&vm, exec);
2120
2121     set->touch(vm, "Executed NotifyWrite");
2122 }
2123
2124 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2125 {
2126     VM& vm = exec->vm();
2127     NativeCallFrameTracer tracer(&vm, exec);
2128     auto scope = DECLARE_THROW_SCOPE(vm);
2129     throwStackOverflowError(exec, scope);
2130 }
2131
2132 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
2133 {
2134     VM& vm = exec->vm();
2135     NativeCallFrameTracer tracer(&vm, exec);
2136     JSValue arguments = JSValue::decode(encodedArguments);
2137     
2138     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2139 }
2140
2141 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2142 {
2143     VM& vm = exec->vm();
2144     NativeCallFrameTracer tracer(&vm, exec);
2145     auto scope = DECLARE_THROW_SCOPE(vm);
2146
2147     JSValue key = JSValue::decode(encodedKey);
2148     Identifier propertyName = key.toPropertyKey(exec);
2149     RETURN_IF_EXCEPTION(scope, false);
2150
2151     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2152     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2153     RETURN_IF_EXCEPTION(scope, false);
2154
2155     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2156     ASSERT(hasOwnPropertyCache);
2157     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2158     return result;
2159 }
2160
2161 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2162 {
2163     VM& vm = exec->vm();
2164     NativeCallFrameTracer tracer(&vm, exec);
2165     auto scope = DECLARE_THROW_SCOPE(vm);
2166
2167     int32_t length = butterfly->publicLength();
2168     auto data = butterfly->contiguous().data();
2169     for (; index < length; ++index) {
2170         JSValue value = data[index].get();
2171         if (!value || !value.isString())
2172             continue;
2173         auto* string = asString(value);
2174         if (string == searchElement)
2175             return index;
2176         if (string->equal(exec, searchElement))
2177             return index;
2178         RETURN_IF_EXCEPTION(scope, { });
2179     }
2180     return -1;
2181 }
2182
2183 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2184 {
2185     VM& vm = exec->vm();
2186     NativeCallFrameTracer tracer(&vm, exec);
2187     auto scope = DECLARE_THROW_SCOPE(vm);
2188
2189     JSValue searchElement = JSValue::decode(encodedValue);
2190
2191     int32_t length = butterfly->publicLength();
2192     auto data = butterfly->contiguous().data();
2193     for (; index < length; ++index) {
2194         JSValue value = data[index].get();
2195         if (!value)
2196             continue;
2197         if (JSValue::strictEqual(exec, searchElement, value))
2198             return index;
2199         RETURN_IF_EXCEPTION(scope, { });
2200     }
2201     return -1;
2202 }
2203
2204 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2205 {
2206     VM& vm = exec->vm();
2207     NativeCallFrameTracer tracer(&vm, exec);
2208
2209     JSValue searchElement = JSValue::decode(encodedValue);
2210
2211     if (!searchElement.isNumber())
2212         return -1;
2213     double number = searchElement.asNumber();
2214
2215     int32_t length = butterfly->publicLength();
2216     const double* data = butterfly->contiguousDouble().data();
2217     for (; index < length; ++index) {
2218         // This comparison ignores NaN.
2219         if (data[index] == number)
2220             return index;
2221     }
2222     return -1;
2223 }
2224
2225 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
2226 {
2227     VM& vm = exec->vm();
2228     NativeCallFrameTracer tracer(&vm, exec);
2229     JSValue arguments = JSValue::decode(encodedArguments);
2230     
2231     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2232     
2233     for (int32_t i = length; i < mandatoryMinimum; ++i)
2234         exec->r(firstElementDest + i) = jsUndefined();
2235 }
2236
2237 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2238 {
2239     return fmod(a, b);
2240 }
2241
2242 #if USE(JSVALUE32_64)
2243 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2244 {
2245     return globalObject->weakRandomNumber();
2246 }
2247 #endif
2248
2249 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2250 {
2251     VM* vm = &exec->vm();
2252     NativeCallFrameTracer tracer(vm, exec);
2253     return JSC::stringFromCharCode(exec, op1);
2254 }
2255
2256 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2257 {
2258     VM* vm = &exec->vm();
2259     NativeCallFrameTracer tracer(vm, exec);
2260     JSValue charValue = JSValue::decode(encodedValue);
2261     int32_t chInt = charValue.toUInt32(exec);
2262     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2263 }
2264
2265 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2266 {
2267     JSValue value = JSValue::decode(encodedValue);
2268     if (!value.isDouble())
2269         return JSValue::notInt52;
2270     return tryConvertToInt52(value.asDouble());
2271 }
2272
2273 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2274 {
2275     return tryConvertToInt52(value);
2276 }
2277
2278 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
2279 {
2280     VM* vm = &exec->vm();
2281     NativeCallFrameTracer tracer(vm, exec);
2282     if (JSObject::defaultHasInstance(exec, value, proto))
2283         return 1;
2284     return 0;
2285 }
2286
2287 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2288 {
2289     VM& vm = exec->vm();
2290     NativeCallFrameTracer tracer(&vm, exec);
2291
2292     if (!butterfly
2293         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2294         IndexingHeader header;
2295         header.setVectorLength(length);
2296         header.setPublicLength(0);
2297         
2298         butterfly = Butterfly::create(
2299             vm, nullptr, 0, structure->outOfLineCapacity(),
2300             hasIndexedProperties(structure->indexingType()), header,
2301             length * sizeof(EncodedJSValue));
2302     }
2303
2304     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2305     result->butterfly(); // Ensure that the butterfly is in to-space.
2306     return bitwise_cast<char*>(result);
2307 }
2308
2309 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2310 {
2311     VM& vm = exec->vm();
2312     NativeCallFrameTracer tracer(&vm, exec);
2313     
2314     if (!butterfly) {
2315         butterfly = Butterfly::create(
2316             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2317     }
2318     
2319     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2320     result->butterfly(); // Ensure that the butterfly is in to-space.
2321     return result;
2322 }
2323
2324 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2325 {
2326     VM& vm = exec->vm();
2327     NativeCallFrameTracer tracer(&vm, exec);
2328
2329     IndexingHeader header;
2330     header.setVectorLength(length);
2331     header.setPublicLength(0);
2332     if (butterfly)
2333         *butterfly->indexingHeader() = header;
2334     else {
2335         butterfly = Butterfly::create(
2336             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2337             sizeof(EncodedJSValue) * length);
2338     }
2339     
2340     // Paradoxically this may allocate a JSArray. That's totally cool.
2341     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2342     result->butterfly(); // Ensure that the butterfly is in to-space.
2343     return result;
2344 }
2345
2346 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2347 {
2348     VM& vm = exec->vm();
2349     NativeCallFrameTracer tracer(&vm, exec);
2350     auto scope = DECLARE_THROW_SCOPE(vm);
2351
2352     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2353     Checked<unsigned, RecordOverflow> checkedLength = 0;
2354     for (unsigned i = 0; i < numItems; i++) {
2355         JSValue value = JSValue::decode(values[i]);
2356         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2357             checkedLength += array->size();
2358         else
2359             ++checkedLength;
2360     }
2361
2362     if (UNLIKELY(checkedLength.hasOverflowed())) {
2363         throwOutOfMemoryError(exec, scope);
2364         return nullptr;
2365     }
2366
2367     unsigned length = checkedLength.unsafeGet();
2368     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2369     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2370
2371     JSArray* result = JSArray::tryCreate(vm, structure, length);
2372     if (UNLIKELY(!result)) {
2373         throwOutOfMemoryError(exec, scope);
2374         return nullptr;
2375     }
2376     RETURN_IF_EXCEPTION(scope, nullptr);
2377
2378     unsigned index = 0;
2379     for (unsigned i = 0; i < numItems; i++) {
2380         JSValue value = JSValue::decode(values[i]);
2381         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2382             // We are spreading.
2383             for (unsigned i = 0; i < array->size(); i++) {
2384                 result->putDirectIndex(exec, index, array->get(i));
2385                 RETURN_IF_EXCEPTION(scope, nullptr);
2386                 ++index;
2387             }
2388         } else {
2389             // We are not spreading.
2390             result->putDirectIndex(exec, index, value);
2391             RETURN_IF_EXCEPTION(scope, nullptr);
2392             ++index;
2393         }
2394     }
2395
2396     return result;
2397 }
2398
2399 JSCell* operationCreateFixedArray(ExecState* exec, unsigned length)
2400 {
2401     VM& vm = exec->vm();
2402     NativeCallFrameTracer tracer(&vm, exec);
2403     auto scope = DECLARE_THROW_SCOPE(vm);
2404
2405     if (JSFixedArray* result = JSFixedArray::tryCreate(vm, vm.fixedArrayStructure.get(), length))
2406         return result;
2407
2408     throwOutOfMemoryError(exec, scope);
2409     return nullptr;
2410 }
2411
2412 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2413 {
2414     VM& vm = exec->vm();
2415     NativeCallFrameTracer tracer(&vm, exec);
2416
2417     auto throwScope = DECLARE_THROW_SCOPE(vm);
2418
2419     if (isJSArray(iterable)) {
2420         JSArray* array = jsCast<JSArray*>(iterable);
2421         if (array->isIteratorProtocolFastAndNonObservable()) {
2422             throwScope.release();
2423             return JSFixedArray::createFromArray(exec, vm, array);
2424         }
2425     }
2426
2427     // FIXME: we can probably make this path faster by having our caller JS code call directly into
2428     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2429
2430     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2431     JSArray* array;
2432     {
2433         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2434         CallData callData;
2435         CallType callType = JSC::getCallData(iterationFunction, callData);
2436         ASSERT(callType != CallType::None);
2437
2438         MarkedArgumentBuffer arguments;
2439         arguments.append(iterable);
2440         ASSERT(!arguments.hasOverflowed());
2441         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2442         RETURN_IF_EXCEPTION(throwScope, nullptr);
2443         array = jsCast<JSArray*>(arrayResult);
2444     }
2445
2446     throwScope.release();
2447     return JSFixedArray::createFromArray(exec, vm, array);
2448 }
2449
2450 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2451 {
2452     VM& vm = exec->vm();
2453     NativeCallFrameTracer tracer(&vm, exec);
2454
2455     ASSERT(isJSArray(cell));
2456     JSArray* array = jsCast<JSArray*>(cell);
2457     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2458
2459     return JSFixedArray::createFromArray(exec, vm, array);
2460 }
2461
2462 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2463 {
2464     VM& vm = exec->vm();
2465     NativeCallFrameTracer tracer(&vm, exec);
2466
2467     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
2468 }
2469
2470 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2471 {
2472     VM& vm = exec->vm();
2473     NativeCallFrameTracer tracer(&vm, exec);
2474         
2475     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2476     return JSValue::encode(resolvedScope);
2477 }
2478     
2479 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2480 {
2481     VM& vm = exec->vm();
2482     NativeCallFrameTracer tracer(&vm, exec);
2483
2484     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2485     return resolvedScope;
2486 }
2487
2488 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2489 {
2490     VM& vm = exec->vm();
2491     NativeCallFrameTracer tracer(&vm, exec);
2492     auto throwScope = DECLARE_THROW_SCOPE(vm);
2493
2494     Identifier ident = Identifier::fromUid(exec, impl);
2495     throwScope.release();
2496     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2497         if (!found) {
2498             GetPutInfo getPutInfo(getPutInfoBits);
2499             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2500                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2501             return jsUndefined();
2502         }
2503
2504         if (scope->isGlobalLexicalEnvironment()) {
2505             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2506             JSValue result = slot.getValue(exec, ident);
2507             if (result == jsTDZValue()) {
2508                 throwException(exec, throwScope, createTDZError(exec));
2509                 return jsUndefined();
2510             }
2511             return result;
2512         }
2513
2514         return slot.getValue(exec, ident);
2515     }));
2516 }
2517
2518 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2519 {
2520     VM& vm = exec->vm();
2521     NativeCallFrameTracer tracer(&vm, exec);
2522     auto throwScope = DECLARE_THROW_SCOPE(vm);
2523
2524     const Identifier& ident = Identifier::fromUid(exec, impl);
2525     GetPutInfo getPutInfo(getPutInfoBits);
2526     bool hasProperty = scope->hasProperty(exec, ident);
2527     RETURN_IF_EXCEPTION(throwScope, void());
2528     if (hasProperty
2529         && scope->isGlobalLexicalEnvironment()
2530         && !isInitialization(getPutInfo.initializationMode())) {
2531         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2532         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2533         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2534         if (slot.getValue(exec, ident) == jsTDZValue()) {
2535             throwException(exec, throwScope, createTDZError(exec));
2536             return;
2537         }
2538     }
2539
2540     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2541         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2542         return;
2543     }
2544
2545     CodeOrigin origin = exec->codeOrigin();
2546     bool strictMode;
2547     if (origin.inlineCallFrame)
2548         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2549     else
2550         strictMode = exec->codeBlock()->isStrictMode();
2551     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2552     throwScope.release();
2553     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2554 }
2555
2556 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2557 {
2558     VM& vm = exec->vm();
2559     NativeCallFrameTracer tracer(&vm, exec);
2560
2561     return jsMapHash(exec, vm, JSValue::decode(input));
2562 }
2563
2564 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2565 {
2566     VM& vm = exec->vm();
2567     NativeCallFrameTracer tracer(&vm, exec);
2568     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
2569     if (!bucket)
2570         return vm.sentinelMapBucket.get();
2571     return *bucket;
2572 }
2573
2574 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2575 {
2576     VM& vm = exec->vm();
2577     NativeCallFrameTracer tracer(&vm, exec);
2578     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
2579     if (!bucket)
2580         return vm.sentinelSetBucket.get();
2581     return *bucket;
2582 }
2583
2584 void JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
2585 {
2586     VM& vm = exec->vm();
2587     NativeCallFrameTracer tracer(&vm, exec);
2588     jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
2589 }
2590
2591 void JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
2592 {
2593     VM& vm = exec->vm();
2594     NativeCallFrameTracer tracer(&vm, exec);
2595     jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
2596 }
2597
2598 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
2599 {
2600     VM& vm = exec->vm();
2601     NativeCallFrameTracer tracer(&vm, exec);
2602     return JSValue::encode(thisObject->getPrototype(vm, exec));
2603 }
2604
2605 EncodedJSValue JIT_OPERATION operationGetPrototypeOf(ExecState* exec, EncodedJSValue encodedValue)
2606 {
2607     VM& vm = exec->vm();
2608     NativeCallFrameTracer tracer(&vm, exec);
2609     auto scope = DECLARE_THROW_SCOPE(vm);
2610
2611     JSValue thisValue = JSValue::decode(encodedValue).toThis(exec, StrictMode);
2612     if (thisValue.isUndefinedOrNull())
2613         return throwVMError(exec, scope, createNotAnObjectError(exec, thisValue));
2614
2615     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
2616     if (!thisObject) {
2617         JSObject* prototype = thisValue.synthesizePrototype(exec);
2618         EXCEPTION_ASSERT(!!scope.exception() == !prototype);
2619         if (UNLIKELY(!prototype))
2620             return JSValue::encode(JSValue());
2621         return JSValue::encode(prototype);
2622     }
2623
2624     scope.release();
2625     return JSValue::encode(thisObject->getPrototype(vm, exec));
2626 }
2627
2628 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2629 {
2630     VM& vm = exec->vm();
2631     NativeCallFrameTracer tracer(&vm, exec);
2632     auto scope = DECLARE_THROW_SCOPE(vm);
2633     scope.throwException(exec, JSValue::decode(valueToThrow));
2634 }
2635
2636 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2637 {
2638     VM& vm = exec->vm();
2639     NativeCallFrameTracer tracer(&vm, exec);
2640     auto scope = DECLARE_THROW_SCOPE(vm);
2641     String errorMessage = message->value(exec);
2642     scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2643 }
2644
2645 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
2646 {
2647     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2648     // really be profitable.
2649     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2650     
2651     sanitizeStackForVM(codeBlock->vm());
2652
2653     if (Options::verboseOSR())
2654         dataLog(*codeBlock, ": Entered reoptimize\n");
2655     // We must be called with the baseline code block.
2656     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2657
2658     // If I am my own replacement, then reoptimization has already been triggered.
2659     // This can happen in recursive functions.
2660     if (codeBlock->replacement() == codeBlock) {
2661         if (Options::verboseOSR())
2662             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2663         return;
2664     }
2665     
2666     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2667     // to check our logic.
2668     ASSERT(codeBlock->hasOptimizedReplacement());
2669     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2670     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2671     
2672     bool didTryToEnterIntoInlinedLoops = false;
2673     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2674         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2675             didTryToEnterIntoInlinedLoops = true;
2676             break;
2677         }
2678     }
2679
2680     // In order to trigger reoptimization, one of two things must have happened:
2681     // 1) We exited more than some number of times.
2682     // 2) We exited and got stuck in a loop, and now we're exiting again.
2683     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2684     bool didGetStuckInLoop =
2685         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2686         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2687     
2688     if (!didExitABunch && !didGetStuckInLoop) {
2689         if (Options::verboseOSR())
2690             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2691         codeBlock->optimizeAfterLongWarmUp();
2692         return;
2693     }
2694
2695     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2696 }
2697
2698 #if ENABLE(FTL_JIT)
2699 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2700 {
2701     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2702         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2703         if (Options::verboseOSR())
2704             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2705         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2706         return false;
2707     }
2708
2709     if (!codeBlock->hasOptimizedReplacement()
2710         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2711         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2712         if (Options::verboseOSR())
2713             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2714         return false;
2715     }
2716     return true;
2717 }
2718
2719 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2720 {
2721     if (codeBlock->codeType() == GlobalCode) {
2722         // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2723         // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2724         // later want to run faster code. Deferring for warm-up seems safest.
2725         jitCode->optimizeAfterWarmUp(codeBlock);
2726         return;
2727     }
2728     
2729     Worklist::State worklistState;
2730     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2731         worklistState = worklist->completeAllReadyPlansForVM(
2732             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2733     } else
2734         worklistState = Worklist::NotKnown;
2735     
2736     if (worklistState == Worklist::Compiling) {
2737         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2738         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2739             codeBlock, CompilationDeferred);
2740         return;
2741     }
2742     
2743     if (codeBlock->hasOptimizedReplacement()) {
2744         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2745         // That's great, we've compiled the code - next time we call this function,
2746         // we'll enter that replacement.
2747         jitCode->optimizeSoon(codeBlock);
2748         return;
2749     }
2750     
2751     if (worklistState == Worklist::Compiled) {
2752         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2753         // This means that we finished compiling, but failed somehow; in that case the
2754         // thresholds will be set appropriately.
2755         if (Options::verboseOSR())
2756             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2757         return;
2758     }
2759
2760     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2761     // We need to compile the code.
2762     compile(
2763         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2764         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2765
2766     // If we reached here, the counter has not be reset. Do that now.
2767     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2768         codeBlock, CompilationDeferred);
2769 }
2770
2771 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2772 {
2773     VM* vm = &exec->vm();
2774     NativeCallFrameTracer tracer(vm, exec);
2775     DeferGCForAWhile deferGC(vm->heap);
2776     CodeBlock* codeBlock = exec->codeBlock();
2777     
2778     sanitizeStackForVM(vm);
2779
2780     if (codeBlock->jitType() != JITCode::DFGJIT) {
2781         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2782         RELEASE_ASSERT_NOT_REACHED();
2783     }
2784     
2785     JITCode* jitCode = codeBlock->jitCode()->dfg();
2786     
2787     if (Options::verboseOSR()) {
2788         dataLog(
2789             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2790             jitCode->tierUpCounter, "\n");
2791     }
2792
2793     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2794         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2795
2796     if (codeBlock->hasOptimizedReplacement()) {
2797         if (jitCode->tierUpEntryTriggers.isEmpty()) {
2798             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2799             // There is nothing more we can do, the only way this will be entered
2800             // is through the function entry point.
2801             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2802             return;
2803         }
2804         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2805             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2806             // There is only one outer loop and its trigger must have been set
2807             // when the plan completed.
2808             // Exiting the inner loop is useless, we can ignore the counter and leave
2809             // the trigger do its job.
2810             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2811             return;
2812         }
2813     }
2814 }
2815
2816 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
2817 {
2818     VM* vm = &exec->vm();
2819     CodeBlock* codeBlock = exec->codeBlock();
2820
2821     // Resolve any pending plan for OSR Enter on this function.
2822     Worklist::State worklistState;
2823     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2824         worklistState = worklist->completeAllReadyPlansForVM(
2825             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2826     } else
2827         worklistState = Worklist::NotKnown;
2828
2829     JITCode* jitCode = codeBlock->jitCode()->dfg();
2830
2831     // The following is only true for triggerTierUpNowInLoop, which can never
2832     // be an OSR entry.
2833     bool canOSRFromHere = originBytecodeIndex == osrEntryBytecodeIndex;
2834     
2835     bool triggeredSlowPathToStartCompilation = false;
2836     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
2837     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
2838         switch (tierUpEntryTriggers->value) {
2839         case JITCode::TriggerReason::DontTrigger:
2840             // The trigger isn't set, we entered because the counter reached its
2841             // threshold.
2842             break;
2843
2844         case JITCode::TriggerReason::CompilationDone:
2845             // The trigger was set because compilation completed. Don't unset it
2846             // so that further DFG executions OSR enters as well.
2847             RELEASE_ASSERT(canOSRFromHere);
2848             break;
2849
2850         case JITCode::TriggerReason::StartCompilation:
2851             // We were asked to enter as soon as possible and start compiling an
2852             // entry for the current bytecode location. Unset this trigger so we
2853             // don't continually enter.
2854             RELEASE_ASSERT(canOSRFromHere);
2855             tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
2856             triggeredSlowPathToStartCompilation = true;
2857             break;
2858         }
2859     }
2860
2861     if (worklistState == Worklist::Compiling) {
2862         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2863         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2864             codeBlock, CompilationDeferred);
2865         return nullptr;
2866     }
2867
2868     if (worklistState == Worklist::Compiled) {
2869         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2870         // This means that compilation failed and we already set the thresholds.
2871         if (Options::verboseOSR())
2872             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2873         return nullptr;
2874     }
2875
2876     // If we can OSR Enter, do it right away.
2877     if (canOSRFromHere) {
2878         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
2879         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2880             if (Options::verboseOSR())
2881                 dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
2882             if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
2883                 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
2884                 return static_cast<char*>(address);
2885             }
2886         }
2887     }
2888
2889     // - If we don't have an FTL code block, then try to compile one.
2890     // - If we do have an FTL code block, then try to enter for a while.
2891     // - If we couldn't enter for a while, then trigger OSR entry.
2892
2893     if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
2894         return nullptr;
2895
2896     if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
2897         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2898
2899         if (!codeBlock->hasOptimizedReplacement())
2900             return nullptr;
2901
2902         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2903             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2904             jitCode->osrEntryRetry++;
2905             return nullptr;
2906         }
2907     } else
2908         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2909
2910     // It's time to try to compile code for OSR entry.
2911     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2912         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2913             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2914             jitCode->osrEntryRetry++;
2915             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2916                 codeBlock, CompilationDeferred);
2917             return nullptr;
2918         }
2919
2920         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
2921         entryCode->countEntryFailure();
2922         if (entryCode->entryFailureCount() <
2923             Options::ftlOSREntryFailureCountForReoptimization()) {
2924             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2925             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2926                 codeBlock, CompilationDeferred);
2927             return nullptr;
2928         }
2929
2930         // OSR entry failed. Oh no! This implies that we need to retry. We retry
2931         // without exponential backoff and we only do this for the entry code block.
2932         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2933         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2934         jitCode->clearOSREntryBlock();
2935         jitCode->osrEntryRetry = 0;
2936         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
2937         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2938             codeBlock, CompilationDeferred);
2939         return nullptr;
2940     }
2941
2942     if (!canOSRFromHere) {
2943         // We can't OSR from here, or even start a compilation because doing so
2944         // calls jitCode->reconstruct which would get the wrong state.
2945         if (Options::verboseOSR())
2946             dataLog("Non-OSR-able bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryBytecodeIndex, "'s trigger and backing off.\n");
2947         jitCode->tierUpEntryTriggers.set(osrEntryBytecodeIndex, JITCode::TriggerReason::StartCompilation);
2948         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2949         return nullptr;
2950     }
2951
2952     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2953
2954     if (!triggeredSlowPathToStartCompilation) {
2955         auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
2956         if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
2957             for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
2958                 if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
2959                     // Ask an enclosing loop to compile, instead of doing so here.
2960                     if (Options::verboseOSR())
2961                         dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
2962                     jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
2963                     jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2964                     return nullptr;
2965                 }
2966             }
2967         }
2968     }
2969
2970     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
2971     // something.
2972     auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
2973     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
2974     JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
2975
2976     Operands<JSValue> mustHandleValues;
2977     jitCode->reconstruct(
2978         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
2979     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2980
2981     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
2982     CompilationResult forEntryResult = compile(
2983         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
2984         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
2985
2986     if (jitCode->neverExecutedEntry)
2987         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2988
2989     if (forEntryResult != CompilationSuccessful) {
2990         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
2991         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2992             codeBlock, CompilationDeferred);
2993         return nullptr;
2994     }
2995     
2996     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
2997     // It's possible that the for-entry compile already succeeded. In that case OSR
2998     // entry will succeed unless we ran out of stack. It's not clear what we should do.
2999     // We signal to try again after a while if that happens.
3000     if (Options::verboseOSR())
3001         dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
3002     void* address = FTL::prepareOSREntry(
3003         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
3004     return static_cast<char*>(address);
3005 }
3006
3007 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
3008 {
3009     VM* vm = &exec->vm();
3010     NativeCallFrameTracer tracer(vm, exec);
3011     DeferGCForAWhile deferGC(vm->heap);
3012     CodeBlock* codeBlock = exec->codeBlock();
3013
3014     sanitizeStackForVM(vm);
3015
3016     if (codeBlock->jitType() != JITCode::DFGJIT) {
3017         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3018         RELEASE_ASSERT_NOT_REACHED();
3019     }
3020
3021     JITCode* jitCode = codeBlock->jitCode()->dfg();
3022
3023     if (Options::verboseOSR()) {
3024         dataLog(
3025             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
3026             jitCode->tierUpCounter, "\n");
3027     }
3028
3029     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
3030     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
3031         && !tierUpHierarchyEntry->value.isEmpty()) {
3032         tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
3033     } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
3034         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3035
3036     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
3037     if (codeBlock->hasOptimizedReplacement()) {
3038         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
3039         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3040     }
3041 }
3042
3043 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
3044 {
3045     VM* vm = &exec->vm();
3046     NativeCallFrameTracer tracer(vm, exec);
3047     DeferGCForAWhile deferGC(vm->heap);
3048     CodeBlock* codeBlock = exec->codeBlock();
3049
3050     sanitizeStackForVM(vm);
3051
3052     if (codeBlock->jitType() != JITCode::DFGJIT) {
3053         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3054         RELEASE_ASSERT_NOT_REACHED();
3055     }
3056
3057     JITCode* jitCode = codeBlock->jitCode()->dfg();
3058     jitCode->tierUpEntrySeen.add(bytecodeIndex);
3059
3060     if (Options::verboseOSR()) {
3061         dataLog(
3062             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
3063             jitCode->tierUpCounter, "\n");
3064     }
3065
3066     return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
3067 }
3068
3069 #endif // ENABLE(FTL_JIT)
3070
3071 } // extern "C"
3072 } } // namespace JSC::DFG
3073
3074 #endif // ENABLE(DFG_JIT)
3075
3076 #endif // ENABLE(JIT)