OSR entry: delay outer-loop compilation when at inner-loop
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011, 2013-2016 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 "HasOwnPropertyCache.h"
46 #include "HostCallReturnValue.h"
47 #include "Interpreter.h"
48 #include "JIT.h"
49 #include "JITExceptions.h"
50 #include "JSArrayInlines.h"
51 #include "JSCInlines.h"
52 #include "JSFixedArray.h"
53 #include "JSGenericTypedArrayViewConstructorInlines.h"
54 #include "JSLexicalEnvironment.h"
55 #include "JSMap.h"
56 #include "JSSet.h"
57 #include "ObjectConstructor.h"
58 #include "Operations.h"
59 #include "RegExpObject.h"
60 #include "Repatch.h"
61 #include "ScopedArguments.h"
62 #include "StringConstructor.h"
63 #include "SuperSampler.h"
64 #include "Symbol.h"
65 #include "TypeProfilerLog.h"
66 #include "TypedArrayInlines.h"
67 #include "VMInlines.h"
68 #include <wtf/InlineASM.h>
69
70 #if ENABLE(JIT)
71 #if ENABLE(DFG_JIT)
72
73 namespace JSC { namespace DFG {
74
75 template<bool strict, bool direct>
76 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
77 {
78     VM& vm = exec->vm();
79     NativeCallFrameTracer tracer(&vm, exec);
80     ASSERT(isIndex(index));
81     if (direct) {
82         RELEASE_ASSERT(baseValue.isObject());
83         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
84         return;
85     }
86     if (baseValue.isObject()) {
87         JSObject* object = asObject(baseValue);
88         if (object->canSetIndexQuickly(index)) {
89             object->setIndexQuickly(vm, index, value);
90             return;
91         }
92
93         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
94         return;
95     }
96
97     baseValue.putByIndex(exec, index, value, strict);
98 }
99
100 template<bool strict, bool direct>
101 ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
102 {
103     VM* vm = &exec->vm();
104     auto scope = DECLARE_THROW_SCOPE(*vm);
105     NativeCallFrameTracer tracer(vm, exec);
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, 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, 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<typename ViewClass>
149 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
150 {
151     VM& vm = exec->vm();
152     NativeCallFrameTracer tracer(&vm, exec);
153     auto scope = DECLARE_THROW_SCOPE(vm);
154
155     if (size < 0) {
156         throwException(exec, scope, createRangeError(exec, ASCIILiteral("Requested length is negative")));
157         return 0;
158     }
159     
160     if (vector)
161         return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
162
163     scope.release();
164     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
165 }
166
167 template <bool strict>
168 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
169 {
170     JSValue baseValue = JSValue::decode(encodedBase);
171     JSValue thisVal = JSValue::decode(encodedThis);
172     JSValue putValue = JSValue::decode(encodedValue);
173     PutPropertySlot slot(thisVal, strict);
174     baseValue.putInline(exec, ident, putValue, slot);
175 }
176
177 extern "C" {
178
179 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
180 {
181     VM* vm = &exec->vm();
182     NativeCallFrameTracer tracer(vm, exec);
183
184     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
185 }
186
187 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
188 {
189     VM* vm = &exec->vm();
190     NativeCallFrameTracer tracer(vm, exec);
191
192     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
193 }
194
195 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
196 {
197     VM& vm = exec->vm();
198     NativeCallFrameTracer tracer(&vm, exec);
199     auto scope = DECLARE_THROW_SCOPE(vm);
200     if (constructor->type() == JSFunctionType) {
201         auto rareData = jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity);
202         RETURN_IF_EXCEPTION(scope, nullptr);
203         return constructEmptyObject(exec, rareData->objectAllocationProfile()->structure());
204     }
205
206     JSValue proto = constructor->get(exec, exec->propertyNames().prototype);
207     RETURN_IF_EXCEPTION(scope, nullptr);
208     if (proto.isObject())
209         return constructEmptyObject(exec, asObject(proto));
210     return constructEmptyObject(exec);
211 }
212
213 JSCell* JIT_OPERATION operationObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
214 {
215     VM* vm = &exec->vm();
216     NativeCallFrameTracer tracer(vm, exec);
217
218     JSValue value = JSValue::decode(encodedTarget);
219     ASSERT(!value.isObject());
220
221     if (value.isUndefinedOrNull())
222         return constructEmptyObject(exec, globalObject->objectPrototype());
223     return value.toObject(exec, globalObject);
224 }
225
226 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
227 {
228     VM* vm = &exec->vm();
229     NativeCallFrameTracer tracer(vm, exec);
230     auto scope = DECLARE_THROW_SCOPE(*vm);
231
232     JSValue op1 = JSValue::decode(encodedOp1);
233     JSValue op2 = JSValue::decode(encodedOp2);
234
235     int32_t a = op1.toInt32(exec);
236     RETURN_IF_EXCEPTION(scope, encodedJSValue());
237     scope.release();
238     int32_t b = op2.toInt32(exec);
239     return JSValue::encode(jsNumber(a & b));
240 }
241
242 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
243 {
244     VM* vm = &exec->vm();
245     NativeCallFrameTracer tracer(vm, exec);
246     auto scope = DECLARE_THROW_SCOPE(*vm);
247
248     JSValue op1 = JSValue::decode(encodedOp1);
249     JSValue op2 = JSValue::decode(encodedOp2);
250
251     int32_t a = op1.toInt32(exec);
252     RETURN_IF_EXCEPTION(scope, encodedJSValue());
253     scope.release();
254     int32_t b = op2.toInt32(exec);
255     return JSValue::encode(jsNumber(a | b));
256 }
257
258 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
259 {
260     VM* vm = &exec->vm();
261     NativeCallFrameTracer tracer(vm, exec);
262     auto scope = DECLARE_THROW_SCOPE(*vm);
263
264     JSValue op1 = JSValue::decode(encodedOp1);
265     JSValue op2 = JSValue::decode(encodedOp2);
266
267     int32_t a = op1.toInt32(exec);
268     RETURN_IF_EXCEPTION(scope, encodedJSValue());
269     scope.release();
270     int32_t b = op2.toInt32(exec);
271     return JSValue::encode(jsNumber(a ^ b));
272 }
273
274 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
275 {
276     VM* vm = &exec->vm();
277     NativeCallFrameTracer tracer(vm, exec);
278     auto scope = DECLARE_THROW_SCOPE(*vm);
279
280     JSValue op1 = JSValue::decode(encodedOp1);
281     JSValue op2 = JSValue::decode(encodedOp2);
282
283     int32_t a = op1.toInt32(exec);
284     RETURN_IF_EXCEPTION(scope, encodedJSValue());
285     scope.release();
286     uint32_t b = op2.toUInt32(exec);
287     return JSValue::encode(jsNumber(a << (b & 0x1f)));
288 }
289
290 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
291 {
292     VM* vm = &exec->vm();
293     NativeCallFrameTracer tracer(vm, exec);
294     auto scope = DECLARE_THROW_SCOPE(*vm);
295
296     JSValue op1 = JSValue::decode(encodedOp1);
297     JSValue op2 = JSValue::decode(encodedOp2);
298
299     int32_t a = op1.toInt32(exec);
300     RETURN_IF_EXCEPTION(scope, encodedJSValue());
301     scope.release();
302     uint32_t b = op2.toUInt32(exec);
303     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
304 }
305
306 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
307 {
308     VM* vm = &exec->vm();
309     NativeCallFrameTracer tracer(vm, exec);
310     auto scope = DECLARE_THROW_SCOPE(*vm);
311
312     JSValue op1 = JSValue::decode(encodedOp1);
313     JSValue op2 = JSValue::decode(encodedOp2);
314
315     uint32_t a = op1.toUInt32(exec);
316     RETURN_IF_EXCEPTION(scope, encodedJSValue());
317     scope.release();
318     uint32_t b = op2.toUInt32(exec);
319     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
320 }
321
322 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
323 {
324     VM* vm = &exec->vm();
325     NativeCallFrameTracer tracer(vm, exec);
326     
327     JSValue op1 = JSValue::decode(encodedOp1);
328     JSValue op2 = JSValue::decode(encodedOp2);
329     
330     ASSERT(!op1.isNumber() || !op2.isNumber());
331     
332     if (op1.isString() && !op2.isObject())
333         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
334
335     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
336 }
337
338 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
339 {
340     VM* vm = &exec->vm();
341     NativeCallFrameTracer tracer(vm, exec);
342     auto scope = DECLARE_THROW_SCOPE(*vm);
343
344     JSValue op1 = JSValue::decode(encodedOp1);
345     JSValue op2 = JSValue::decode(encodedOp2);
346
347     double a = op1.toNumber(exec);
348     RETURN_IF_EXCEPTION(scope, encodedJSValue());
349     scope.release();
350     double b = op2.toNumber(exec);
351     return JSValue::encode(jsNumber(a / b));
352 }
353
354 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
355 {
356     VM* vm = &exec->vm();
357     NativeCallFrameTracer tracer(vm, exec);
358     auto scope = DECLARE_THROW_SCOPE(*vm);
359
360     JSValue op1 = JSValue::decode(encodedOp1);
361     double a = op1.toNumber(exec);
362     RETURN_IF_EXCEPTION(scope, PNaN);
363     return fabs(a);
364 }
365
366 int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
367 {
368     VM* vm = &exec->vm();
369     NativeCallFrameTracer tracer(vm, exec);
370     auto scope = DECLARE_THROW_SCOPE(*vm);
371
372     JSValue op1 = JSValue::decode(encodedOp1);
373     uint32_t value = op1.toUInt32(exec);
374     RETURN_IF_EXCEPTION(scope, 0);
375     return clz32(value);
376 }
377
378 double JIT_OPERATION operationArithCos(ExecState* exec, EncodedJSValue encodedOp1)
379 {
380     VM* vm = &exec->vm();
381     NativeCallFrameTracer tracer(vm, exec);
382     auto scope = DECLARE_THROW_SCOPE(*vm);
383
384     JSValue op1 = JSValue::decode(encodedOp1);
385     double a = op1.toNumber(exec);
386     RETURN_IF_EXCEPTION(scope, encodedJSValue());
387     return cos(a);
388 }
389
390 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
391 {
392     VM* vm = &exec->vm();
393     NativeCallFrameTracer tracer(vm, exec);
394     auto scope = DECLARE_THROW_SCOPE(*vm);
395
396     JSValue op1 = JSValue::decode(encodedOp1);
397     double a = op1.toNumber(exec);
398     RETURN_IF_EXCEPTION(scope, PNaN);
399     return static_cast<float>(a);
400 }
401
402 double JIT_OPERATION operationArithLog(ExecState* exec, EncodedJSValue encodedOp1)
403 {
404     VM* vm = &exec->vm();
405     NativeCallFrameTracer tracer(vm, exec);
406     auto scope = DECLARE_THROW_SCOPE(*vm);
407
408     JSValue op1 = JSValue::decode(encodedOp1);
409     double a = op1.toNumber(exec);
410     RETURN_IF_EXCEPTION(scope, PNaN);
411     return log(a);
412 }
413
414 double JIT_OPERATION operationArithSin(ExecState* exec, EncodedJSValue encodedOp1)
415 {
416     VM* vm = &exec->vm();
417     NativeCallFrameTracer tracer(vm, exec);
418     auto scope = DECLARE_THROW_SCOPE(*vm);
419
420     JSValue op1 = JSValue::decode(encodedOp1);
421     double a = op1.toNumber(exec);
422     RETURN_IF_EXCEPTION(scope, PNaN);
423     return sin(a);
424 }
425
426 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
427 {
428     VM* vm = &exec->vm();
429     NativeCallFrameTracer tracer(vm, exec);
430     auto scope = DECLARE_THROW_SCOPE(*vm);
431
432     JSValue op1 = JSValue::decode(encodedOp1);
433     double a = op1.toNumber(exec);
434     RETURN_IF_EXCEPTION(scope, PNaN);
435     return sqrt(a);
436 }
437
438 double JIT_OPERATION operationArithTan(ExecState* exec, EncodedJSValue encodedOp1)
439 {
440     VM* vm = &exec->vm();
441     NativeCallFrameTracer tracer(vm, exec);
442     auto scope = DECLARE_THROW_SCOPE(*vm);
443
444     JSValue op1 = JSValue::decode(encodedOp1);
445     double a = op1.toNumber(exec);
446     RETURN_IF_EXCEPTION(scope, encodedJSValue());
447     return tan(a);
448 }
449
450 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
451 {
452     VM* vm = &exec->vm();
453     NativeCallFrameTracer tracer(vm, exec);
454     auto scope = DECLARE_THROW_SCOPE(*vm);
455
456     JSValue argument = JSValue::decode(encodedArgument);
457     double valueOfArgument = argument.toNumber(exec);
458     RETURN_IF_EXCEPTION(scope, encodedJSValue());
459     return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
460 }
461
462 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
463 {
464     VM* vm = &exec->vm();
465     NativeCallFrameTracer tracer(vm, exec);
466     auto scope = DECLARE_THROW_SCOPE(*vm);
467
468     JSValue argument = JSValue::decode(encodedArgument);
469     double valueOfArgument = argument.toNumber(exec);
470     RETURN_IF_EXCEPTION(scope, encodedJSValue());
471     return JSValue::encode(jsNumber(floor(valueOfArgument)));
472 }
473
474 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
475 {
476     VM* vm = &exec->vm();
477     NativeCallFrameTracer tracer(vm, exec);
478     auto scope = DECLARE_THROW_SCOPE(*vm);
479
480     JSValue argument = JSValue::decode(encodedArgument);
481     double valueOfArgument = argument.toNumber(exec);
482     RETURN_IF_EXCEPTION(scope, encodedJSValue());
483     return JSValue::encode(jsNumber(ceil(valueOfArgument)));
484 }
485
486 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
487 {
488     VM* vm = &exec->vm();
489     NativeCallFrameTracer tracer(vm, exec);
490     auto scope = DECLARE_THROW_SCOPE(*vm);
491
492     JSValue argument = JSValue::decode(encodedArgument);
493     double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
494     RETURN_IF_EXCEPTION(scope, encodedJSValue());
495     return JSValue::encode(jsNumber(truncatedValueOfArgument));
496 }
497
498 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
499 {
500     VM& vm = exec->vm();
501     NativeCallFrameTracer tracer(&vm, exec);
502     
503     if (base->isObject()) {
504         JSObject* object = asObject(base);
505         if (object->canGetIndexQuickly(index))
506             return JSValue::encode(object->getIndexQuickly(index));
507     }
508
509     if (isJSString(base) && asString(base)->canGetIndex(index))
510         return JSValue::encode(asString(base)->getIndex(exec, index));
511
512     return JSValue::encode(JSValue(base).get(exec, index));
513 }
514
515 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
516 {
517     VM& vm = exec->vm();
518     NativeCallFrameTracer tracer(&vm, exec);
519     auto scope = DECLARE_THROW_SCOPE(vm);
520
521     JSValue baseValue = JSValue::decode(encodedBase);
522     JSValue property = JSValue::decode(encodedProperty);
523
524     if (LIKELY(baseValue.isCell())) {
525         JSCell* base = baseValue.asCell();
526
527         if (property.isUInt32()) {
528             scope.release();
529             return getByVal(exec, base, property.asUInt32());
530         }
531         if (property.isDouble()) {
532             double propertyAsDouble = property.asDouble();
533             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
534             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) {
535                 scope.release();
536                 return getByVal(exec, base, propertyAsUInt32);
537             }
538         } else if (property.isString()) {
539             Structure& structure = *base->structure(vm);
540             if (JSCell::canUseFastGetOwnProperty(structure)) {
541                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
542                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
543                         return JSValue::encode(result);
544                 }
545             }
546         }
547     }
548
549     baseValue.requireObjectCoercible(exec);
550     RETURN_IF_EXCEPTION(scope, encodedJSValue());
551     auto propertyName = property.toPropertyKey(exec);
552     RETURN_IF_EXCEPTION(scope, encodedJSValue());
553     scope.release();
554     return JSValue::encode(baseValue.get(exec, propertyName));
555 }
556
557 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
558 {
559     VM& vm = exec->vm();
560     NativeCallFrameTracer tracer(&vm, exec);
561     auto scope = DECLARE_THROW_SCOPE(vm);
562
563     JSValue property = JSValue::decode(encodedProperty);
564
565     if (property.isUInt32())
566         return getByVal(exec, base, property.asUInt32());
567     if (property.isDouble()) {
568         double propertyAsDouble = property.asDouble();
569         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
570         if (propertyAsUInt32 == propertyAsDouble)
571             return getByVal(exec, base, propertyAsUInt32);
572     } else if (property.isString()) {
573         Structure& structure = *base->structure(vm);
574         if (JSCell::canUseFastGetOwnProperty(structure)) {
575             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
576                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
577                     return JSValue::encode(result);
578             }
579         }
580     }
581
582     auto propertyName = property.toPropertyKey(exec);
583     RETURN_IF_EXCEPTION(scope, encodedJSValue());
584     return JSValue::encode(JSValue(base).get(exec, propertyName));
585 }
586
587 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
588 {
589     VM* vm = &exec->vm();
590     NativeCallFrameTracer tracer(vm, exec);
591     
592     if (index < 0) {
593         // Go the slowest way possible becase negative indices don't use indexed storage.
594         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
595     }
596
597     // Use this since we know that the value is out of bounds.
598     return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
599 }
600
601 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
602 {
603     return getByValCellInt(exec, base, index);
604 }
605
606 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
607 {
608     return getByValCellInt(exec, base, index);
609 }
610
611 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
612 {
613     VM* vm = &exec->vm();
614     NativeCallFrameTracer tracer(vm, exec);
615     
616     operationPutByValInternal<true, false>(exec, encodedBase, encodedProperty, encodedValue);
617 }
618
619 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
620 {
621     VM* vm = &exec->vm();
622     NativeCallFrameTracer tracer(vm, exec);
623     
624     operationPutByValInternal<false, false>(exec, encodedBase, encodedProperty, encodedValue);
625 }
626
627 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
628 {
629     VM* vm = &exec->vm();
630     NativeCallFrameTracer tracer(vm, exec);
631     
632     operationPutByValInternal<true, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
633 }
634
635 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
636 {
637     VM* vm = &exec->vm();
638     NativeCallFrameTracer tracer(vm, exec);
639     
640     operationPutByValInternal<false, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
641 }
642
643 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
644 {
645     VM& vm = exec->vm();
646     NativeCallFrameTracer tracer(&vm, exec);
647     
648     if (index >= 0) {
649         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
650         return;
651     }
652     
653     PutPropertySlot slot(array, true);
654     array->methodTable()->put(
655         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
656 }
657
658 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
659 {
660     VM* vm = &exec->vm();
661     NativeCallFrameTracer tracer(vm, exec);
662     
663     if (index >= 0) {
664         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
665         return;
666     }
667     
668     PutPropertySlot slot(array, false);
669     array->methodTable()->put(
670         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
671 }
672
673 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
674 {
675     VM* vm = &exec->vm();
676     NativeCallFrameTracer tracer(vm, exec);
677     
678     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
679     
680     if (index >= 0) {
681         array->putByIndexInline(exec, index, jsValue, true);
682         return;
683     }
684     
685     PutPropertySlot slot(array, true);
686     array->methodTable()->put(
687         array, exec, Identifier::from(exec, index), jsValue, slot);
688 }
689
690 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
691 {
692     VM* vm = &exec->vm();
693     NativeCallFrameTracer tracer(vm, exec);
694     
695     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
696     
697     if (index >= 0) {
698         array->putByIndexInline(exec, index, jsValue, false);
699         return;
700     }
701     
702     PutPropertySlot slot(array, false);
703     array->methodTable()->put(
704         array, exec, Identifier::from(exec, index), jsValue, slot);
705 }
706
707 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
708 {
709     VM* vm = &exec->vm();
710     NativeCallFrameTracer tracer(vm, exec);
711     
712     operationPutByValInternal<true, true>(exec, encodedBase, encodedProperty, encodedValue);
713 }
714
715 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
716 {
717     VM* vm = &exec->vm();
718     NativeCallFrameTracer tracer(vm, exec);
719     
720     operationPutByValInternal<false, true>(exec, encodedBase, encodedProperty, encodedValue);
721 }
722
723 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
724 {
725     VM* vm = &exec->vm();
726     NativeCallFrameTracer tracer(vm, exec);
727     
728     operationPutByValInternal<true, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
729 }
730
731 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
732 {
733     VM* vm = &exec->vm();
734     NativeCallFrameTracer tracer(vm, exec);
735     
736     operationPutByValInternal<false, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
737 }
738
739 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
740 {
741     VM* vm = &exec->vm();
742     NativeCallFrameTracer tracer(vm, exec);
743     if (index >= 0) {
744         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
745         return;
746     }
747     
748     PutPropertySlot slot(array, true);
749     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
750 }
751
752 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
753 {
754     VM* vm = &exec->vm();
755     NativeCallFrameTracer tracer(vm, exec);
756     
757     if (index >= 0) {
758         array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
759         return;
760     }
761     
762     PutPropertySlot slot(array, false);
763     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
764 }
765
766 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
767 {
768     VM* vm = &exec->vm();
769     NativeCallFrameTracer tracer(vm, exec);
770     
771     array->push(exec, JSValue::decode(encodedValue));
772     return JSValue::encode(jsNumber(array->length()));
773 }
774
775 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
776 {
777     VM* vm = &exec->vm();
778     NativeCallFrameTracer tracer(vm, exec);
779     
780     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
781     return JSValue::encode(jsNumber(array->length()));
782 }
783
784 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
785 {
786     VM* vm = &exec->vm();
787     NativeCallFrameTracer tracer(vm, exec);
788     
789     return JSValue::encode(array->pop(exec));
790 }
791         
792 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
793 {
794     VM* vm = &exec->vm();
795     NativeCallFrameTracer tracer(vm, exec);
796     
797     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
798     
799     return JSValue::encode(array->pop(exec));
800 }
801         
802 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
803 {
804     SuperSamplerScope superSamplerScope(false);
805     
806     VM& vm = globalObject->vm();
807     NativeCallFrameTracer tracer(&vm, exec);
808     
809     return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
810 }
811         
812 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
813 {
814     SuperSamplerScope superSamplerScope(false);
815     
816     VM& vm = globalObject->vm();
817     NativeCallFrameTracer tracer(&vm, exec);
818     auto scope = DECLARE_THROW_SCOPE(vm);
819     
820     JSValue argument = JSValue::decode(encodedArgument);
821
822     JSString* input = argument.toStringOrNull(exec);
823     ASSERT(!!scope.exception() == !input);
824     if (!input)
825         return encodedJSValue();
826     scope.release();
827     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
828 }
829         
830 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
831 {
832     SuperSamplerScope superSamplerScope(false);
833     
834     VM& vm = globalObject->vm();
835     NativeCallFrameTracer tracer(&vm, exec);
836     auto scope = DECLARE_THROW_SCOPE(vm);
837
838     JSValue base = JSValue::decode(encodedBase);
839     JSValue argument = JSValue::decode(encodedArgument);
840     
841     if (!base.inherits(RegExpObject::info()))
842         return throwVMTypeError(exec, scope);
843
844     JSString* input = argument.toStringOrNull(exec);
845     ASSERT(!!scope.exception() == !input);
846     if (!input)
847         return JSValue::encode(jsUndefined());
848     scope.release();
849     return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
850 }
851         
852 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
853 {
854     SuperSamplerScope superSamplerScope(false);
855     
856     VM& vm = globalObject->vm();
857     NativeCallFrameTracer tracer(&vm, exec);
858
859     return regExpObject->testInline(exec, globalObject, input);
860 }
861
862 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
863 {
864     SuperSamplerScope superSamplerScope(false);
865     
866     VM& vm = globalObject->vm();
867     NativeCallFrameTracer tracer(&vm, exec);
868
869     JSValue argument = JSValue::decode(encodedArgument);
870
871     JSString* input = argument.toStringOrNull(exec);
872     if (!input)
873         return false;
874     return regExpObject->testInline(exec, globalObject, input);
875 }
876
877 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
878 {
879     SuperSamplerScope superSamplerScope(false);
880     
881     VM& vm = globalObject->vm();
882     NativeCallFrameTracer tracer(&vm, exec);
883     auto scope = DECLARE_THROW_SCOPE(vm);
884
885     JSValue base = JSValue::decode(encodedBase);
886     JSValue argument = JSValue::decode(encodedArgument);
887
888     if (!base.inherits(RegExpObject::info())) {
889         throwTypeError(exec, scope);
890         return false;
891     }
892
893     JSString* input = argument.toStringOrNull(exec);
894     ASSERT(!!scope.exception() == !input);
895     if (!input)
896         return false;
897     scope.release();
898     return asRegExpObject(base)->test(exec, globalObject, input);
899 }
900
901 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
902 {
903     VM* vm = &exec->vm();
904     NativeCallFrameTracer tracer(vm, exec);
905     
906     JSValue op1 = JSValue::decode(encodedOp1);
907     JSValue op2 = JSValue::decode(encodedOp2);
908     
909     ASSERT(op1.isCell());
910     ASSERT(op2.isCell());
911     
912     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
913 }
914
915 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
916 {
917     VM* vm = &exec->vm();
918     NativeCallFrameTracer tracer(vm, exec);
919
920     JSValue src1 = JSValue::decode(encodedOp1);
921     JSValue src2 = JSValue::decode(encodedOp2);
922     
923     return JSValue::strictEqual(exec, src1, src2);
924 }
925
926 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
927 {
928     VM* vm = &exec->vm();
929     NativeCallFrameTracer tracer(vm, exec);
930     
931     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
932 }
933
934 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
935 {
936     VM* vm = &exec->vm();
937     NativeCallFrameTracer tracer(vm, exec);
938
939     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
940 }
941
942 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
943 {
944     VM& vm = exec->vm();
945     NativeCallFrameTracer tracer(&vm, exec);
946
947     JSValue baseValue = JSValue::decode(encodedBase);
948     JSValue thisVal = JSValue::decode(encodedThis);
949     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
950     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
951     return JSValue::encode(result);
952 }
953
954 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
955 {
956     VM& vm = exec->vm();
957     NativeCallFrameTracer tracer(&vm, exec);
958     auto scope = DECLARE_THROW_SCOPE(vm);
959
960     JSValue baseValue = JSValue::decode(encodedBase);
961     JSValue thisVal = JSValue::decode(encodedThis);
962     JSValue subscript = JSValue::decode(encodedSubscript);
963
964     if (LIKELY(baseValue.isCell() && subscript.isString())) {
965         Structure& structure = *baseValue.asCell()->structure(vm);
966         if (JSCell::canUseFastGetOwnProperty(structure)) {
967             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
968                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
969                     return JSValue::encode(result);
970             }
971         }
972     }
973     
974     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
975     if (subscript.isUInt32()) {
976         uint32_t i = subscript.asUInt32();
977         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
978             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
979         
980         scope.release();
981         return JSValue::encode(baseValue.get(exec, i, slot));
982     }
983
984     baseValue.requireObjectCoercible(exec);
985     RETURN_IF_EXCEPTION(scope, encodedJSValue());
986
987     auto property = subscript.toPropertyKey(exec);
988     RETURN_IF_EXCEPTION(scope, encodedJSValue());
989     scope.release();
990     return JSValue::encode(baseValue.get(exec, property, slot));
991 }
992
993 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
994 {
995     VM& vm = exec->vm();
996     NativeCallFrameTracer tracer(&vm, exec);
997
998     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
999 }
1000
1001 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1002 {
1003     VM& vm = exec->vm();
1004     NativeCallFrameTracer tracer(&vm, exec);
1005
1006     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1007 }
1008
1009 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1010 {
1011     VM& vm = exec->vm();
1012     NativeCallFrameTracer tracer(&vm, exec);
1013     auto scope = DECLARE_THROW_SCOPE(vm);
1014
1015     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1016     RETURN_IF_EXCEPTION(scope, void());
1017     scope.release();
1018     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1019 }
1020
1021 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1022 {
1023     VM& vm = exec->vm();
1024     NativeCallFrameTracer tracer(&vm, exec);
1025     auto scope = DECLARE_THROW_SCOPE(vm);
1026
1027     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1028     RETURN_IF_EXCEPTION(scope, void());
1029     scope.release();
1030     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1031 }
1032
1033 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1034 {
1035     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1036     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
1037     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1038         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1039     else
1040         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1041 }
1042
1043 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1044 {
1045     VM& vm = exec->vm();
1046     NativeCallFrameTracer tracer(&vm, exec);
1047     auto scope = DECLARE_THROW_SCOPE(vm);
1048
1049     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1050     RETURN_IF_EXCEPTION(scope, void());
1051     scope.release();
1052     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1053 }
1054
1055 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1056 {
1057     VM& vm = exec->vm();
1058     NativeCallFrameTracer tracer(&vm, exec);
1059     auto scope = DECLARE_THROW_SCOPE(vm);
1060
1061     Identifier propertyName = property->toIdentifier(exec);
1062     RETURN_IF_EXCEPTION(scope, void());
1063     scope.release();
1064     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1065 }
1066
1067 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1068 {
1069     VM& vm = exec->vm();
1070     NativeCallFrameTracer tracer(&vm, exec);
1071     defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1072 }
1073
1074 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1075 {
1076     VM& vm = exec->vm();
1077     NativeCallFrameTracer tracer(&vm, exec);
1078     defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1079 }
1080
1081 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1082 {
1083     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1084     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
1085     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1086         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1087     else
1088         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1089 }
1090
1091 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1092 {
1093     VM& vm = exec->vm();
1094     NativeCallFrameTracer tracer(&vm, exec);
1095     auto scope = DECLARE_THROW_SCOPE(vm);
1096
1097     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1098     RETURN_IF_EXCEPTION(scope, void());
1099     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1100 }
1101
1102 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1103 {
1104     VM& vm = exec->vm();
1105     NativeCallFrameTracer tracer(&vm, exec);
1106     auto scope = DECLARE_THROW_SCOPE(vm);
1107
1108     Identifier propertyName = property->toIdentifier(exec);
1109     RETURN_IF_EXCEPTION(scope, void());
1110     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1111 }
1112
1113 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1114 {
1115     VM& vm = exec->vm();
1116     NativeCallFrameTracer tracer(&vm, exec);
1117     defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
1118 }
1119
1120 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1121 {
1122     VM& vm = exec->vm();
1123     NativeCallFrameTracer tracer(&vm, exec);
1124     defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1125 }
1126
1127 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1128 {
1129     VM* vm = &exec->vm();
1130     NativeCallFrameTracer tracer(vm, exec);
1131     
1132     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1133 }
1134
1135 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1136 {
1137     VM* vm = &exec->vm();
1138     NativeCallFrameTracer tracer(vm, exec);
1139     
1140     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1141 }
1142
1143 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1144 {
1145     VM& vm = exec->vm();
1146     NativeCallFrameTracer tracer(&vm, exec);
1147     auto scope = DECLARE_THROW_SCOPE(vm);
1148
1149     if (UNLIKELY(size < 0))
1150         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1151
1152     JSArray* result;
1153     if (butterfly)
1154         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1155     else
1156         result = JSArray::create(vm, arrayStructure, size);
1157     return bitwise_cast<char*>(result);
1158 }
1159
1160 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1161 {
1162     VM& vm = exec->vm();
1163     NativeCallFrameTracer tracer(&vm, exec);
1164     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1165 }
1166
1167 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1168     ExecState* exec, Structure* structure, int32_t length, char* vector)
1169 {
1170     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1171 }
1172
1173 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1174     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1175 {
1176     VM& vm = exec->vm();
1177     NativeCallFrameTracer tracer(&vm, exec);
1178     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1179 }
1180
1181 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1182     ExecState* exec, Structure* structure, int32_t length, char* vector)
1183 {
1184     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1185 }
1186
1187 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1188     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1189 {
1190     VM& vm = exec->vm();
1191     NativeCallFrameTracer tracer(&vm, exec);
1192     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1193 }
1194
1195 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1196     ExecState* exec, Structure* structure, int32_t length, char* vector)
1197 {
1198     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1199 }
1200
1201 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1202     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1203 {
1204     VM& vm = exec->vm();
1205     NativeCallFrameTracer tracer(&vm, exec);
1206     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1207 }
1208
1209 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1210     ExecState* exec, Structure* structure, int32_t length, char* vector)
1211 {
1212     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1213 }
1214
1215 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1216     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1217 {
1218     VM& vm = exec->vm();
1219     NativeCallFrameTracer tracer(&vm, exec);
1220     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1221 }
1222
1223 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1224     ExecState* exec, Structure* structure, int32_t length, char* vector)
1225 {
1226     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1227 }
1228
1229 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1230     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1231 {
1232     VM& vm = exec->vm();
1233     NativeCallFrameTracer tracer(&vm, exec);
1234     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1235 }
1236
1237 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1238     ExecState* exec, Structure* structure, int32_t length, char* vector)
1239 {
1240     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1241 }
1242
1243 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1244     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1245 {
1246     VM& vm = exec->vm();
1247     NativeCallFrameTracer tracer(&vm, exec);
1248     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1249 }
1250
1251 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1252     ExecState* exec, Structure* structure, int32_t length, char* vector)
1253 {
1254     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1255 }
1256
1257 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1258     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1259 {
1260     VM& vm = exec->vm();
1261     NativeCallFrameTracer tracer(&vm, exec);
1262     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1263 }
1264
1265 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1266     ExecState* exec, Structure* structure, int32_t length, char* vector)
1267 {
1268     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1269 }
1270
1271 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1272     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1273 {
1274     VM& vm = exec->vm();
1275     NativeCallFrameTracer tracer(&vm, exec);
1276     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1277 }
1278
1279 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1280     ExecState* exec, Structure* structure, int32_t length, char* vector)
1281 {
1282     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1283 }
1284
1285 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1286     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1287 {
1288     VM& vm = exec->vm();
1289     NativeCallFrameTracer tracer(&vm, exec);
1290     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1291 }
1292
1293 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1294 {
1295     JSValue initialValue = JSValue::decode(initialValueEncoded);
1296     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1297     VM& vm = exec->vm();
1298     NativeCallFrameTracer tracer(&vm, exec);
1299     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1300 }
1301
1302 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1303 {
1304     VM& vm = exec->vm();
1305     NativeCallFrameTracer target(&vm, exec);
1306     DirectArguments* result = DirectArguments::create(
1307         vm, structure, length, std::max(length, minCapacity));
1308     // The caller will store to this object without barriers. Most likely, at this point, this is
1309     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1310     // since the GC should be allowed to do crazy (like pretenuring, for example).
1311     vm.heap.writeBarrier(result);
1312     return result;
1313 }
1314
1315 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1316 {
1317     VM& vm = exec->vm();
1318     NativeCallFrameTracer target(&vm, exec);
1319     
1320     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1321     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1322     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1323     
1324     return ScopedArguments::createByCopyingFrom(
1325         vm, structure, argumentStart, length, callee, table, scope);
1326 }
1327
1328 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1329 {
1330     VM& vm = exec->vm();
1331     NativeCallFrameTracer target(&vm, exec);
1332     return ClonedArguments::createByCopyingFrom(
1333         exec, structure, argumentStart, length, callee);
1334 }
1335
1336 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1337 {
1338     VM& vm = exec->vm();
1339     NativeCallFrameTracer target(&vm, exec);
1340     
1341     DeferGCForAWhile deferGC(vm.heap);
1342     
1343     CodeBlock* codeBlock;
1344     if (inlineCallFrame)
1345         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1346     else
1347         codeBlock = exec->codeBlock();
1348     
1349     unsigned length = argumentCount - 1;
1350     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1351     DirectArguments* result = DirectArguments::create(
1352         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1353     
1354     result->callee().set(vm, result, callee);
1355     
1356     Register* arguments =
1357         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1358         CallFrame::argumentOffset(0);
1359     for (unsigned i = length; i--;)
1360         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1361     
1362     return result;
1363 }
1364
1365 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1366 {
1367     VM& vm = exec->vm();
1368     NativeCallFrameTracer target(&vm, exec);
1369     
1370     DeferGCForAWhile deferGC(vm.heap);
1371     
1372     CodeBlock* codeBlock;
1373     if (inlineCallFrame)
1374         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1375     else
1376         codeBlock = exec->codeBlock();
1377     
1378     unsigned length = argumentCount - 1;
1379     ClonedArguments* result = ClonedArguments::createEmpty(
1380         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1381     
1382     Register* arguments =
1383         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1384         CallFrame::argumentOffset(0);
1385     for (unsigned i = length; i--;)
1386         result->initializeIndex(vm, i, arguments[i].jsValue());
1387
1388     
1389     return result;
1390 }
1391
1392 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1393 {
1394     VM* vm = &exec->vm();
1395     NativeCallFrameTracer tracer(vm, exec);
1396
1397     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1398     Structure* structure = globalObject->restParameterStructure();
1399     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1400     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1401     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1402 }
1403
1404 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1405 {
1406     VM& vm = exec->vm();
1407     NativeCallFrameTracer tracer(&vm, exec);
1408
1409     ASSERT(jsDynamicCast<JSObject*>(object));
1410     
1411     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1412         return false;
1413     if (object->type() == JSFunctionType)
1414         return false;
1415     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1416         CallData callData;
1417         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1418             return false;
1419     }
1420     
1421     return true;
1422 }
1423
1424 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1425 {
1426     VM& vm = exec->vm();
1427     NativeCallFrameTracer tracer(&vm, exec);
1428
1429     ASSERT(jsDynamicCast<JSObject*>(object));
1430     
1431     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1432         return false;
1433     if (object->type() == JSFunctionType)
1434         return true;
1435     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1436         CallData callData;
1437         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1438             return true;
1439     }
1440     
1441     return false;
1442 }
1443
1444 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1445 {
1446     VM& vm = exec->vm();
1447     NativeCallFrameTracer tracer(&vm, exec);
1448
1449     ASSERT(jsDynamicCast<JSObject*>(object));
1450     
1451     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1452         return vm.smallStrings.undefinedString();
1453     if (object->type() == JSFunctionType)
1454         return vm.smallStrings.functionString();
1455     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1456         CallData callData;
1457         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1458             return vm.smallStrings.functionString();
1459     }
1460     
1461     return vm.smallStrings.objectString();
1462 }
1463
1464 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1465 {
1466     VM& vm = exec->vm();
1467     NativeCallFrameTracer tracer(&vm, exec);
1468
1469     ASSERT(jsDynamicCast<JSObject*>(object));
1470     
1471     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1472         return static_cast<int32_t>(TypeofType::Undefined);
1473     if (object->type() == JSFunctionType)
1474         return static_cast<int32_t>(TypeofType::Function);
1475     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1476         CallData callData;
1477         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1478             return static_cast<int32_t>(TypeofType::Function);
1479     }
1480     
1481     return static_cast<int32_t>(TypeofType::Object);
1482 }
1483
1484 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1485 {
1486     VM& vm = exec->vm();
1487     NativeCallFrameTracer tracer(&vm, exec);
1488
1489     return reinterpret_cast<char*>(
1490         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1491 }
1492
1493 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1494 {
1495     VM& vm = exec->vm();
1496     NativeCallFrameTracer tracer(&vm, exec);
1497
1498     return reinterpret_cast<char*>(
1499         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1500 }
1501
1502 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1503 {
1504     VM& vm = exec->vm();
1505     NativeCallFrameTracer tracer(&vm, exec);
1506
1507     ASSERT(!object->structure()->outOfLineCapacity());
1508     return reinterpret_cast<char*>(
1509         object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1510 }
1511
1512 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1513 {
1514     VM& vm = exec->vm();
1515     NativeCallFrameTracer tracer(&vm, exec);
1516
1517     return reinterpret_cast<char*>(
1518         object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize));
1519 }
1520
1521 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1522 {
1523     VM& vm = exec->vm();
1524     NativeCallFrameTracer tracer(&vm, exec);
1525     
1526     if (!cell->isObject())
1527         return 0;
1528     
1529     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1530 }
1531
1532 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1533 {
1534     VM& vm = exec->vm();
1535     NativeCallFrameTracer tracer(&vm, exec);
1536     
1537     if (!cell->isObject())
1538         return 0;
1539     
1540     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1541 }
1542
1543 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1544 {
1545     VM& vm = exec->vm();
1546     NativeCallFrameTracer tracer(&vm, exec);
1547     
1548     if (!cell->isObject())
1549         return 0;
1550     
1551     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1552 }
1553
1554 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1555 {
1556     VM& vm = exec->vm();
1557     NativeCallFrameTracer tracer(&vm, exec);
1558     
1559     if (!cell->isObject())
1560         return 0;
1561
1562     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1563 }
1564
1565 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1566 {
1567     VM& vm = exec->vm();
1568     NativeCallFrameTracer tracer(&vm, exec);
1569
1570     return string->value(exec).impl();
1571 }
1572
1573 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
1574 {
1575     VM& vm = exec->vm();
1576     NativeCallFrameTracer tracer(&vm, exec);
1577
1578     auto scope = DECLARE_THROW_SCOPE(vm);
1579
1580     const String& inputString = string->value(exec);
1581     RETURN_IF_EXCEPTION(scope, nullptr);
1582     if (!inputString.length())
1583         return vm.smallStrings.emptyString();
1584
1585     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
1586     if (lowercasedString.impl() == inputString.impl())
1587         return string;
1588     scope.release();
1589     return jsString(exec, lowercasedString);
1590 }
1591
1592 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1593 {
1594     VM& vm = exec->vm();
1595     NativeCallFrameTracer tracer(&vm, exec);
1596     
1597     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1598 }
1599
1600 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1601 {
1602     VM& vm = exec->vm();
1603     NativeCallFrameTracer tracer(&vm, exec);
1604     
1605     return StringObject::create(vm, structure, string);
1606 }
1607
1608 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1609 {
1610     VM& vm = exec->vm();
1611     NativeCallFrameTracer tracer(&vm, exec);
1612     
1613     return JSValue(cell).toString(exec);
1614 }
1615
1616 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1617 {
1618     VM& vm = exec->vm();
1619     NativeCallFrameTracer tracer(&vm, exec);
1620
1621     return JSValue::decode(value).toString(exec);
1622 }
1623
1624 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1625 {
1626     VM& vm = exec->vm();
1627     NativeCallFrameTracer tracer(&vm, exec);
1628
1629     return stringConstructor(exec, cell);
1630 }
1631
1632 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1633 {
1634     VM& vm = exec->vm();
1635     NativeCallFrameTracer tracer(&vm, exec);
1636
1637     return stringConstructor(exec, JSValue::decode(value));
1638 }
1639
1640 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1641 {
1642     VM& vm = exec->vm();
1643     NativeCallFrameTracer tracer(&vm, exec);
1644
1645     return jsString(exec, left, right);
1646 }
1647
1648 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1649 {
1650     VM& vm = exec->vm();
1651     NativeCallFrameTracer tracer(&vm, exec);
1652
1653     return jsString(exec, a, b, c);
1654 }
1655
1656 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1657 {
1658     VM& vm = exec->vm();
1659     NativeCallFrameTracer tracer(&vm, exec);
1660     auto scope = DECLARE_THROW_SCOPE(vm);
1661
1662     JSString* str1 = JSValue::decode(a).toString(exec);
1663     ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
1664     JSString* str2 = JSValue::decode(b).toString(exec);
1665     ASSERT(!scope.exception());
1666
1667     scope.release();
1668     return jsString(exec, str1, str2);
1669 }
1670     
1671 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1672 {
1673     VM& vm = exec->vm();
1674     NativeCallFrameTracer tracer(&vm, exec);
1675     auto scope = DECLARE_THROW_SCOPE(vm);
1676
1677     JSString* str1 = JSValue::decode(a).toString(exec);
1678     ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
1679     JSString* str2 = JSValue::decode(b).toString(exec);
1680     ASSERT(!scope.exception());
1681     JSString* str3 = JSValue::decode(c).toString(exec);
1682     ASSERT(!scope.exception());
1683
1684     scope.release();
1685     return jsString(exec, str1, str2, str3);
1686 }
1687
1688 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1689     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1690 {
1691     VM& vm = exec->vm();
1692     NativeCallFrameTracer tracer(&vm, exec);
1693
1694     CodeBlock* codeBlock = exec->codeBlock();
1695     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1696     JSValue value = JSValue::decode(encodedValue);
1697     ASSERT(value.isDouble());
1698     double asDouble = value.asDouble();
1699     int32_t asInt32 = static_cast<int32_t>(asDouble);
1700     if (asDouble == asInt32)
1701         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1702     return static_cast<char*>(table.ctiDefault.executableAddress());
1703 }
1704
1705 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1706 {
1707     VM& vm = exec->vm();
1708     NativeCallFrameTracer tracer(&vm, exec);
1709
1710     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1711 }
1712
1713 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1714 {
1715     VM& vm = exec->vm();
1716     NativeCallFrameTracer tracer(&vm, exec);
1717
1718     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1719 }
1720
1721 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
1722 {
1723     return codePointCompare(a, b) < 0;
1724 }
1725
1726 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
1727 {
1728     return codePointCompare(a, b) <= 0;
1729 }
1730
1731 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
1732 {
1733     return codePointCompare(a, b) > 0;
1734 }
1735
1736 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
1737 {
1738     return codePointCompare(a, b) >= 0;
1739 }
1740
1741 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
1742 {
1743     VM& vm = exec->vm();
1744     NativeCallFrameTracer tracer(&vm, exec);
1745
1746     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1747 }
1748
1749 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
1750 {
1751     VM& vm = exec->vm();
1752     NativeCallFrameTracer tracer(&vm, exec);
1753
1754     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1755 }
1756
1757 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
1758 {
1759     VM& vm = exec->vm();
1760     NativeCallFrameTracer tracer(&vm, exec);
1761
1762     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1763 }
1764
1765 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
1766 {
1767     VM& vm = exec->vm();
1768     NativeCallFrameTracer tracer(&vm, exec);
1769
1770     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1771 }
1772
1773 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1774 {
1775     VM& vm = exec->vm();
1776     NativeCallFrameTracer tracer(&vm, exec);
1777
1778     set->touch(vm, "Executed NotifyWrite");
1779 }
1780
1781 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
1782 {
1783     VM& vm = exec->vm();
1784     NativeCallFrameTracer tracer(&vm, exec);
1785     auto scope = DECLARE_THROW_SCOPE(vm);
1786     throwStackOverflowError(exec, scope);
1787 }
1788
1789 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1790 {
1791     VM& vm = exec->vm();
1792     NativeCallFrameTracer tracer(&vm, exec);
1793     JSValue arguments = JSValue::decode(encodedArguments);
1794     
1795     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
1796 }
1797
1798 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
1799 {
1800     VM& vm = exec->vm();
1801     NativeCallFrameTracer tracer(&vm, exec);
1802     auto scope = DECLARE_THROW_SCOPE(vm);
1803
1804     JSValue key = JSValue::decode(encodedKey);
1805     Identifier propertyName = key.toPropertyKey(exec);
1806     RETURN_IF_EXCEPTION(scope, false);
1807
1808     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
1809     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
1810     RETURN_IF_EXCEPTION(scope, false);
1811
1812     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
1813     ASSERT(hasOwnPropertyCache);
1814     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
1815     return result;
1816 }
1817
1818 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
1819 {
1820     VM& vm = exec->vm();
1821     NativeCallFrameTracer tracer(&vm, exec);
1822     JSValue arguments = JSValue::decode(encodedArguments);
1823     
1824     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
1825     
1826     for (int32_t i = length; i < mandatoryMinimum; ++i)
1827         exec->r(firstElementDest + i) = jsUndefined();
1828 }
1829
1830 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1831 {
1832     return fmod(a, b);
1833 }
1834
1835 #if USE(JSVALUE32_64)
1836 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
1837 {
1838     return globalObject->weakRandomNumber();
1839 }
1840 #endif
1841
1842 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1843 {
1844     VM* vm = &exec->vm();
1845     NativeCallFrameTracer tracer(vm, exec);
1846     return JSC::stringFromCharCode(exec, op1);
1847 }
1848
1849 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
1850 {
1851     VM* vm = &exec->vm();
1852     NativeCallFrameTracer tracer(vm, exec);
1853     JSValue charValue = JSValue::decode(encodedValue);
1854     int32_t chInt = charValue.toUInt32(exec);
1855     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
1856 }
1857
1858 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
1859 {
1860     JSValue value = JSValue::decode(encodedValue);
1861     if (!value.isDouble())
1862         return JSValue::notInt52;
1863     return tryConvertToInt52(value.asDouble());
1864 }
1865
1866 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
1867 {
1868     return tryConvertToInt52(value);
1869 }
1870
1871 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
1872 {
1873     VM* vm = &exec->vm();
1874     NativeCallFrameTracer tracer(vm, exec);
1875     if (JSObject::defaultHasInstance(exec, value, proto))
1876         return 1;
1877     return 0;
1878 }
1879
1880 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
1881 {
1882     VM& vm = exec->vm();
1883     NativeCallFrameTracer tracer(&vm, exec);
1884
1885     if (!butterfly
1886         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
1887         IndexingHeader header;
1888         header.setVectorLength(length);
1889         header.setPublicLength(0);
1890         
1891         butterfly = Butterfly::create(
1892             vm, nullptr, 0, structure->outOfLineCapacity(),
1893             hasIndexedProperties(structure->indexingType()), header,
1894             length * sizeof(EncodedJSValue));
1895     }
1896
1897     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1898     result->butterfly(); // Ensure that the butterfly is in to-space.
1899     return bitwise_cast<char*>(result);
1900 }
1901
1902 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
1903 {
1904     VM& vm = exec->vm();
1905     NativeCallFrameTracer tracer(&vm, exec);
1906     
1907     if (!butterfly) {
1908         butterfly = Butterfly::create(
1909             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
1910     }
1911     
1912     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1913     result->butterfly(); // Ensure that the butterfly is in to-space.
1914     return result;
1915 }
1916
1917 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
1918 {
1919     VM& vm = exec->vm();
1920     NativeCallFrameTracer tracer(&vm, exec);
1921
1922     IndexingHeader header;
1923     header.setVectorLength(length);
1924     header.setPublicLength(0);
1925     if (butterfly)
1926         *butterfly->indexingHeader() = header;
1927     else {
1928         butterfly = Butterfly::create(
1929             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
1930             sizeof(EncodedJSValue) * length);
1931     }
1932     
1933     // Paradoxically this may allocate a JSArray. That's totally cool.
1934     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1935     result->butterfly(); // Ensure that the butterfly is in to-space.
1936     return result;
1937 }
1938
1939 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
1940 {
1941     VM& vm = exec->vm();
1942     NativeCallFrameTracer tracer(&vm, exec);
1943     auto scope = DECLARE_THROW_SCOPE(vm);
1944
1945     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
1946     unsigned length = 0;
1947     for (unsigned i = 0; i < numItems; i++) {
1948         JSValue value = JSValue::decode(values[i]);
1949         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(value))
1950             length += array->size();
1951         else
1952             ++length;
1953     }
1954
1955
1956     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1957     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
1958
1959     JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, structure, length);
1960     RETURN_IF_EXCEPTION(scope, nullptr);
1961
1962     unsigned index = 0;
1963     for (unsigned i = 0; i < numItems; i++) {
1964         JSValue value = JSValue::decode(values[i]);
1965         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(value)) {
1966             // We are spreading.
1967             for (unsigned i = 0; i < array->size(); i++) {
1968                 result->initializeIndex(vm, index, array->get(i));
1969                 ++index;
1970             }
1971         } else {
1972             // We are not spreading.
1973             result->initializeIndex(vm, index, value);
1974             ++index;
1975         }
1976     }
1977
1978     return result;
1979 }
1980
1981 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
1982 {
1983     VM& vm = exec->vm();
1984     NativeCallFrameTracer tracer(&vm, exec);
1985
1986     auto throwScope = DECLARE_THROW_SCOPE(vm);
1987
1988     if (isJSArray(iterable)) {
1989         JSArray* array = jsCast<JSArray*>(iterable);
1990         if (array->isIteratorProtocolFastAndNonObservable()) {
1991             throwScope.release();
1992             return JSFixedArray::createFromArray(exec, vm, array);
1993         }
1994     }
1995
1996     // FIXME: we can probably make this path faster by having our caller JS code call directly into
1997     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
1998
1999     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2000     JSArray* array;
2001     {
2002         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2003         CallData callData;
2004         CallType callType = JSC::getCallData(iterationFunction, callData);
2005         ASSERT(callType != CallType::None);
2006
2007         MarkedArgumentBuffer arguments;
2008         arguments.append(iterable);
2009         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2010         RETURN_IF_EXCEPTION(throwScope, nullptr);
2011         array = jsCast<JSArray*>(arrayResult);
2012     }
2013
2014     throwScope.release();
2015     return JSFixedArray::createFromArray(exec, vm, array);
2016 }
2017
2018 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2019 {
2020     VM& vm = exec->vm();
2021     NativeCallFrameTracer tracer(&vm, exec);
2022
2023     ASSERT(isJSArray(cell));
2024     JSArray* array = jsCast<JSArray*>(cell);
2025     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2026
2027     return JSFixedArray::createFromArray(exec, vm, array);
2028 }
2029
2030 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2031 {
2032     VM& vm = exec->vm();
2033     NativeCallFrameTracer tracer(&vm, exec);
2034
2035     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
2036 }
2037
2038 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
2039 {
2040     VM* vm = &exec->vm();
2041     NativeCallFrameTracer tracer(vm, exec);
2042     
2043     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
2044     CodeBlock* codeBlock = debugInfo->codeBlock;
2045     CodeBlock* alternative = codeBlock->alternative();
2046     dataLog("Speculation failure in ", *codeBlock);
2047     dataLog(" @ exit #", vm->osrExitIndex, " (bc#", debugInfo->bytecodeOffset, ", ", exitKindToString(debugInfo->kind), ") with ");
2048     if (alternative) {
2049         dataLog(
2050             "executeCounter = ", alternative->jitExecuteCounter(),
2051             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
2052             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
2053     } else
2054         dataLog("no alternative code block (i.e. we've been jettisoned)");
2055     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
2056     dataLog("    GPRs at time of exit:");
2057     char* scratchPointer = static_cast<char*>(scratch);
2058     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
2059         GPRReg gpr = GPRInfo::toRegister(i);
2060         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
2061         scratchPointer += sizeof(EncodedJSValue);
2062     }
2063     dataLog("\n");
2064     dataLog("    FPRs at time of exit:");
2065     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
2066         FPRReg fpr = FPRInfo::toRegister(i);
2067         dataLog(" ", FPRInfo::debugName(fpr), ":");
2068         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
2069         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
2070         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
2071         scratchPointer += sizeof(EncodedJSValue);
2072     }
2073     dataLog("\n");
2074 }
2075
2076 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2077 {
2078     VM& vm = exec->vm();
2079     NativeCallFrameTracer tracer(&vm, exec);
2080
2081     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2082     return resolvedScope;
2083 }
2084
2085 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2086 {
2087     VM& vm = exec->vm();
2088     NativeCallFrameTracer tracer(&vm, exec);
2089     auto throwScope = DECLARE_THROW_SCOPE(vm);
2090
2091     Identifier ident = Identifier::fromUid(exec, impl);
2092     throwScope.release();
2093     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2094         if (!found) {
2095             GetPutInfo getPutInfo(getPutInfoBits);
2096             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2097                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2098             return jsUndefined();
2099         }
2100
2101         if (scope->isGlobalLexicalEnvironment()) {
2102             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2103             JSValue result = slot.getValue(exec, ident);
2104             if (result == jsTDZValue()) {
2105                 throwException(exec, throwScope, createTDZError(exec));
2106                 return jsUndefined();
2107             }
2108             return result;
2109         }
2110
2111         return slot.getValue(exec, ident);
2112     }));
2113 }
2114
2115 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2116 {
2117     VM& vm = exec->vm();
2118     NativeCallFrameTracer tracer(&vm, exec);
2119     auto throwScope = DECLARE_THROW_SCOPE(vm);
2120
2121     const Identifier& ident = Identifier::fromUid(exec, impl);
2122     GetPutInfo getPutInfo(getPutInfoBits);
2123     bool hasProperty = scope->hasProperty(exec, ident);
2124     RETURN_IF_EXCEPTION(throwScope, void());
2125     if (hasProperty
2126         && scope->isGlobalLexicalEnvironment()
2127         && !isInitialization(getPutInfo.initializationMode())) {
2128         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2129         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2130         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2131         if (slot.getValue(exec, ident) == jsTDZValue()) {
2132             throwException(exec, throwScope, createTDZError(exec));
2133             return;
2134         }
2135     }
2136
2137     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2138         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2139         return;
2140     }
2141
2142     CodeOrigin origin = exec->codeOrigin();
2143     bool strictMode;
2144     if (origin.inlineCallFrame)
2145         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2146     else
2147         strictMode = exec->codeBlock()->isStrictMode();
2148     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2149     throwScope.release();
2150     scope->methodTable()->put(scope, exec, ident, JSValue::decode(value), slot);
2151 }
2152
2153 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2154 {
2155     VM& vm = exec->vm();
2156     NativeCallFrameTracer tracer(&vm, exec);
2157
2158     return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input)));
2159 }
2160
2161 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2162 {
2163     VM& vm = exec->vm();
2164     NativeCallFrameTracer tracer(&vm, exec);
2165     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
2166     if (!bucket)
2167         return nullptr;
2168     return *bucket;
2169 }
2170
2171 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2172 {
2173     VM& vm = exec->vm();
2174     NativeCallFrameTracer tracer(&vm, exec);
2175     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
2176     if (!bucket)
2177         return nullptr;
2178     return *bucket;
2179 }
2180
2181 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
2182 {
2183     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2184     // really be profitable.
2185     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2186     
2187     if (Options::verboseOSR())
2188         dataLog(*codeBlock, ": Entered reoptimize\n");
2189     // We must be called with the baseline code block.
2190     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2191
2192     // If I am my own replacement, then reoptimization has already been triggered.
2193     // This can happen in recursive functions.
2194     if (codeBlock->replacement() == codeBlock) {
2195         if (Options::verboseOSR())
2196             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2197         return;
2198     }
2199     
2200     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2201     // to check our logic.
2202     ASSERT(codeBlock->hasOptimizedReplacement());
2203     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2204     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2205     
2206     bool didTryToEnterIntoInlinedLoops = false;
2207     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2208         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2209             didTryToEnterIntoInlinedLoops = true;
2210             break;
2211         }
2212     }
2213
2214     // In order to trigger reoptimization, one of two things must have happened:
2215     // 1) We exited more than some number of times.
2216     // 2) We exited and got stuck in a loop, and now we're exiting again.
2217     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2218     bool didGetStuckInLoop =
2219         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2220         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2221     
2222     if (!didExitABunch && !didGetStuckInLoop) {
2223         if (Options::verboseOSR())
2224             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2225         codeBlock->optimizeAfterLongWarmUp();
2226         return;
2227     }
2228
2229     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2230 }
2231
2232 #if ENABLE(FTL_JIT)
2233 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2234 {
2235     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2236         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2237         if (Options::verboseOSR())
2238             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2239         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2240         return false;
2241     }
2242
2243     if (!codeBlock->hasOptimizedReplacement()
2244         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2245         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2246         if (Options::verboseOSR())
2247             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2248         return false;
2249     }
2250     return true;
2251 }
2252
2253 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2254 {
2255     Worklist::State worklistState;
2256     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2257         worklistState = worklist->completeAllReadyPlansForVM(
2258             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2259     } else
2260         worklistState = Worklist::NotKnown;
2261     
2262     if (worklistState == Worklist::Compiling) {
2263         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2264         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2265             codeBlock, CompilationDeferred);
2266         return;
2267     }
2268     
2269     if (codeBlock->hasOptimizedReplacement()) {
2270         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2271         // That's great, we've compiled the code - next time we call this function,
2272         // we'll enter that replacement.
2273         jitCode->optimizeSoon(codeBlock);
2274         return;
2275     }
2276     
2277     if (worklistState == Worklist::Compiled) {
2278         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2279         // This means that we finished compiling, but failed somehow; in that case the
2280         // thresholds will be set appropriately.
2281         if (Options::verboseOSR())
2282             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2283         return;
2284     }
2285
2286     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2287     // We need to compile the code.
2288     compile(
2289         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2290         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2291
2292     // If we reached here, the counter has not be reset. Do that now.
2293     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2294         codeBlock, CompilationDeferred);
2295 }
2296
2297 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2298 {
2299     VM* vm = &exec->vm();
2300     NativeCallFrameTracer tracer(vm, exec);
2301     DeferGCForAWhile deferGC(vm->heap);
2302     CodeBlock* codeBlock = exec->codeBlock();
2303     
2304     if (codeBlock->jitType() != JITCode::DFGJIT) {
2305         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2306         RELEASE_ASSERT_NOT_REACHED();
2307     }
2308     
2309     JITCode* jitCode = codeBlock->jitCode()->dfg();
2310     
2311     if (Options::verboseOSR()) {
2312         dataLog(
2313             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2314             jitCode->tierUpCounter, "\n");
2315     }
2316
2317     // This updates the execution counter.
2318     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2319         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2320
2321     if (codeBlock->hasOptimizedReplacement()) {
2322         if (jitCode->tierUpEntryTriggers.isEmpty()) {
2323             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2324             // There is nothing more we can do, the only way this will be entered
2325             // is through the function entry point.
2326             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2327             return;
2328         }
2329         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2330             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2331             // There is only one outer loop and its trigger must have been set
2332             // when the plan completed.
2333             // Exiting the inner loop is useless, we can ignore the counter and leave
2334             // the trigger do its job.
2335             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2336             return;
2337         }
2338     }
2339 }
2340
2341 enum class EntryReason {
2342     Spurious,
2343     CheckingUpOnHowCompilationIsGoing,
2344     HaveOSREntryReady,
2345     ShouldStartCompiling,
2346     ShouldStartCompilingRightNow,
2347     CompilationFailed,
2348 };
2349
2350 static EntryReason whatHaveYouDoneAndWhyAmIHere(VM* vm, CodeBlock* codeBlock, JITCode* jitCode, unsigned bytecodeIndex, CodeBlock*& osrEntryBlock)
2351 {
2352     // Gather facts about why we could be here.
2353
2354     // Resolve any pending plan for OSR Enter on this function.
2355     Worklist::State worklistState;
2356     if (Worklist* worklist = existingGlobalFTLWorklistOrNull())
2357         worklistState = worklist->completeAllReadyPlansForVM(*vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2358     else
2359         worklistState = Worklist::NotKnown;
2360
2361     osrEntryBlock = jitCode->osrEntryBlock();
2362
2363     // Was the tier-up entry trigger set to slow-path?
2364     bool triggeredSlowPath = false;
2365     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(bytecodeIndex);
2366     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
2367         if (tierUpEntryTriggers->value == TierUpEntryTrigger::TakeSlowPath) {
2368             // We were asked to enter as soon as possible. Unset this trigger so we don't continually enter.
2369             if (Options::verboseOSR())
2370                 dataLog("EntryTrigger for ", *codeBlock, " forced slow-path.\n");
2371             triggeredSlowPath = true;
2372             tierUpEntryTriggers->value = TierUpEntryTrigger::None;
2373         }
2374     }
2375
2376     // Put those facts together to make a final determination.
2377
2378     switch (worklistState) {
2379     case Worklist::NotKnown:
2380         if (osrEntryBlock)
2381             return EntryReason::HaveOSREntryReady;
2382         if (triggeredSlowPath) {
2383             // Someone went through the trouble of forcing us into slow-path, they really wanted us to compile.
2384             return EntryReason::ShouldStartCompilingRightNow;
2385         }
2386         return EntryReason::ShouldStartCompiling;
2387
2388     case Worklist::Compiling:
2389         if (triggeredSlowPath) {
2390             // We're already compiling, and can't OSR enter. We therefore must
2391             // have set our slow-path trigger as well as another slow path
2392             // trigger, hoping one of these would kick off a compilation. Sure
2393             // enough another bytecode location did kick off a compilation
2394             // before this one got a chance to do so. There's nothing for us to
2395             // do but wait.
2396             return EntryReason::Spurious;
2397         }
2398         return EntryReason::CheckingUpOnHowCompilationIsGoing;
2399
2400     case Worklist::Compiled:
2401         return EntryReason::CompilationFailed;
2402     }
2403
2404     RELEASE_ASSERT_NOT_REACHED();
2405     return EntryReason::Spurious;
2406 }
2407
2408 enum class CanOSREnterFromHere {
2409     No,
2410     Yes,
2411 };
2412
2413 static char* tierUpCommon(VM* vm, ExecState* exec, CodeBlock* codeBlock, JITCode* jitCode, unsigned bytecodeIndex, CanOSREnterFromHere canOSREnterFromHere)
2414 {
2415     CodeBlock* osrEntryBlock;
2416     EntryReason entryReason = whatHaveYouDoneAndWhyAmIHere(vm, codeBlock, jitCode, bytecodeIndex, osrEntryBlock);
2417
2418     switch (entryReason) {
2419     case EntryReason::CheckingUpOnHowCompilationIsGoing:
2420         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2421         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2422             codeBlock, CompilationDeferred);
2423         return nullptr;
2424
2425     case EntryReason::CompilationFailed:
2426         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2427         // We've already set the thresholds.
2428         if (Options::verboseOSR())
2429             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2430         return nullptr;
2431
2432     case EntryReason::HaveOSREntryReady:
2433         if (canOSREnterFromHere == CanOSREnterFromHere::No)
2434             break; // OSR entry is for another location.
2435
2436         {
2437             // If we can OSR Enter, do it right away.
2438             unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(bytecodeIndex);
2439             auto osrEntryPreparation = FTL::prepareOSREntry(exec, codeBlock, osrEntryBlock, bytecodeIndex, streamIndex);
2440             if (osrEntryPreparation) {
2441                 CODEBLOCK_LOG_EVENT(osrEntryBlock, "osrEntry", ("at bc#", bytecodeIndex));
2442                 void* address = osrEntryPreparation.value();
2443                 ASSERT(address);
2444                 return static_cast<char*>(address);
2445             }
2446             switch (osrEntryPreparation.error()) {
2447             case FTL::OSREntryFail::StackGrowthFailed:
2448                 break;
2449             case FTL::OSREntryFail::WrongBytecode:
2450                 // Above we checked that an entry was possible from the current
2451                 // location, but we didn't know whether the compiled OSR entry
2452                 // was for this location. Now we know it's not.
2453                 break;
2454             }
2455
2456             break;
2457         }
2458
2459     case EntryReason::ShouldStartCompiling:
2460     case EntryReason::ShouldStartCompilingRightNow:
2461         // We'll take care of that below.
2462         break;
2463
2464     case EntryReason::Spurious:
2465         if (Options::verboseOSR())
2466             dataLog("Code block ", *codeBlock, " was spuriously woken up, compilation is already under way.\n");
2467         jitCode->checkIfOptimizationThresholdReached(codeBlock);
2468         return nullptr;
2469     }
2470
2471     // - If we don't have an FTL code block, then try to compile one.
2472     // - If we do have an FTL code block, then try to enter for a while.
2473     // - If we couldn't enter for a while, then trigger OSR entry.
2474
2475     // This updates the execution counter.
2476     if (!shouldTriggerFTLCompile(codeBlock, jitCode))
2477         return nullptr;
2478
2479     if (!jitCode->neverExecutedEntry) {
2480         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2481
2482         if (!codeBlock->hasOptimizedReplacement())
2483             return nullptr;
2484
2485         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2486             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2487             jitCode->osrEntryRetry++;
2488             return nullptr;
2489         }
2490     } else
2491         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2492
2493     if (osrEntryBlock) {
2494         // We have a compiled OSR entry for this function, but didn't enter.
2495
2496         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2497             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2498             jitCode->osrEntryRetry++;
2499             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2500                 codeBlock, CompilationDeferred);
2501             return nullptr;
2502         }
2503
2504         FTL::ForOSREntryJITCode* entryCode = osrEntryBlock->jitCode()->ftlForOSREntry();
2505         entryCode->countEntryFailure();
2506         if (entryCode->entryFailureCount() <
2507             Options::ftlOSREntryFailureCountForReoptimization()) {
2508             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2509             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2510                 codeBlock, CompilationDeferred);
2511             return nullptr;
2512         }
2513
2514         // OSR entry failed. Oh no! This implies that we need to retry. We retry
2515         // without exponential backoff and we only do this for the entry code block.
2516         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2517         unsigned osrEntryBytecode = osrEntryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2518         jitCode->clearOSREntryBlock();
2519         jitCode->osrEntryRetry = 0;
2520         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, TierUpEntryTrigger::None);
2521         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2522             codeBlock, CompilationDeferred);
2523         return nullptr;
2524     }
2525
2526     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile something.
2527
2528     if (entryReason != EntryReason::ShouldStartCompilingRightNow) {
2529         // We entered because our threshold was set, not because someone is forcing us to compile.
2530         // Try to see if there would be a better place to compile from than where we currently are.
2531
2532         // Compiling an outer-loop for OSR entry often generates better code than an inner-loop because
2533         // the entry is less disruptive. If we're at an inner-loop be smart and mark the outer-loop as
2534         // needing compilation ASAP. Once execution reaches the outer-loop compilation will trigger.
2535         auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
2536         if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end() && !tierUpHierarchyEntry->value.isEmpty()) {
2537             // Traverse the loop hierarchy from the outer-most loop, to the inner-most one.
2538             for (auto iterator = tierUpHierarchyEntry->value.rbegin(), end = tierUpHierarchyEntry->value.rend(); iterator != end; ++iterator) {
2539                 unsigned osrEntryCandidate = *iterator;
2540                 if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
2541                     unsigned outerLoopOsrEntryBytecodeIndex = osrEntryCandidate;
2542
2543                     // We found an outer-loop which would be a better OSR entry
2544                     // than the current location:
2545                     //  - Set its trigger so it takes the slow-path ASAP;
2546                     //  - Tell the codeblock to stop its counter slow-path for a
2547                     //    while, because it should wait for the outer-loop to
2548                     //    trigger.
2549                     //
2550                     // If we slow-path again then one of these is true:
2551                     //  1. We enter from the outer-loop because of its trigger,
2552                     //     it un-sets its trigger, kicks off a compile,
2553                     //     everything is good;
2554                     //  2. We enter from anywhere and a compile is under way,
2555                     //     just chill as usual;
2556                     //  3. We never got to that outer-loop and the counter
2557                     //     tripped again, bummer!
2558                     //
2559                     // We can detect 3. because the outer-loop's trigger is
2560                     // set. It's still a great place to enter, so leave its
2561                     // trigger set, but also:
2562                     //  - Set the trigger for the next loop in, hope that one triggers;
2563                     //  - Backoff the counter as before.
2564                     // That is, unless all the inner-loop's parent triggers are
2565                     // set. In that case just optimize the innermost-loop: it
2566                     // won't generate as good code, but the outer-loops aren't
2567                     // triggering so we may as we tier up where we can.
2568                     auto outerLoopTierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(outerLoopOsrEntryBytecodeIndex);
2569                     ASSERT(outerLoopTierUpEntryTriggers != jitCode->tierUpEntryTriggers.end());
2570
2571                     if (outerLoopTierUpEntryTriggers->value != TierUpEntryTrigger::TakeSlowPath) {
2572                         if (Options::verboseOSR())
2573                             dataLog("Forcibly FTL-optimize outer-loop bc#", outerLoopOsrEntryBytecodeIndex, " in ", *codeBlock, "by setting its trigger.\n");
2574
2575                         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry request from inner-loop for outer-loop"));
2576                         jitCode->tierUpEntryTriggers.set(outerLoopOsrEntryBytecodeIndex, TierUpEntryTrigger::TakeSlowPath);
2577                         jitCode->optimizeSoon(codeBlock);
2578                         return nullptr;
2579                     }
2580
2581                     if (Options::verboseOSR())
2582                         dataLog("Trying to forcibly FTL-optimize outer-loop bc#", outerLoopOsrEntryBytecodeIndex, " in ", *codeBlock, ", but trigger is already set.\n");
2583                 }
2584             }
2585
2586             // All the outer-loops have their trigger set, but none have been entered.
2587
2588             if (canOSREnterFromHere == CanOSREnterFromHere::No) {
2589                 // We just can't enter from here, we've asked everyone we know
2590                 // to please optimize ASAP, nobody has heeded our call. Keep
2591                 // hoping one of the outer loops triggers get to their slow
2592                 // path. Stop the counter, there's nothing we can do.
2593                 jitCode->dontOptimizeAnytimeSoon(codeBlock);
2594                 return nullptr;
2595             }
2596
2597             if (Options::verboseOSR())
2598                 dataLog("Tried to forcibly-optimize outer-loop, but falling back to bc#", bytecodeIndex, " in ", *codeBlock, ", outer-loop triggers didn't work.\n");
2599         }
2600     }
2601
2602     RELEASE_ASSERT(canOSREnterFromHere == CanOSREnterFromHere::Yes);
2603
2604     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(bytecodeIndex);
2605
2606     // We're not trying to kick off a compile of an outer-loop from within an
2607     // inner-loop. We can compile right here, right now.
2608     auto triggerIterator = jitCode->tierUpEntryTriggers.find(bytecodeIndex);
2609     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
2610     TierUpEntryTrigger* triggerAddress = &(triggerIterator->value);
2611
2612     // Use OSR reconstruction to generate a snapshot of JSValues at the current
2613     // location of execution. The optimizer is happy when it can look at real
2614     // and live values, as opposed to mere type traces.
2615     Operands<JSValue> mustHandleValues;
2616     jitCode->reconstruct(
2617         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
2618     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2619
2620     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
2621     CompilationResult forEntryResult = compile(
2622         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
2623         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
2624
2625     if (jitCode->neverExecutedEntry)
2626         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2627
2628     if (forEntryResult != CompilationSuccessful) {
2629         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
2630         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2631             codeBlock, CompilationDeferred);
2632         return nullptr;
2633     }
2634
2635     // It's possible that the for-entry compile already succeeded. In that case
2636     // OSR entry will succeed unless we ran out of stack.
2637     auto osrEntryPreparation = FTL::prepareOSREntry(exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
2638     if (osrEntryPreparation) {
2639         CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", bytecodeIndex));
2640         void* address = osrEntryPreparation.value();
2641         ASSERT(address);
2642         return static_cast<char*>(address);
2643     }
2644     switch (osrEntryPreparation.error()) {
2645     case FTL::OSREntryFail::StackGrowthFailed:
2646         // It's not clear what we should do. We signal to try again after a
2647         // while if that happens.
2648         return nullptr;
2649     case FTL::OSREntryFail::WrongBytecode:
2650         RELEASE_ASSERT_NOT_REACHED();
2651     }
2652
2653     RELEASE_ASSERT_NOT_REACHED();
2654     return nullptr;
2655 }
2656
2657 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
2658 {
2659     VM* vm = &exec->vm();
2660     NativeCallFrameTracer tracer(vm, exec);
2661     DeferGCForAWhile deferGC(vm->heap);
2662     CodeBlock* codeBlock = exec->codeBlock();
2663
2664     if (codeBlock->jitType() != JITCode::DFGJIT) {
2665         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2666         RELEASE_ASSERT_NOT_REACHED();
2667     }
2668
2669     JITCode* jitCode = codeBlock->jitCode()->dfg();
2670
2671     if (Options::verboseOSR()) {
2672         dataLog(
2673             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
2674             jitCode->tierUpCounter, "\n");
2675     }
2676
2677     // It's impossible to OSR enter from the current bytecode index: CheckTierUpInLoop is only even generated for non-OSR-entry bytecodes.
2678     // It's nonetheless a good spot to request that a nearby loop get optimized the next time it's entered.
2679
2680     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
2681     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
2682         && !tierUpHierarchyEntry->value.isEmpty()) {
2683         // There is a suitable loop to OSR enter from.
2684         tierUpCommon(vm, exec, codeBlock, jitCode, bytecodeIndex, CanOSREnterFromHere::No);
2685     } else if (shouldTriggerFTLCompile(codeBlock, jitCode)) // This updates the execution counter.
2686         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2687
2688     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
2689     if (codeBlock->hasOptimizedReplacement()) {
2690         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
2691         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2692     }
2693 }
2694
2695 char* JIT_OPERATION checkTierUpAndOSREnterNow(ExecState* exec, unsigned bytecodeIndex)
2696 {
2697     VM* vm = &exec->vm();
2698     NativeCallFrameTracer tracer(vm, exec);
2699     DeferGCForAWhile deferGC(vm->heap);
2700     CodeBlock* codeBlock = exec->codeBlock();
2701
2702     if (codeBlock->jitType() != JITCode::DFGJIT) {
2703         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2704         RELEASE_ASSERT_NOT_REACHED();
2705     }
2706
2707     JITCode* jitCode = codeBlock->jitCode()->dfg();
2708
2709     if (Options::verboseOSR()) {
2710         dataLog(
2711             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
2712             jitCode->tierUpCounter, "\n");
2713     }
2714
2715     jitCode->tierUpEntrySeen.add(bytecodeIndex);
2716     return tierUpCommon(vm, exec, codeBlock, jitCode, bytecodeIndex, CanOSREnterFromHere::Yes);
2717 }
2718
2719 #endif // ENABLE(FTL_JIT)
2720
2721 } // extern "C"
2722 } } // namespace JSC::DFG
2723
2724 #endif // ENABLE(DFG_JIT)
2725
2726 #endif // ENABLE(JIT)