OSR entry: delay outer-loop compilation when at inner-loop
[WebKit-https.git] / Source / JavaScriptCore / jit / JITOperations.cpp
1 /*
2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "JITOperations.h"
28
29 #if ENABLE(JIT)
30
31 #include "ArithProfile.h"
32 #include "ArrayConstructor.h"
33 #include "CommonSlowPaths.h"
34 #include "DFGCompilationMode.h"
35 #include "DFGDriver.h"
36 #include "DFGOSREntry.h"
37 #include "DFGThunks.h"
38 #include "DFGWorklist.h"
39 #include "Debugger.h"
40 #include "DirectArguments.h"
41 #include "Error.h"
42 #include "ErrorHandlingScope.h"
43 #include "EvalCodeBlock.h"
44 #include "ExceptionFuzz.h"
45 #include "FunctionCodeBlock.h"
46 #include "GetterSetter.h"
47 #include "HostCallReturnValue.h"
48 #include "ICStats.h"
49 #include "Interpreter.h"
50 #include "JIT.h"
51 #include "JITExceptions.h"
52 #include "JITToDFGDeferredCompilationCallback.h"
53 #include "JSAsyncFunction.h"
54 #include "JSCInlines.h"
55 #include "JSGeneratorFunction.h"
56 #include "JSGlobalObjectFunctions.h"
57 #include "JSLexicalEnvironment.h"
58 #include "JSPropertyNameEnumerator.h"
59 #include "ModuleProgramCodeBlock.h"
60 #include "ObjectConstructor.h"
61 #include "PolymorphicAccess.h"
62 #include "ProgramCodeBlock.h"
63 #include "PropertyName.h"
64 #include "RegExpObject.h"
65 #include "Repatch.h"
66 #include "ScopedArguments.h"
67 #include "ShadowChicken.h"
68 #include "StructureStubInfo.h"
69 #include "SuperSampler.h"
70 #include "TestRunnerUtils.h"
71 #include "TypeProfilerLog.h"
72 #include "VMInlines.h"
73 #include <wtf/InlineASM.h>
74
75 namespace JSC {
76
77 extern "C" {
78
79 #if COMPILER(MSVC)
80 void * _ReturnAddress(void);
81 #pragma intrinsic(_ReturnAddress)
82
83 #define OUR_RETURN_ADDRESS _ReturnAddress()
84 #else
85 #define OUR_RETURN_ADDRESS __builtin_return_address(0)
86 #endif
87
88 #if ENABLE(OPCODE_SAMPLING)
89 #define CTI_SAMPLER vm->interpreter->sampler()
90 #else
91 #define CTI_SAMPLER 0
92 #endif
93
94
95 void JIT_OPERATION operationThrowStackOverflowError(ExecState* exec, CodeBlock* codeBlock)
96 {
97     // We pass in our own code block, because the callframe hasn't been populated.
98     VM* vm = codeBlock->vm();
99     auto scope = DECLARE_THROW_SCOPE(*vm);
100
101     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
102     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
103     if (!callerFrame) {
104         callerFrame = exec;
105         vmEntryFrame = vm->topVMEntryFrame;
106     }
107
108     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
109     throwStackOverflowError(callerFrame, scope);
110 }
111
112 #if ENABLE(WEBASSEMBLY)
113 void JIT_OPERATION operationThrowDivideError(ExecState* exec)
114 {
115     VM* vm = &exec->vm();
116     auto scope = DECLARE_THROW_SCOPE(*vm);
117
118     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
119     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
120
121     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
122     ErrorHandlingScope errorScope(*vm);
123     throwException(callerFrame, scope, createError(callerFrame, ASCIILiteral("Division by zero or division overflow.")));
124 }
125
126 void JIT_OPERATION operationThrowOutOfBoundsAccessError(ExecState* exec)
127 {
128     VM* vm = &exec->vm();
129     auto scope = DECLARE_THROW_SCOPE(*vm);
130
131     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
132     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
133
134     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
135     ErrorHandlingScope errorScope(*vm);
136     throwException(callerFrame, scope, createError(callerFrame, ASCIILiteral("Out-of-bounds access.")));
137 }
138 #endif
139
140 int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
141 {
142     VM* vm = &exec->vm();
143     auto scope = DECLARE_THROW_SCOPE(*vm);
144
145     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, *vm, CodeForCall);
146     if (missingArgCount < 0) {
147         VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
148         CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
149         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
150         throwStackOverflowError(callerFrame, scope);
151     }
152
153     return missingArgCount;
154 }
155
156 int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
157 {
158     VM* vm = &exec->vm();
159     auto scope = DECLARE_THROW_SCOPE(*vm);
160
161     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, *vm, CodeForConstruct);
162     if (missingArgCount < 0) {
163         VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
164         CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
165         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
166         throwStackOverflowError(callerFrame, scope);
167     }
168
169     return missingArgCount;
170 }
171
172 EncodedJSValue JIT_OPERATION operationTryGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
173 {
174     VM* vm = &exec->vm();
175     NativeCallFrameTracer tracer(vm, exec);
176     Identifier ident = Identifier::fromUid(vm, uid);
177     stubInfo->tookSlowPath = true;
178
179     JSValue baseValue = JSValue::decode(base);
180     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
181     baseValue.getPropertySlot(exec, ident, slot);
182
183     return JSValue::encode(slot.getPureResult());
184 }
185
186
187 EncodedJSValue JIT_OPERATION operationTryGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
188 {
189     VM* vm = &exec->vm();
190     NativeCallFrameTracer tracer(vm, exec);
191     Identifier ident = Identifier::fromUid(vm, uid);
192
193     JSValue baseValue = JSValue::decode(base);
194     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
195     baseValue.getPropertySlot(exec, ident, slot);
196
197     return JSValue::encode(slot.getPureResult());
198 }
199
200 EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
201 {
202     VM* vm = &exec->vm();
203     NativeCallFrameTracer tracer(vm, exec);
204     auto scope = DECLARE_THROW_SCOPE(*vm);
205     Identifier ident = Identifier::fromUid(vm, uid);
206
207     JSValue baseValue = JSValue::decode(base);
208     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
209
210     baseValue.getPropertySlot(exec, ident, slot);
211     RETURN_IF_EXCEPTION(scope, encodedJSValue());
212
213     if (stubInfo->considerCaching(baseValue.structureOrNull()) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
214         repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
215
216     return JSValue::encode(slot.getPureResult());
217 }
218
219 EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
220 {
221     SuperSamplerScope superSamplerScope(false);
222     
223     VM* vm = &exec->vm();
224     NativeCallFrameTracer tracer(vm, exec);
225     
226     stubInfo->tookSlowPath = true;
227     
228     JSValue baseValue = JSValue::decode(base);
229     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
230     Identifier ident = Identifier::fromUid(vm, uid);
231     
232     LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(), ident));
233     return JSValue::encode(baseValue.get(exec, ident, slot));
234 }
235
236 EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
237 {
238     SuperSamplerScope superSamplerScope(false);
239     
240     VM* vm = &exec->vm();
241     NativeCallFrameTracer tracer(vm, exec);
242     
243     JSValue baseValue = JSValue::decode(base);
244     PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
245     Identifier ident = Identifier::fromUid(vm, uid);
246     LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(), ident));
247     return JSValue::encode(baseValue.get(exec, ident, slot));
248 }
249
250 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
251 {
252     SuperSamplerScope superSamplerScope(false);
253     
254     VM* vm = &exec->vm();
255     NativeCallFrameTracer tracer(vm, exec);
256     Identifier ident = Identifier::fromUid(vm, uid);
257
258     JSValue baseValue = JSValue::decode(base);
259     LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(), ident));
260
261     return JSValue::encode(baseValue.getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
262         if (stubInfo->considerCaching(baseValue.structureOrNull()))
263             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
264         return found ? slot.getValue(exec, ident) : jsUndefined();
265     }));
266 }
267
268 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
269 {
270     SuperSamplerScope superSamplerScope(false);
271     
272     VM* vm = &exec->vm();
273     NativeCallFrameTracer tracer(vm, exec);
274     auto scope = DECLARE_THROW_SCOPE(*vm);
275
276     if (!base->isObject()) {
277         throwException(exec, scope, createInvalidInParameterError(exec, base));
278         return JSValue::encode(jsUndefined());
279     }
280     
281     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
282
283     Identifier ident = Identifier::fromUid(vm, key);
284     LOG_IC((ICEvent::OperationInOptimize, base->classInfo(), ident));
285     PropertySlot slot(base, PropertySlot::InternalMethodType::HasProperty);
286     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
287     RETURN_IF_EXCEPTION(scope, encodedJSValue());
288     
289     RELEASE_ASSERT(accessType == stubInfo->accessType);
290     
291     if (stubInfo->considerCaching(asObject(base)->structure()))
292         repatchIn(exec, base, ident, result, slot, *stubInfo);
293     
294     return JSValue::encode(jsBoolean(result));
295 }
296
297 EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
298 {
299     SuperSamplerScope superSamplerScope(false);
300     
301     VM* vm = &exec->vm();
302     NativeCallFrameTracer tracer(vm, exec);
303     auto scope = DECLARE_THROW_SCOPE(*vm);
304
305     stubInfo->tookSlowPath = true;
306
307     if (!base->isObject()) {
308         throwException(exec, scope, createInvalidInParameterError(exec, base));
309         return JSValue::encode(jsUndefined());
310     }
311
312     Identifier ident = Identifier::fromUid(vm, key);
313     LOG_IC((ICEvent::OperationIn, base->classInfo(), ident));
314     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
315 }
316
317 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key)
318 {
319     SuperSamplerScope superSamplerScope(false);
320     
321     VM* vm = &exec->vm();
322     NativeCallFrameTracer tracer(vm, exec);
323
324     return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
325 }
326
327 void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
328 {
329     SuperSamplerScope superSamplerScope(false);
330     
331     VM* vm = &exec->vm();
332     NativeCallFrameTracer tracer(vm, exec);
333     
334     stubInfo->tookSlowPath = true;
335     
336     JSValue baseValue = JSValue::decode(encodedBase);
337     Identifier ident = Identifier::fromUid(vm, uid);
338     LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(), ident));
339
340     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
341     baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
342 }
343
344 void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
345 {
346     SuperSamplerScope superSamplerScope(false);
347     
348     VM* vm = &exec->vm();
349     NativeCallFrameTracer tracer(vm, exec);
350     
351     stubInfo->tookSlowPath = true;
352     
353     JSValue baseValue = JSValue::decode(encodedBase);
354     Identifier ident = Identifier::fromUid(vm, uid);
355     LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(), ident));
356     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
357     baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
358 }
359
360 void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
361 {
362     SuperSamplerScope superSamplerScope(false);
363     
364     VM* vm = &exec->vm();
365     NativeCallFrameTracer tracer(vm, exec);
366     
367     stubInfo->tookSlowPath = true;
368     
369     JSValue baseValue = JSValue::decode(encodedBase);
370     Identifier ident = Identifier::fromUid(vm, uid);
371     LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(), ident));
372     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
373     asObject(baseValue)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
374 }
375
376 void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
377 {
378     SuperSamplerScope superSamplerScope(false);
379     
380     VM* vm = &exec->vm();
381     NativeCallFrameTracer tracer(vm, exec);
382     
383     stubInfo->tookSlowPath = true;
384     
385     JSValue baseValue = JSValue::decode(encodedBase);
386     Identifier ident = Identifier::fromUid(vm, uid);
387     LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(), ident));
388     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
389     asObject(baseValue)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
390 }
391
392 void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
393 {
394     SuperSamplerScope superSamplerScope(false);
395     
396     VM* vm = &exec->vm();
397     NativeCallFrameTracer tracer(vm, exec);
398     auto scope = DECLARE_THROW_SCOPE(*vm);
399
400     Identifier ident = Identifier::fromUid(vm, uid);
401     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
402
403     JSValue value = JSValue::decode(encodedValue);
404     JSValue baseValue = JSValue::decode(encodedBase);
405     LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(), ident));
406     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
407
408     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
409     baseValue.putInline(exec, ident, value, slot);
410     RETURN_IF_EXCEPTION(scope, void());
411
412     if (accessType != static_cast<AccessType>(stubInfo->accessType))
413         return;
414     
415     if (stubInfo->considerCaching(structure))
416         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
417 }
418
419 void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
420 {
421     SuperSamplerScope superSamplerScope(false);
422     
423     VM* vm = &exec->vm();
424     NativeCallFrameTracer tracer(vm, exec);
425     auto scope = DECLARE_THROW_SCOPE(*vm);
426
427     Identifier ident = Identifier::fromUid(vm, uid);
428     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
429
430     JSValue value = JSValue::decode(encodedValue);
431     JSValue baseValue = JSValue::decode(encodedBase);
432     LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(), ident));
433     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
434
435     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
436     baseValue.putInline(exec, ident, value, slot);
437     RETURN_IF_EXCEPTION(scope, void());
438
439     if (accessType != static_cast<AccessType>(stubInfo->accessType))
440         return;
441     
442     if (stubInfo->considerCaching(structure))
443         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
444 }
445
446 void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
447 {
448     SuperSamplerScope superSamplerScope(false);
449     
450     VM* vm = &exec->vm();
451     NativeCallFrameTracer tracer(vm, exec);
452     
453     Identifier ident = Identifier::fromUid(vm, uid);
454     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
455
456     JSValue value = JSValue::decode(encodedValue);
457     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
458     LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(), ident));
459     PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
460     
461     Structure* structure = baseObject->structure(*vm);
462     baseObject->putDirect(exec->vm(), ident, value, slot);
463     
464     if (accessType != static_cast<AccessType>(stubInfo->accessType))
465         return;
466     
467     if (stubInfo->considerCaching(structure))
468         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
469 }
470
471 void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
472 {
473     SuperSamplerScope superSamplerScope(false);
474     
475     VM* vm = &exec->vm();
476     NativeCallFrameTracer tracer(vm, exec);
477     
478     Identifier ident = Identifier::fromUid(vm, uid);
479     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
480
481     JSValue value = JSValue::decode(encodedValue);
482     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
483     LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(), ident));
484     PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
485     
486     Structure* structure = baseObject->structure(*vm);
487     baseObject->putDirect(exec->vm(), ident, value, slot);
488     
489     if (accessType != static_cast<AccessType>(stubInfo->accessType))
490         return;
491     
492     if (stubInfo->considerCaching(structure))
493         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
494 }
495
496 ALWAYS_INLINE static bool isStringOrSymbol(JSValue value)
497 {
498     return value.isString() || value.isSymbol();
499 }
500
501 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo)
502 {
503     VM& vm = callFrame->vm();
504     auto scope = DECLARE_THROW_SCOPE(vm);
505     if (LIKELY(subscript.isUInt32())) {
506         byValInfo->tookSlowPath = true;
507         uint32_t i = subscript.asUInt32();
508         if (baseValue.isObject()) {
509             JSObject* object = asObject(baseValue);
510             if (object->canSetIndexQuickly(i))
511                 object->setIndexQuickly(callFrame->vm(), i, value);
512             else {
513                 // FIXME: This will make us think that in-bounds typed array accesses are actually
514                 // out-of-bounds.
515                 // https://bugs.webkit.org/show_bug.cgi?id=149886
516                 byValInfo->arrayProfile->setOutOfBounds();
517                 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
518             }
519         } else
520             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
521         return;
522     }
523
524     auto property = subscript.toPropertyKey(callFrame);
525     // Don't put to an object if toString threw an exception.
526     RETURN_IF_EXCEPTION(scope, void());
527
528     if (byValInfo->stubInfo && (!isStringOrSymbol(subscript) || byValInfo->cachedId != property))
529         byValInfo->tookSlowPath = true;
530
531     scope.release();
532     PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
533     baseValue.putInline(callFrame, property, value, slot);
534 }
535
536 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo)
537 {
538     VM& vm = callFrame->vm();
539     auto scope = DECLARE_THROW_SCOPE(vm);
540     bool isStrictMode = callFrame->codeBlock()->isStrictMode();
541     if (LIKELY(subscript.isUInt32())) {
542         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
543         byValInfo->tookSlowPath = true;
544         uint32_t index = subscript.asUInt32();
545         ASSERT(isIndex(index));
546         if (baseObject->canSetIndexQuicklyForPutDirect(index)) {
547             baseObject->setIndexQuickly(callFrame->vm(), index, value);
548             return;
549         }
550
551         // FIXME: This will make us think that in-bounds typed array accesses are actually
552         // out-of-bounds.
553         // https://bugs.webkit.org/show_bug.cgi?id=149886
554         byValInfo->arrayProfile->setOutOfBounds();
555         baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
556         return;
557     }
558
559     if (subscript.isDouble()) {
560         double subscriptAsDouble = subscript.asDouble();
561         uint32_t subscriptAsUInt32 = static_cast<uint32_t>(subscriptAsDouble);
562         if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
563             byValInfo->tookSlowPath = true;
564             baseObject->putDirectIndex(callFrame, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
565             return;
566         }
567     }
568
569     // Don't put to an object if toString threw an exception.
570     auto property = subscript.toPropertyKey(callFrame);
571     RETURN_IF_EXCEPTION(scope, void());
572
573     if (std::optional<uint32_t> index = parseIndex(property)) {
574         byValInfo->tookSlowPath = true;
575         baseObject->putDirectIndex(callFrame, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
576         return;
577     }
578
579     if (byValInfo->stubInfo && (!isStringOrSymbol(subscript) || byValInfo->cachedId != property))
580         byValInfo->tookSlowPath = true;
581
582     PutPropertySlot slot(baseObject, isStrictMode);
583     baseObject->putDirect(callFrame->vm(), property, value, slot);
584 }
585
586 enum class OptimizationResult {
587     NotOptimized,
588     SeenOnce,
589     Optimized,
590     GiveUp,
591 };
592
593 static OptimizationResult tryPutByValOptimize(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
594 {
595     // See if it's worth optimizing at all.
596     OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
597
598     VM& vm = exec->vm();
599
600     if (baseValue.isObject() && subscript.isInt32()) {
601         JSObject* object = asObject(baseValue);
602
603         ASSERT(exec->bytecodeOffset());
604         ASSERT(!byValInfo->stubRoutine);
605
606         Structure* structure = object->structure(vm);
607         if (hasOptimizableIndexing(structure)) {
608             // Attempt to optimize.
609             JITArrayMode arrayMode = jitArrayModeForStructure(structure);
610             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
611                 CodeBlock* codeBlock = exec->codeBlock();
612                 ConcurrentJSLocker locker(codeBlock->m_lock);
613                 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
614
615                 JIT::compilePutByVal(&vm, exec->codeBlock(), byValInfo, returnAddress, arrayMode);
616                 optimizationResult = OptimizationResult::Optimized;
617             }
618         }
619
620         // If we failed to patch and we have some object that intercepts indexed get, then don't even wait until 10 times.
621         if (optimizationResult != OptimizationResult::Optimized && object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
622             optimizationResult = OptimizationResult::GiveUp;
623     }
624
625     if (baseValue.isObject() && isStringOrSymbol(subscript)) {
626         const Identifier propertyName = subscript.toPropertyKey(exec);
627         if (subscript.isSymbol() || !parseIndex(propertyName)) {
628             ASSERT(exec->bytecodeOffset());
629             ASSERT(!byValInfo->stubRoutine);
630             if (byValInfo->seen) {
631                 if (byValInfo->cachedId == propertyName) {
632                     JIT::compilePutByValWithCachedId(&vm, exec->codeBlock(), byValInfo, returnAddress, NotDirect, propertyName);
633                     optimizationResult = OptimizationResult::Optimized;
634                 } else {
635                     // Seem like a generic property access site.
636                     optimizationResult = OptimizationResult::GiveUp;
637                 }
638             } else {
639                 CodeBlock* codeBlock = exec->codeBlock();
640                 ConcurrentJSLocker locker(codeBlock->m_lock);
641                 byValInfo->seen = true;
642                 byValInfo->cachedId = propertyName;
643                 if (subscript.isSymbol())
644                     byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
645                 optimizationResult = OptimizationResult::SeenOnce;
646             }
647         }
648     }
649
650     if (optimizationResult != OptimizationResult::Optimized && optimizationResult != OptimizationResult::SeenOnce) {
651         // If we take slow path more than 10 times without patching then make sure we
652         // never make that mistake again. For cases where we see non-index-intercepting
653         // objects, this gives 10 iterations worth of opportunity for us to observe
654         // that the put_by_val may be polymorphic. We count up slowPathCount even if
655         // the result is GiveUp.
656         if (++byValInfo->slowPathCount >= 10)
657             optimizationResult = OptimizationResult::GiveUp;
658     }
659
660     return optimizationResult;
661 }
662
663 void JIT_OPERATION operationPutByValOptimize(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
664 {
665     VM& vm = exec->vm();
666     NativeCallFrameTracer tracer(&vm, exec);
667
668     JSValue baseValue = JSValue::decode(encodedBaseValue);
669     JSValue subscript = JSValue::decode(encodedSubscript);
670     JSValue value = JSValue::decode(encodedValue);
671     if (tryPutByValOptimize(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) {
672         // Don't ever try to optimize.
673         byValInfo->tookSlowPath = true;
674         ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
675     }
676     putByVal(exec, baseValue, subscript, value, byValInfo);
677 }
678
679 static OptimizationResult tryDirectPutByValOptimize(ExecState* exec, JSObject* object, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
680 {
681     // See if it's worth optimizing at all.
682     OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
683
684     VM& vm = exec->vm();
685
686     if (subscript.isInt32()) {
687         ASSERT(exec->bytecodeOffset());
688         ASSERT(!byValInfo->stubRoutine);
689
690         Structure* structure = object->structure(vm);
691         if (hasOptimizableIndexing(structure)) {
692             // Attempt to optimize.
693             JITArrayMode arrayMode = jitArrayModeForStructure(structure);
694             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
695                 CodeBlock* codeBlock = exec->codeBlock();
696                 ConcurrentJSLocker locker(codeBlock->m_lock);
697                 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
698
699                 JIT::compileDirectPutByVal(&vm, exec->codeBlock(), byValInfo, returnAddress, arrayMode);
700                 optimizationResult = OptimizationResult::Optimized;
701             }
702         }
703
704         // If we failed to patch and we have some object that intercepts indexed get, then don't even wait until 10 times.
705         if (optimizationResult != OptimizationResult::Optimized && object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
706             optimizationResult = OptimizationResult::GiveUp;
707     } else if (isStringOrSymbol(subscript)) {
708         const Identifier propertyName = subscript.toPropertyKey(exec);
709         if (subscript.isSymbol() || !parseIndex(propertyName)) {
710             ASSERT(exec->bytecodeOffset());
711             ASSERT(!byValInfo->stubRoutine);
712             if (byValInfo->seen) {
713                 if (byValInfo->cachedId == propertyName) {
714                     JIT::compilePutByValWithCachedId(&vm, exec->codeBlock(), byValInfo, returnAddress, Direct, propertyName);
715                     optimizationResult = OptimizationResult::Optimized;
716                 } else {
717                     // Seem like a generic property access site.
718                     optimizationResult = OptimizationResult::GiveUp;
719                 }
720             } else {
721                 CodeBlock* codeBlock = exec->codeBlock();
722                 ConcurrentJSLocker locker(codeBlock->m_lock);
723                 byValInfo->seen = true;
724                 byValInfo->cachedId = propertyName;
725                 if (subscript.isSymbol())
726                     byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
727                 optimizationResult = OptimizationResult::SeenOnce;
728             }
729         }
730     }
731
732     if (optimizationResult != OptimizationResult::Optimized && optimizationResult != OptimizationResult::SeenOnce) {
733         // If we take slow path more than 10 times without patching then make sure we
734         // never make that mistake again. For cases where we see non-index-intercepting
735         // objects, this gives 10 iterations worth of opportunity for us to observe
736         // that the get_by_val may be polymorphic. We count up slowPathCount even if
737         // the result is GiveUp.
738         if (++byValInfo->slowPathCount >= 10)
739             optimizationResult = OptimizationResult::GiveUp;
740     }
741
742     return optimizationResult;
743 }
744
745 void JIT_OPERATION operationDirectPutByValOptimize(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
746 {
747     VM& vm = exec->vm();
748     NativeCallFrameTracer tracer(&vm, exec);
749
750     JSValue baseValue = JSValue::decode(encodedBaseValue);
751     JSValue subscript = JSValue::decode(encodedSubscript);
752     JSValue value = JSValue::decode(encodedValue);
753     RELEASE_ASSERT(baseValue.isObject());
754     JSObject* object = asObject(baseValue);
755     if (tryDirectPutByValOptimize(exec, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) {
756         // Don't ever try to optimize.
757         byValInfo->tookSlowPath = true;
758         ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
759     }
760
761     directPutByVal(exec, object, subscript, value, byValInfo);
762 }
763
764 void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
765 {
766     VM& vm = exec->vm();
767     NativeCallFrameTracer tracer(&vm, exec);
768     
769     JSValue baseValue = JSValue::decode(encodedBaseValue);
770     JSValue subscript = JSValue::decode(encodedSubscript);
771     JSValue value = JSValue::decode(encodedValue);
772
773     putByVal(exec, baseValue, subscript, value, byValInfo);
774 }
775
776
777 void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
778 {
779     VM& vm = exec->vm();
780     NativeCallFrameTracer tracer(&vm, exec);
781     
782     JSValue baseValue = JSValue::decode(encodedBaseValue);
783     JSValue subscript = JSValue::decode(encodedSubscript);
784     JSValue value = JSValue::decode(encodedValue);
785     RELEASE_ASSERT(baseValue.isObject());
786     directPutByVal(exec, asObject(baseValue), subscript, value, byValInfo);
787 }
788
789 EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
790 {
791     VM* vm = &exec->vm();
792     auto scope = DECLARE_THROW_SCOPE(*vm);
793
794     execCallee->setCodeBlock(0);
795     
796     if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
797         return JSValue::encode(JSValue());
798
799     JSValue result = eval(execCallee);
800     RETURN_IF_EXCEPTION(scope, encodedJSValue());
801     
802     return JSValue::encode(result);
803 }
804
805 static SlowPathReturnType handleHostCall(ExecState* execCallee, JSValue callee, CallLinkInfo* callLinkInfo)
806 {
807     ExecState* exec = execCallee->callerFrame();
808     VM* vm = &exec->vm();
809     auto scope = DECLARE_THROW_SCOPE(*vm);
810
811     execCallee->setCodeBlock(0);
812
813     if (callLinkInfo->specializationKind() == CodeForCall) {
814         CallData callData;
815         CallType callType = getCallData(callee, callData);
816     
817         ASSERT(callType != CallType::JS);
818     
819         if (callType == CallType::Host) {
820             NativeCallFrameTracer tracer(vm, execCallee);
821             execCallee->setCallee(asObject(callee));
822             vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
823             if (UNLIKELY(scope.exception())) {
824                 return encodeResult(
825                     vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
826                     reinterpret_cast<void*>(KeepTheFrame));
827             }
828
829             return encodeResult(
830                 bitwise_cast<void*>(getHostCallReturnValue),
831                 reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
832         }
833     
834         ASSERT(callType == CallType::None);
835         throwException(exec, scope, createNotAFunctionError(exec, callee));
836         return encodeResult(
837             vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
838             reinterpret_cast<void*>(KeepTheFrame));
839     }
840
841     ASSERT(callLinkInfo->specializationKind() == CodeForConstruct);
842     
843     ConstructData constructData;
844     ConstructType constructType = getConstructData(callee, constructData);
845     
846     ASSERT(constructType != ConstructType::JS);
847     
848     if (constructType == ConstructType::Host) {
849         NativeCallFrameTracer tracer(vm, execCallee);
850         execCallee->setCallee(asObject(callee));
851         vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
852         if (UNLIKELY(scope.exception())) {
853             return encodeResult(
854                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
855                 reinterpret_cast<void*>(KeepTheFrame));
856         }
857
858         return encodeResult(bitwise_cast<void*>(getHostCallReturnValue), reinterpret_cast<void*>(KeepTheFrame));
859     }
860     
861     ASSERT(constructType == ConstructType::None);
862     throwException(exec, scope, createNotAConstructorError(exec, callee));
863     return encodeResult(
864         vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
865         reinterpret_cast<void*>(KeepTheFrame));
866 }
867
868 SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
869 {
870     ExecState* exec = execCallee->callerFrame();
871     VM* vm = &exec->vm();
872     auto throwScope = DECLARE_THROW_SCOPE(*vm);
873
874     CodeSpecializationKind kind = callLinkInfo->specializationKind();
875     NativeCallFrameTracer tracer(vm, exec);
876     
877     RELEASE_ASSERT(!callLinkInfo->isDirect());
878     
879     JSValue calleeAsValue = execCallee->calleeAsValue();
880     JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
881     if (!calleeAsFunctionCell) {
882         // FIXME: We should cache these kinds of calls. They can be common and currently they are
883         // expensive.
884         // https://bugs.webkit.org/show_bug.cgi?id=144458
885         throwScope.release();
886         return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
887     }
888
889     JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
890     JSScope* scope = callee->scopeUnchecked();
891     ExecutableBase* executable = callee->executable();
892
893     MacroAssemblerCodePtr codePtr;
894     CodeBlock* codeBlock = 0;
895     if (executable->isHostFunction()) {
896         codePtr = executable->entrypointFor(kind, MustCheckArity);
897     } else {
898         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
899
900         if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
901             throwException(exec, throwScope, createNotAConstructorError(exec, callee));
902             return encodeResult(
903                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
904                 reinterpret_cast<void*>(KeepTheFrame));
905         }
906
907         CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
908         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, *codeBlockSlot);
909         ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
910         if (error) {
911             throwException(exec, throwScope, error);
912             return encodeResult(
913                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
914                 reinterpret_cast<void*>(KeepTheFrame));
915         }
916         codeBlock = *codeBlockSlot;
917         ArityCheckMode arity;
918         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->isVarargs())
919             arity = MustCheckArity;
920         else
921             arity = ArityCheckNotRequired;
922         codePtr = functionExecutable->entrypointFor(kind, arity);
923     }
924     if (!callLinkInfo->seenOnce())
925         callLinkInfo->setSeen();
926     else
927         linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
928     
929     return encodeResult(codePtr.executableAddress(), reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
930 }
931
932 void JIT_OPERATION operationLinkDirectCall(ExecState* exec, CallLinkInfo* callLinkInfo, JSFunction* callee)
933 {
934     VM* vm = &exec->vm();
935     auto throwScope = DECLARE_THROW_SCOPE(*vm);
936
937     CodeSpecializationKind kind = callLinkInfo->specializationKind();
938     NativeCallFrameTracer tracer(vm, exec);
939     
940     RELEASE_ASSERT(callLinkInfo->isDirect());
941     
942     // This would happen if the executable died during GC but the CodeBlock did not die. That should
943     // not happen because the CodeBlock should have a weak reference to any executable it uses for
944     // this purpose.
945     RELEASE_ASSERT(callLinkInfo->executable());
946     
947     // Having a CodeBlock indicates that this is linked. We shouldn't be taking this path if it's
948     // linked.
949     RELEASE_ASSERT(!callLinkInfo->codeBlock());
950     
951     // We just don't support this yet.
952     RELEASE_ASSERT(!callLinkInfo->isVarargs());
953     
954     ExecutableBase* executable = callLinkInfo->executable();
955     RELEASE_ASSERT(callee->executable() == callLinkInfo->executable());
956
957     JSScope* scope = callee->scopeUnchecked();
958
959     MacroAssemblerCodePtr codePtr;
960     CodeBlock* codeBlock = nullptr;
961     if (executable->isHostFunction())
962         codePtr = executable->entrypointFor(kind, MustCheckArity);
963     else {
964         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
965
966         RELEASE_ASSERT(isCall(kind) || functionExecutable->constructAbility() != ConstructAbility::CannotConstruct);
967         
968         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, codeBlock);
969         ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
970         if (error) {
971             throwException(exec, throwScope, error);
972             return;
973         }
974         ArityCheckMode arity;
975         unsigned argumentStackSlots = callLinkInfo->maxNumArguments();
976         if (argumentStackSlots < static_cast<size_t>(codeBlock->numParameters()))
977             arity = MustCheckArity;
978         else
979             arity = ArityCheckNotRequired;
980         codePtr = functionExecutable->entrypointFor(kind, arity);
981     }
982     
983     linkDirectFor(exec, *callLinkInfo, codeBlock, codePtr);
984 }
985
986 inline SlowPathReturnType virtualForWithFunction(
987     ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*& calleeAsFunctionCell)
988 {
989     ExecState* exec = execCallee->callerFrame();
990     VM* vm = &exec->vm();
991     auto throwScope = DECLARE_THROW_SCOPE(*vm);
992
993     CodeSpecializationKind kind = callLinkInfo->specializationKind();
994     NativeCallFrameTracer tracer(vm, exec);
995
996     JSValue calleeAsValue = execCallee->calleeAsValue();
997     calleeAsFunctionCell = getJSFunction(calleeAsValue);
998     if (UNLIKELY(!calleeAsFunctionCell))
999         return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
1000     
1001     JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
1002     JSScope* scope = function->scopeUnchecked();
1003     ExecutableBase* executable = function->executable();
1004     if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
1005         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1006
1007         if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) {
1008             throwException(exec, throwScope, createNotAConstructorError(exec, function));
1009             return encodeResult(
1010                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
1011                 reinterpret_cast<void*>(KeepTheFrame));
1012         }
1013
1014         CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
1015         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, function, scope, kind, *codeBlockSlot);
1016         if (error) {
1017             throwException(exec, throwScope, error);
1018             return encodeResult(
1019                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
1020                 reinterpret_cast<void*>(KeepTheFrame));
1021         }
1022     }
1023     return encodeResult(executable->entrypointFor(
1024         kind, MustCheckArity).executableAddress(),
1025         reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
1026 }
1027
1028 SlowPathReturnType JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
1029 {
1030     ASSERT(callLinkInfo->specializationKind() == CodeForCall);
1031     JSCell* calleeAsFunctionCell;
1032     SlowPathReturnType result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
1033
1034     linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
1035     
1036     return result;
1037 }
1038
1039 SlowPathReturnType JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
1040 {
1041     JSCell* calleeAsFunctionCellIgnored;
1042     return virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCellIgnored);
1043 }
1044
1045 size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1046 {
1047     VM* vm = &exec->vm();
1048     NativeCallFrameTracer tracer(vm, exec);
1049     
1050     return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1051 }
1052
1053 size_t JIT_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1054 {
1055     VM* vm = &exec->vm();
1056     NativeCallFrameTracer tracer(vm, exec);
1057
1058     return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1059 }
1060
1061 size_t JIT_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1062 {
1063     VM* vm = &exec->vm();
1064     NativeCallFrameTracer tracer(vm, exec);
1065
1066     return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1067 }
1068
1069 size_t JIT_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1070 {
1071     VM* vm = &exec->vm();
1072     NativeCallFrameTracer tracer(vm, exec);
1073
1074     return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1075 }
1076
1077 size_t JIT_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1078 {
1079     VM* vm = &exec->vm();
1080     NativeCallFrameTracer tracer(vm, exec);
1081
1082     return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1083 }
1084
1085 #if USE(JSVALUE64)
1086 EncodedJSValue JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
1087 #else
1088 size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
1089 #endif
1090 {
1091     VM* vm = &exec->vm();
1092     NativeCallFrameTracer tracer(vm, exec);
1093
1094     bool result = asString(left)->equal(exec, asString(right));
1095 #if USE(JSVALUE64)
1096     return JSValue::encode(jsBoolean(result));
1097 #else
1098     return result;
1099 #endif
1100 }
1101
1102 EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
1103 {
1104     VM* vm = &exec->vm();
1105     NativeCallFrameTracer tracer(vm, exec);
1106     return JSValue::encode(constructArrayNegativeIndexed(exec, profile, values, size));
1107 }
1108
1109 EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
1110 {
1111     VM* vm = &exec->vm();
1112     NativeCallFrameTracer tracer(vm, exec);
1113     return JSValue::encode(constructArray(exec, profile, values, size));
1114 }
1115
1116 EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState* exec, ArrayAllocationProfile* profile, EncodedJSValue size)
1117 {
1118     VM* vm = &exec->vm();
1119     NativeCallFrameTracer tracer(vm, exec);
1120     JSValue sizeValue = JSValue::decode(size);
1121     return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
1122 }
1123
1124 }
1125
1126 template<typename FunctionType>
1127 static EncodedJSValue operationNewFunctionCommon(ExecState* exec, JSScope* scope, JSCell* functionExecutable, bool isInvalidated)
1128 {
1129     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
1130     VM& vm = exec->vm();
1131     NativeCallFrameTracer tracer(&vm, exec);
1132     if (isInvalidated)
1133         return JSValue::encode(FunctionType::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
1134     return JSValue::encode(FunctionType::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
1135 }
1136
1137 extern "C" {
1138
1139 EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1140 {
1141     return operationNewFunctionCommon<JSFunction>(exec, scope, functionExecutable, false);
1142 }
1143
1144 EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1145 {
1146     return operationNewFunctionCommon<JSFunction>(exec, scope, functionExecutable, true);
1147 }
1148
1149 EncodedJSValue JIT_OPERATION operationNewGeneratorFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1150 {
1151     return operationNewFunctionCommon<JSGeneratorFunction>(exec, scope, functionExecutable, false);
1152 }
1153
1154 EncodedJSValue JIT_OPERATION operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1155 {
1156     return operationNewFunctionCommon<JSGeneratorFunction>(exec, scope, functionExecutable, true);
1157 }
1158
1159 EncodedJSValue JIT_OPERATION operationNewAsyncFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1160 {
1161     return operationNewFunctionCommon<JSAsyncFunction>(exec, scope, functionExecutable, false);
1162 }
1163
1164 EncodedJSValue JIT_OPERATION operationNewAsyncFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
1165 {
1166     return operationNewFunctionCommon<JSAsyncFunction>(exec, scope, functionExecutable, true);
1167 }
1168
1169 void JIT_OPERATION operationSetFunctionName(ExecState* exec, JSCell* funcCell, EncodedJSValue encodedName)
1170 {
1171     VM* vm = &exec->vm();
1172     NativeCallFrameTracer tracer(vm, exec);
1173
1174     JSFunction* func = jsCast<JSFunction*>(funcCell);
1175     JSValue name = JSValue::decode(encodedName);
1176     func->setFunctionName(exec, name);
1177 }
1178
1179 JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
1180 {
1181     VM* vm = &exec->vm();
1182     NativeCallFrameTracer tracer(vm, exec);
1183
1184     return constructEmptyObject(exec, structure);
1185 }
1186
1187 EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
1188 {
1189     SuperSamplerScope superSamplerScope(false);
1190     VM& vm = exec->vm();
1191     NativeCallFrameTracer tracer(&vm, exec);
1192     auto scope = DECLARE_THROW_SCOPE(vm);
1193
1194     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
1195     if (!regexp->isValid()) {
1196         throwException(exec, scope, createSyntaxError(exec, regexp->errorMessage()));
1197         return JSValue::encode(jsUndefined());
1198     }
1199
1200     return JSValue::encode(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp));
1201 }
1202
1203 // The only reason for returning an UnusedPtr (instead of void) is so that we can reuse the
1204 // existing DFG slow path generator machinery when creating the slow path for CheckWatchdogTimer
1205 // in the DFG. If a DFG slow path generator that supports a void return type is added in the
1206 // future, we can switch to using that then.
1207 UnusedPtr JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
1208 {
1209     VM& vm = exec->vm();
1210     NativeCallFrameTracer tracer(&vm, exec);
1211     auto scope = DECLARE_THROW_SCOPE(vm);
1212
1213     if (UNLIKELY(vm.shouldTriggerTermination(exec)))
1214         throwException(exec, scope, createTerminatedExecutionException(&vm));
1215
1216     return nullptr;
1217 }
1218
1219 void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookType)
1220 {
1221     VM& vm = exec->vm();
1222     NativeCallFrameTracer tracer(&vm, exec);
1223
1224     vm.interpreter->debug(exec, static_cast<DebugHookType>(debugHookType));
1225 }
1226
1227 #if ENABLE(DFG_JIT)
1228 static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
1229 {
1230     codeBlock->updateAllPredictions();
1231     codeBlock->optimizeAfterWarmUp();
1232 }
1233
1234 SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
1235 {
1236     VM& vm = exec->vm();
1237     NativeCallFrameTracer tracer(&vm, exec);
1238
1239     // Defer GC for a while so that it doesn't run between when we enter into this
1240     // slow path and when we figure out the state of our code block. This prevents
1241     // a number of awkward reentrancy scenarios, including:
1242     //
1243     // - The optimized version of our code block being jettisoned by GC right after
1244     //   we concluded that we wanted to use it, but have not planted it into the JS
1245     //   stack yet.
1246     //
1247     // - An optimized version of our code block being installed just as we decided
1248     //   that it wasn't ready yet.
1249     //
1250     // Note that jettisoning won't happen if we already initiated OSR, because in
1251     // that case we would have already planted the optimized code block into the JS
1252     // stack.
1253     DeferGCForAWhile deferGC(vm.heap);
1254     
1255     CodeBlock* codeBlock = exec->codeBlock();
1256     if (codeBlock->jitType() != JITCode::BaselineJIT) {
1257         dataLog("Unexpected code block in Baseline->DFG tier-up: ", *codeBlock, "\n");
1258         RELEASE_ASSERT_NOT_REACHED();
1259     }
1260     
1261     if (bytecodeIndex) {
1262         // If we're attempting to OSR from a loop, assume that this should be
1263         // separately optimized.
1264         codeBlock->m_shouldAlwaysBeInlined = false;
1265     }
1266
1267     if (Options::verboseOSR()) {
1268         dataLog(
1269             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
1270             ", executeCounter = ", codeBlock->jitExecuteCounter(),
1271             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
1272             ", exitCounter = ");
1273         if (codeBlock->hasOptimizedReplacement())
1274             dataLog(codeBlock->replacement()->osrExitCounter());
1275         else
1276             dataLog("N/A");
1277         dataLog("\n");
1278     }
1279
1280     if (!codeBlock->checkIfOptimizationThresholdReached()) {
1281         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("counter = ", codeBlock->jitExecuteCounter()));
1282         codeBlock->updateAllPredictions();
1283         if (Options::verboseOSR())
1284             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
1285         return encodeResult(0, 0);
1286     }
1287     
1288     Debugger* debugger = codeBlock->globalObject()->debugger();
1289     if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
1290         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("debugger is stepping or has requests"));
1291         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1292         return encodeResult(0, 0);
1293     }
1294
1295     if (codeBlock->m_shouldAlwaysBeInlined) {
1296         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should always be inlined"));
1297         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1298         if (Options::verboseOSR())
1299             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
1300         return encodeResult(0, 0);
1301     }
1302
1303     // We cannot be in the process of asynchronous compilation and also have an optimized
1304     // replacement.
1305     DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull();
1306     ASSERT(
1307         !worklist
1308         || !(worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
1309         && codeBlock->hasOptimizedReplacement()));
1310
1311     DFG::Worklist::State worklistState;
1312     if (worklist) {
1313         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
1314         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
1315         // what the result was so that we don't plow ahead and attempt OSR or immediate
1316         // reoptimization. This will have already also set the appropriate JIT execution
1317         // count threshold depending on what happened, so if the compilation was anything
1318         // but successful we just want to return early. See the case for worklistState ==
1319         // DFG::Worklist::Compiled, below.
1320         
1321         // Note that we could have alternatively just called Worklist::compilationState()
1322         // here, and if it returned Compiled, we could have then called
1323         // completeAndScheduleOSR() below. But that would have meant that it could take
1324         // longer for code blocks to be completed: they would only complete when *their*
1325         // execution count trigger fired; but that could take a while since the firing is
1326         // racy. It could also mean that code blocks that never run again after being
1327         // compiled would sit on the worklist until next GC. That's fine, but it's
1328         // probably a waste of memory. Our goal here is to complete code blocks as soon as
1329         // possible in order to minimize the chances of us executing baseline code after
1330         // optimized code is already available.
1331         worklistState = worklist->completeAllReadyPlansForVM(
1332             vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
1333     } else
1334         worklistState = DFG::Worklist::NotKnown;
1335
1336     if (worklistState == DFG::Worklist::Compiling) {
1337         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiling"));
1338         // We cannot be in the process of asynchronous compilation and also have an optimized
1339         // replacement.
1340         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1341         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
1342         return encodeResult(0, 0);
1343     }
1344
1345     if (worklistState == DFG::Worklist::Compiled) {
1346         // If we don't have an optimized replacement but we did just get compiled, then
1347         // the compilation failed or was invalidated, in which case the execution count
1348         // thresholds have already been set appropriately by
1349         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1350         // nothing left to do.
1351         if (!codeBlock->hasOptimizedReplacement()) {
1352             CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiled and failed"));
1353             codeBlock->updateAllPredictions();
1354             if (Options::verboseOSR())
1355                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1356             return encodeResult(0, 0);
1357         }
1358     } else if (codeBlock->hasOptimizedReplacement()) {
1359         if (Options::verboseOSR())
1360             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1361         // If we have an optimized replacement, then it must be the case that we entered
1362         // cti_optimize from a loop. That's because if there's an optimized replacement,
1363         // then all calls to this function will be relinked to the replacement and so
1364         // the prologue OSR will never fire.
1365         
1366         // This is an interesting threshold check. Consider that a function OSR exits
1367         // in the middle of a loop, while having a relatively low exit count. The exit
1368         // will reset the execution counter to some target threshold, meaning that this
1369         // code won't be reached until that loop heats up for >=1000 executions. But then
1370         // we do a second check here, to see if we should either reoptimize, or just
1371         // attempt OSR entry. Hence it might even be correct for
1372         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1373         // additional checking anyway, to reduce the amount of recompilation thrashing.
1374         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1375             CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize from loop now"));
1376             if (Options::verboseOSR()) {
1377                 dataLog(
1378                     "Triggering reoptimization of ", *codeBlock,
1379                     "(", *codeBlock->replacement(), ") (in loop).\n");
1380             }
1381             codeBlock->replacement()->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
1382             return encodeResult(0, 0);
1383         }
1384     } else {
1385         if (!codeBlock->shouldOptimizeNow()) {
1386             CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("insufficient profiling"));
1387             if (Options::verboseOSR()) {
1388                 dataLog(
1389                     "Delaying optimization for ", *codeBlock,
1390                     " because of insufficient profiling.\n");
1391             }
1392             return encodeResult(0, 0);
1393         }
1394
1395         if (Options::verboseOSR())
1396             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1397
1398         unsigned numVarsWithValues;
1399         if (bytecodeIndex)
1400             numVarsWithValues = codeBlock->m_numCalleeLocals;
1401         else
1402             numVarsWithValues = 0;
1403         Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
1404         int localsUsedForCalleeSaves = static_cast<int>(CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters());
1405         for (size_t i = 0; i < mustHandleValues.size(); ++i) {
1406             int operand = mustHandleValues.operandForIndex(i);
1407             if (operandIsLocal(operand) && VirtualRegister(operand).toLocal() < localsUsedForCalleeSaves)
1408                 continue;
1409             mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
1410         }
1411
1412         CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
1413         CompilationResult result = DFG::compile(
1414             vm, replacementCodeBlock, nullptr, DFG::DFGMode, bytecodeIndex,
1415             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
1416         
1417         if (result != CompilationSuccessful) {
1418             CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compilation failed"));
1419             return encodeResult(0, 0);
1420         }
1421     }
1422     
1423     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1424     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1425     
1426     if (auto osrEntryPreparation = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
1427         void* dataBuffer = osrEntryPreparation.value();
1428         CODEBLOCK_LOG_EVENT(optimizedCodeBlock, "osrEntry", ("at bc#", bytecodeIndex));
1429         if (Options::verboseOSR()) {
1430             dataLog(
1431                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
1432         }
1433
1434         codeBlock->optimizeSoon();
1435         codeBlock->unlinkedCodeBlock()->setDidOptimize(TrueTriState);
1436         return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer);
1437     }
1438
1439     if (Options::verboseOSR()) {
1440         dataLog(
1441             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1442             " succeeded, OSR failed, after a delay of ",
1443             codeBlock->optimizationDelayCounter(), ".\n");
1444     }
1445
1446     // Count the OSR failure as a speculation failure. If this happens a lot, then
1447     // reoptimize.
1448     optimizedCodeBlock->countOSRExit();
1449
1450     // We are a lot more conservative about triggering reoptimization after OSR failure than
1451     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1452     // already, then we really would like to reoptimize immediately. But this case covers
1453     // something else: there weren't many (or any) speculation failures before, but we just
1454     // failed to enter the speculative code because some variable had the wrong value or
1455     // because the OSR code decided for any spurious reason that it did not want to OSR
1456     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1457     // reoptimization trigger.
1458     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1459         CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize now"));
1460         if (Options::verboseOSR()) {
1461             dataLog(
1462                 "Triggering reoptimization of ", *codeBlock, " -> ",
1463                 *codeBlock->replacement(), " (after OSR fail).\n");
1464         }
1465         optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
1466         return encodeResult(0, 0);
1467     }
1468
1469     // OSR failed this time, but it might succeed next time! Let the code run a bit
1470     // longer and then try again.
1471     codeBlock->optimizeAfterWarmUp();
1472     
1473     CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("OSR failed"));
1474     return encodeResult(0, 0);
1475 }
1476 #endif
1477
1478 void JIT_OPERATION operationPutByIndex(ExecState* exec, EncodedJSValue encodedArrayValue, int32_t index, EncodedJSValue encodedValue)
1479 {
1480     VM& vm = exec->vm();
1481     NativeCallFrameTracer tracer(&vm, exec);
1482
1483     JSValue arrayValue = JSValue::decode(encodedArrayValue);
1484     ASSERT(isJSArray(arrayValue));
1485     asArray(arrayValue)->putDirectIndex(exec, index, JSValue::decode(encodedValue));
1486 }
1487
1488 enum class AccessorType {
1489     Getter,
1490     Setter
1491 };
1492
1493 static void putAccessorByVal(ExecState* exec, JSObject* base, JSValue subscript, int32_t attribute, JSObject* accessor, AccessorType accessorType)
1494 {
1495     VM& vm = exec->vm();
1496     auto scope = DECLARE_THROW_SCOPE(vm);
1497     auto propertyKey = subscript.toPropertyKey(exec);
1498     RETURN_IF_EXCEPTION(scope, void());
1499
1500     if (accessorType == AccessorType::Getter)
1501         base->putGetter(exec, propertyKey, accessor, attribute);
1502     else
1503         base->putSetter(exec, propertyKey, accessor, attribute);
1504 }
1505
1506 void JIT_OPERATION operationPutGetterById(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* getter)
1507 {
1508     VM& vm = exec->vm();
1509     NativeCallFrameTracer tracer(&vm, exec);
1510
1511     ASSERT(object && object->isObject());
1512     JSObject* baseObj = object->getObject();
1513
1514     ASSERT(getter->isObject());
1515     baseObj->putGetter(exec, uid, getter, options);
1516 }
1517
1518 void JIT_OPERATION operationPutSetterById(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* setter)
1519 {
1520     VM& vm = exec->vm();
1521     NativeCallFrameTracer tracer(&vm, exec);
1522
1523     ASSERT(object && object->isObject());
1524     JSObject* baseObj = object->getObject();
1525
1526     ASSERT(setter->isObject());
1527     baseObj->putSetter(exec, uid, setter, options);
1528 }
1529
1530 void JIT_OPERATION operationPutGetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* getter)
1531 {
1532     VM& vm = exec->vm();
1533     NativeCallFrameTracer tracer(&vm, exec);
1534
1535     putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(getter), AccessorType::Getter);
1536 }
1537
1538 void JIT_OPERATION operationPutSetterByVal(ExecState* exec, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* setter)
1539 {
1540     VM& vm = exec->vm();
1541     NativeCallFrameTracer tracer(&vm, exec);
1542
1543     putAccessorByVal(exec, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(setter), AccessorType::Setter);
1544 }
1545
1546 #if USE(JSVALUE64)
1547 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t attribute, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
1548 {
1549     VM& vm = exec->vm();
1550     NativeCallFrameTracer tracer(&vm, exec);
1551
1552     ASSERT(object && object->isObject());
1553     JSObject* baseObj = asObject(object);
1554
1555     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1556
1557     JSValue getter = JSValue::decode(encodedGetterValue);
1558     JSValue setter = JSValue::decode(encodedSetterValue);
1559     ASSERT(getter.isObject() || getter.isUndefined());
1560     ASSERT(setter.isObject() || setter.isUndefined());
1561     ASSERT(getter.isObject() || setter.isObject());
1562
1563     if (!getter.isUndefined())
1564         accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
1565     if (!setter.isUndefined())
1566         accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
1567     baseObj->putDirectAccessor(exec, uid, accessor, attribute);
1568 }
1569
1570 #else
1571 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, UniquedStringImpl* uid, int32_t attribute, JSCell* getter, JSCell* setter)
1572 {
1573     VM& vm = exec->vm();
1574     NativeCallFrameTracer tracer(&vm, exec);
1575
1576     ASSERT(object && object->isObject());
1577     JSObject* baseObj = asObject(object);
1578
1579     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1580
1581     ASSERT(!getter || getter->isObject());
1582     ASSERT(!setter || setter->isObject());
1583     ASSERT(getter || setter);
1584
1585     if (getter)
1586         accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
1587     if (setter)
1588         accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
1589     baseObj->putDirectAccessor(exec, uid, accessor, attribute);
1590 }
1591 #endif
1592
1593 void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
1594 {
1595     VM& vm = exec->vm();
1596     NativeCallFrameTracer tracer(&vm, exec);
1597
1598     JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1599     exec->uncheckedR(scopeReg) = scope->next();
1600 }
1601
1602 int32_t JIT_OPERATION operationInstanceOfCustom(ExecState* exec, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance)
1603 {
1604     VM& vm = exec->vm();
1605     NativeCallFrameTracer tracer(&vm, exec);
1606
1607     JSValue value = JSValue::decode(encodedValue);
1608     JSValue hasInstanceValue = JSValue::decode(encodedHasInstance);
1609
1610     ASSERT(hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction() || !constructor->structure()->typeInfo().implementsDefaultHasInstance());
1611
1612     if (constructor->hasInstance(exec, value, hasInstanceValue))
1613         return 1;
1614     return 0;
1615 }
1616
1617 }
1618
1619 static bool canAccessArgumentIndexQuickly(JSObject& object, uint32_t index)
1620 {
1621     switch (object.structure()->typeInfo().type()) {
1622     case DirectArgumentsType: {
1623         DirectArguments* directArguments = jsCast<DirectArguments*>(&object);
1624         if (directArguments->isMappedArgumentInDFG(index))
1625             return true;
1626         break;
1627     }
1628     case ScopedArgumentsType: {
1629         ScopedArguments* scopedArguments = jsCast<ScopedArguments*>(&object);
1630         if (scopedArguments->isMappedArgumentInDFG(index))
1631             return true;
1632         break;
1633     }
1634     default:
1635         break;
1636     }
1637     return false;
1638 }
1639
1640 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
1641 {
1642     VM& vm = exec->vm();
1643     auto scope = DECLARE_THROW_SCOPE(vm);
1644
1645     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1646         Structure& structure = *baseValue.asCell()->structure(vm);
1647         if (JSCell::canUseFastGetOwnProperty(structure)) {
1648             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1649                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get())) {
1650                     ASSERT(exec->bytecodeOffset());
1651                     if (byValInfo->stubInfo && byValInfo->cachedId.impl() != existingAtomicString)
1652                         byValInfo->tookSlowPath = true;
1653                     return result;
1654                 }
1655             }
1656         }
1657     }
1658
1659     if (subscript.isUInt32()) {
1660         ASSERT(exec->bytecodeOffset());
1661         byValInfo->tookSlowPath = true;
1662
1663         uint32_t i = subscript.asUInt32();
1664         if (isJSString(baseValue)) {
1665             if (asString(baseValue)->canGetIndex(i)) {
1666                 ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(operationGetByValString));
1667                 return asString(baseValue)->getIndex(exec, i);
1668             }
1669             byValInfo->arrayProfile->setOutOfBounds();
1670         } else if (baseValue.isObject()) {
1671             JSObject* object = asObject(baseValue);
1672             if (object->canGetIndexQuickly(i))
1673                 return object->getIndexQuickly(i);
1674
1675             if (!canAccessArgumentIndexQuickly(*object, i)) {
1676                 // FIXME: This will make us think that in-bounds typed array accesses are actually
1677                 // out-of-bounds.
1678                 // https://bugs.webkit.org/show_bug.cgi?id=149886
1679                 byValInfo->arrayProfile->setOutOfBounds();
1680             }
1681         }
1682
1683         return baseValue.get(exec, i);
1684     }
1685
1686     baseValue.requireObjectCoercible(exec);
1687     RETURN_IF_EXCEPTION(scope, JSValue());
1688     auto property = subscript.toPropertyKey(exec);
1689     RETURN_IF_EXCEPTION(scope, JSValue());
1690
1691     ASSERT(exec->bytecodeOffset());
1692     if (byValInfo->stubInfo && (!isStringOrSymbol(subscript) || byValInfo->cachedId != property))
1693         byValInfo->tookSlowPath = true;
1694
1695     return baseValue.get(exec, property);
1696 }
1697
1698 static OptimizationResult tryGetByValOptimize(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
1699 {
1700     // See if it's worth optimizing this at all.
1701     OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
1702
1703     VM& vm = exec->vm();
1704
1705     if (baseValue.isObject() && subscript.isInt32()) {
1706         JSObject* object = asObject(baseValue);
1707
1708         ASSERT(exec->bytecodeOffset());
1709         ASSERT(!byValInfo->stubRoutine);
1710
1711         if (hasOptimizableIndexing(object->structure(vm))) {
1712             // Attempt to optimize.
1713             Structure* structure = object->structure(vm);
1714             JITArrayMode arrayMode = jitArrayModeForStructure(structure);
1715             if (arrayMode != byValInfo->arrayMode) {
1716                 // If we reached this case, we got an interesting array mode we did not expect when we compiled.
1717                 // Let's update the profile to do better next time.
1718                 CodeBlock* codeBlock = exec->codeBlock();
1719                 ConcurrentJSLocker locker(codeBlock->m_lock);
1720                 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
1721
1722                 JIT::compileGetByVal(&vm, exec->codeBlock(), byValInfo, returnAddress, arrayMode);
1723                 optimizationResult = OptimizationResult::Optimized;
1724             }
1725         }
1726
1727         // If we failed to patch and we have some object that intercepts indexed get, then don't even wait until 10 times.
1728         if (optimizationResult != OptimizationResult::Optimized && object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
1729             optimizationResult = OptimizationResult::GiveUp;
1730     }
1731
1732     if (baseValue.isObject() && isStringOrSymbol(subscript)) {
1733         const Identifier propertyName = subscript.toPropertyKey(exec);
1734         if (subscript.isSymbol() || !parseIndex(propertyName)) {
1735             ASSERT(exec->bytecodeOffset());
1736             ASSERT(!byValInfo->stubRoutine);
1737             if (byValInfo->seen) {
1738                 if (byValInfo->cachedId == propertyName) {
1739                     JIT::compileGetByValWithCachedId(&vm, exec->codeBlock(), byValInfo, returnAddress, propertyName);
1740                     optimizationResult = OptimizationResult::Optimized;
1741                 } else {
1742                     // Seem like a generic property access site.
1743                     optimizationResult = OptimizationResult::GiveUp;
1744                 }
1745             } else {
1746                 CodeBlock* codeBlock = exec->codeBlock();
1747                 ConcurrentJSLocker locker(codeBlock->m_lock);
1748                 byValInfo->seen = true;
1749                 byValInfo->cachedId = propertyName;
1750                 if (subscript.isSymbol())
1751                     byValInfo->cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
1752                 optimizationResult = OptimizationResult::SeenOnce;
1753             }
1754         }
1755     }
1756
1757     if (optimizationResult != OptimizationResult::Optimized && optimizationResult != OptimizationResult::SeenOnce) {
1758         // If we take slow path more than 10 times without patching then make sure we
1759         // never make that mistake again. For cases where we see non-index-intercepting
1760         // objects, this gives 10 iterations worth of opportunity for us to observe
1761         // that the get_by_val may be polymorphic. We count up slowPathCount even if
1762         // the result is GiveUp.
1763         if (++byValInfo->slowPathCount >= 10)
1764             optimizationResult = OptimizationResult::GiveUp;
1765     }
1766
1767     return optimizationResult;
1768 }
1769
1770 extern "C" {
1771
1772 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
1773 {
1774     VM& vm = exec->vm();
1775     NativeCallFrameTracer tracer(&vm, exec);
1776     JSValue baseValue = JSValue::decode(encodedBase);
1777     JSValue subscript = JSValue::decode(encodedSubscript);
1778
1779     JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1780     return JSValue::encode(result);
1781 }
1782
1783 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
1784 {
1785     VM& vm = exec->vm();
1786     NativeCallFrameTracer tracer(&vm, exec);
1787
1788     JSValue baseValue = JSValue::decode(encodedBase);
1789     JSValue subscript = JSValue::decode(encodedSubscript);
1790     ReturnAddressPtr returnAddress = ReturnAddressPtr(OUR_RETURN_ADDRESS);
1791     if (tryGetByValOptimize(exec, baseValue, subscript, byValInfo, returnAddress) == OptimizationResult::GiveUp) {
1792         // Don't ever try to optimize.
1793         byValInfo->tookSlowPath = true;
1794         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(operationGetByValGeneric));
1795     }
1796
1797     return JSValue::encode(getByVal(exec, baseValue, subscript, byValInfo, returnAddress));
1798 }
1799
1800 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
1801 {
1802     VM& vm = exec->vm();
1803     NativeCallFrameTracer tracer(&vm, exec);
1804     JSValue baseValue = JSValue::decode(encodedBase);
1805     JSValue subscript = JSValue::decode(encodedSubscript);
1806     
1807     ASSERT(baseValue.isObject());
1808     ASSERT(subscript.isUInt32());
1809
1810     JSObject* object = asObject(baseValue);
1811     bool didOptimize = false;
1812
1813     ASSERT(exec->bytecodeOffset());
1814     ASSERT(!byValInfo->stubRoutine);
1815     
1816     if (hasOptimizableIndexing(object->structure(vm))) {
1817         // Attempt to optimize.
1818         JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1819         if (arrayMode != byValInfo->arrayMode) {
1820             JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1821             didOptimize = true;
1822         }
1823     }
1824     
1825     if (!didOptimize) {
1826         // If we take slow path more than 10 times without patching then make sure we
1827         // never make that mistake again. Or, if we failed to patch and we have some object
1828         // that intercepts indexed get, then don't even wait until 10 times. For cases
1829         // where we see non-index-intercepting objects, this gives 10 iterations worth of
1830         // opportunity for us to observe that the get_by_val may be polymorphic.
1831         if (++byValInfo->slowPathCount >= 10
1832             || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1833             // Don't ever try to optimize.
1834             ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
1835         }
1836     }
1837
1838     uint32_t index = subscript.asUInt32();
1839     if (object->canGetIndexQuickly(index))
1840         return JSValue::encode(JSValue(JSValue::JSTrue));
1841
1842     if (!canAccessArgumentIndexQuickly(*object, index)) {
1843         // FIXME: This will make us think that in-bounds typed array accesses are actually
1844         // out-of-bounds.
1845         // https://bugs.webkit.org/show_bug.cgi?id=149886
1846         byValInfo->arrayProfile->setOutOfBounds();
1847     }
1848     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, index, PropertySlot::InternalMethodType::GetOwnProperty)));
1849 }
1850     
1851 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
1852 {
1853     VM& vm = exec->vm();
1854     NativeCallFrameTracer tracer(&vm, exec);
1855     JSValue baseValue = JSValue::decode(encodedBase);
1856     JSValue subscript = JSValue::decode(encodedSubscript);
1857     
1858     ASSERT(baseValue.isObject());
1859     ASSERT(subscript.isUInt32());
1860
1861     JSObject* object = asObject(baseValue);
1862     uint32_t index = subscript.asUInt32();
1863     if (object->canGetIndexQuickly(index))
1864         return JSValue::encode(JSValue(JSValue::JSTrue));
1865
1866     if (!canAccessArgumentIndexQuickly(*object, index)) {
1867         // FIXME: This will make us think that in-bounds typed array accesses are actually
1868         // out-of-bounds.
1869         // https://bugs.webkit.org/show_bug.cgi?id=149886
1870         byValInfo->arrayProfile->setOutOfBounds();
1871     }
1872     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
1873 }
1874     
1875 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
1876 {
1877     VM& vm = exec->vm();
1878     NativeCallFrameTracer tracer(&vm, exec);
1879     auto scope = DECLARE_THROW_SCOPE(vm);
1880     JSValue baseValue = JSValue::decode(encodedBase);
1881     JSValue subscript = JSValue::decode(encodedSubscript);
1882     
1883     JSValue result;
1884     if (LIKELY(subscript.isUInt32())) {
1885         uint32_t i = subscript.asUInt32();
1886         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1887             result = asString(baseValue)->getIndex(exec, i);
1888         else {
1889             result = baseValue.get(exec, i);
1890             if (!isJSString(baseValue)) {
1891                 ASSERT(exec->bytecodeOffset());
1892                 ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
1893             }
1894         }
1895     } else {
1896         baseValue.requireObjectCoercible(exec);
1897         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1898         auto property = subscript.toPropertyKey(exec);
1899         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1900         result = baseValue.get(exec, property);
1901     }
1902
1903     return JSValue::encode(result);
1904 }
1905
1906 EncodedJSValue JIT_OPERATION operationDeleteByIdJSResult(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
1907 {
1908     return JSValue::encode(jsBoolean(operationDeleteById(exec, base, uid)));
1909 }
1910
1911 size_t JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, UniquedStringImpl* uid)
1912 {
1913     VM& vm = exec->vm();
1914     NativeCallFrameTracer tracer(&vm, exec);
1915     auto scope = DECLARE_THROW_SCOPE(vm);
1916
1917     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
1918     if (!baseObj)
1919         return false;
1920     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, Identifier::fromUid(&vm, uid));
1921     if (!couldDelete && exec->codeBlock()->isStrictMode())
1922         throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
1923     return couldDelete;
1924 }
1925
1926 EncodedJSValue JIT_OPERATION operationDeleteByValJSResult(ExecState* exec, EncodedJSValue base,  EncodedJSValue key)
1927 {
1928     return JSValue::encode(jsBoolean(operationDeleteByVal(exec, base, key)));
1929 }
1930
1931 size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedKey)
1932 {
1933     VM& vm = exec->vm();
1934     NativeCallFrameTracer tracer(&vm, exec);
1935     auto scope = DECLARE_THROW_SCOPE(vm);
1936
1937     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
1938     JSValue key = JSValue::decode(encodedKey);
1939     if (!baseObj)
1940         return false;
1941
1942     bool couldDelete;
1943     uint32_t index;
1944     if (key.getUInt32(index))
1945         couldDelete = baseObj->methodTable(vm)->deletePropertyByIndex(baseObj, exec, index);
1946     else {
1947         RETURN_IF_EXCEPTION(scope, false);
1948         Identifier property = key.toPropertyKey(exec);
1949         RETURN_IF_EXCEPTION(scope, false);
1950         couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
1951     }
1952     if (!couldDelete && exec->codeBlock()->isStrictMode())
1953         throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
1954     return couldDelete;
1955 }
1956
1957 EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
1958 {
1959     VM& vm = exec->vm();
1960     NativeCallFrameTracer tracer(&vm, exec);
1961     JSValue value = JSValue::decode(encodedValue);
1962     JSValue proto = JSValue::decode(encodedProto);
1963     
1964     bool result = JSObject::defaultHasInstance(exec, value, proto);
1965     return JSValue::encode(jsBoolean(result));
1966 }
1967
1968 int32_t JIT_OPERATION operationSizeFrameForForwardArguments(ExecState* exec, EncodedJSValue, int32_t numUsedStackSlots, int32_t)
1969 {
1970     VM& vm = exec->vm();
1971     NativeCallFrameTracer tracer(&vm, exec);
1972     return sizeFrameForForwardArguments(exec, vm, numUsedStackSlots);
1973 }
1974
1975 int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
1976 {
1977     VM& vm = exec->vm();
1978     NativeCallFrameTracer tracer(&vm, exec);
1979     JSValue arguments = JSValue::decode(encodedArguments);
1980     return sizeFrameForVarargs(exec, vm, arguments, numUsedStackSlots, firstVarArgOffset);
1981 }
1982
1983 CallFrame* JIT_OPERATION operationSetupForwardArgumentsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue, int32_t, int32_t length)
1984 {
1985     VM& vm = exec->vm();
1986     NativeCallFrameTracer tracer(&vm, exec);
1987     setupForwardArgumentsFrame(exec, newCallFrame, length);
1988     return newCallFrame;
1989 }
1990
1991 CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
1992 {
1993     VM& vm = exec->vm();
1994     NativeCallFrameTracer tracer(&vm, exec);
1995     JSValue arguments = JSValue::decode(encodedArguments);
1996     setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
1997     return newCallFrame;
1998 }
1999
2000 EncodedJSValue JIT_OPERATION operationToObject(ExecState* exec, EncodedJSValue value)
2001 {
2002     VM& vm = exec->vm();
2003     NativeCallFrameTracer tracer(&vm, exec);
2004     JSObject* obj = JSValue::decode(value).toObject(exec);
2005     if (!obj)
2006         return JSValue::encode(JSValue());
2007     return JSValue::encode(obj);
2008 }
2009
2010 char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
2011 {
2012     VM& vm = exec->vm();
2013     NativeCallFrameTracer tracer(&vm, exec);
2014     JSValue key = JSValue::decode(encodedKey);
2015     CodeBlock* codeBlock = exec->codeBlock();
2016
2017     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
2018     void* result = jumpTable.ctiDefault.executableAddress();
2019
2020     if (key.isString()) {
2021         StringImpl* value = asString(key)->value(exec).impl();
2022         if (value->length() == 1)
2023             result = jumpTable.ctiForValue((*value)[0]).executableAddress();
2024     }
2025
2026     return reinterpret_cast<char*>(result);
2027 }
2028
2029 char* JIT_OPERATION operationSwitchImmWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
2030 {
2031     VM& vm = exec->vm();
2032     NativeCallFrameTracer tracer(&vm, exec);
2033     JSValue key = JSValue::decode(encodedKey);
2034     CodeBlock* codeBlock = exec->codeBlock();
2035
2036     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
2037     void* result;
2038     if (key.isInt32())
2039         result = jumpTable.ctiForValue(key.asInt32()).executableAddress();
2040     else if (key.isDouble() && key.asDouble() == static_cast<int32_t>(key.asDouble()))
2041         result = jumpTable.ctiForValue(static_cast<int32_t>(key.asDouble())).executableAddress();
2042     else
2043         result = jumpTable.ctiDefault.executableAddress();
2044     return reinterpret_cast<char*>(result);
2045 }
2046
2047 char* JIT_OPERATION operationSwitchStringWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
2048 {
2049     VM& vm = exec->vm();
2050     NativeCallFrameTracer tracer(&vm, exec);
2051     JSValue key = JSValue::decode(encodedKey);
2052     CodeBlock* codeBlock = exec->codeBlock();
2053
2054     void* result;
2055     StringJumpTable& jumpTable = codeBlock->stringSwitchJumpTable(tableIndex);
2056
2057     if (key.isString()) {
2058         StringImpl* value = asString(key)->value(exec).impl();
2059         result = jumpTable.ctiForValue(value).executableAddress();
2060     } else
2061         result = jumpTable.ctiDefault.executableAddress();
2062
2063     return reinterpret_cast<char*>(result);
2064 }
2065
2066 EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
2067 {
2068     VM& vm = exec->vm();
2069     NativeCallFrameTracer tracer(&vm, exec);
2070     auto throwScope = DECLARE_THROW_SCOPE(vm);
2071
2072     CodeBlock* codeBlock = exec->codeBlock();
2073     Instruction* pc = bytecodePC;
2074
2075     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
2076     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
2077     GetPutInfo getPutInfo(pc[4].u.operand);
2078
2079     // ModuleVar is always converted to ClosureVar for get_from_scope.
2080     ASSERT(getPutInfo.resolveType() != ModuleVar);
2081
2082     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2083         if (!found) {
2084             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2085                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2086             return jsUndefined();
2087         }
2088
2089         JSValue result = JSValue();
2090         if (scope->isGlobalLexicalEnvironment()) {
2091             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2092             result = slot.getValue(exec, ident);
2093             if (result == jsTDZValue()) {
2094                 throwException(exec, throwScope, createTDZError(exec));
2095                 return jsUndefined();
2096             }
2097         }
2098
2099         CommonSlowPaths::tryCacheGetFromScopeGlobal(exec, vm, pc, scope, slot, ident);
2100
2101         if (!result)
2102             return slot.getValue(exec, ident);
2103         return result;
2104     }));
2105 }
2106
2107 void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
2108 {
2109     VM& vm = exec->vm();
2110     NativeCallFrameTracer tracer(&vm, exec);
2111     auto throwScope = DECLARE_THROW_SCOPE(vm);
2112
2113     Instruction* pc = bytecodePC;
2114
2115     CodeBlock* codeBlock = exec->codeBlock();
2116     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
2117     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
2118     JSValue value = exec->r(pc[3].u.operand).jsValue();
2119     GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
2120
2121     // ModuleVar does not keep the scope register value alive in DFG.
2122     ASSERT(getPutInfo.resolveType() != ModuleVar);
2123
2124     if (getPutInfo.resolveType() == LocalClosureVar) {
2125         JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
2126         environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value);
2127         if (WatchpointSet* set = pc[5].u.watchpointSet)
2128             set->touch(vm, "Executed op_put_scope<LocalClosureVar>");
2129         return;
2130     }
2131
2132     bool hasProperty = scope->hasProperty(exec, ident);
2133     if (hasProperty
2134         && scope->isGlobalLexicalEnvironment()
2135         && !isInitialization(getPutInfo.initializationMode())) {
2136         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2137         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2138         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2139         if (slot.getValue(exec, ident) == jsTDZValue()) {
2140             throwException(exec, throwScope, createTDZError(exec));
2141             return;
2142         }
2143     }
2144
2145     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2146         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2147         return;
2148     }
2149
2150     PutPropertySlot slot(scope, codeBlock->isStrictMode(), PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2151     scope->methodTable()->put(scope, exec, ident, value, slot);
2152     
2153     RETURN_IF_EXCEPTION(throwScope, void());
2154
2155     CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, getPutInfo, slot, ident);
2156 }
2157
2158 void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
2159 {
2160     VM* vm = &exec->vm();
2161     NativeCallFrameTracer tracer(vm, exec);
2162     auto scope = DECLARE_THROW_SCOPE(*vm);
2163
2164     JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
2165     throwException(exec, scope, exceptionValue);
2166
2167     // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForCatch
2168     genericUnwind(vm, exec);
2169 }
2170
2171 char* JIT_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
2172 {
2173     VM& vm = exec->vm();
2174     NativeCallFrameTracer tracer(&vm, exec);
2175
2176     ASSERT(!object->structure()->outOfLineCapacity());
2177     Butterfly* result = object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
2178     object->nukeStructureAndSetButterfly(vm, object->structureID(), result);
2179     return reinterpret_cast<char*>(result);
2180 }
2181
2182 char* JIT_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
2183 {
2184     VM& vm = exec->vm();
2185     NativeCallFrameTracer tracer(&vm, exec);
2186
2187     Butterfly* result = object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
2188     object->nukeStructureAndSetButterfly(vm, object->structureID(), result);
2189     return reinterpret_cast<char*>(result);
2190 }
2191
2192 void JIT_OPERATION operationOSRWriteBarrier(ExecState* exec, JSCell* cell)
2193 {
2194     VM* vm = &exec->vm();
2195     NativeCallFrameTracer tracer(vm, exec);
2196     vm->heap.writeBarrier(cell);
2197 }
2198
2199 void JIT_OPERATION operationWriteBarrierSlowPath(ExecState* exec, JSCell* cell)
2200 {
2201     VM* vm = &exec->vm();
2202     NativeCallFrameTracer tracer(vm, exec);
2203     vm->heap.writeBarrierSlowPath(cell);
2204 }
2205
2206 void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
2207 {
2208     NativeCallFrameTracer tracer(vm, exec);
2209     genericUnwind(vm, exec);
2210     ASSERT(vm->targetMachinePCForThrow);
2211 }
2212
2213 void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
2214 {
2215     vm->topCallFrame = exec->callerFrame();
2216     genericUnwind(vm, exec, UnwindFromCallerFrame);
2217     ASSERT(vm->targetMachinePCForThrow);
2218 }
2219
2220 void JIT_OPERATION operationVMHandleException(ExecState* exec)
2221 {
2222     VM* vm = &exec->vm();
2223     NativeCallFrameTracer tracer(vm, exec);
2224     genericUnwind(vm, exec);
2225 }
2226
2227 // This function "should" just take the ExecState*, but doing so would make it more difficult
2228 // to call from exception check sites. So, unlike all of our other functions, we allow
2229 // ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
2230 // particularly safe here since this is never called on the critical path - it's only for
2231 // testing.
2232 void JIT_OPERATION operationExceptionFuzz(ExecState* exec)
2233 {
2234     VM* vm = &exec->vm();
2235     NativeCallFrameTracer tracer(vm, exec);
2236     auto scope = DECLARE_THROW_SCOPE(*vm);
2237     UNUSED_PARAM(scope);
2238 #if COMPILER(GCC_OR_CLANG)
2239     void* returnPC = __builtin_return_address(0);
2240     doExceptionFuzzing(exec, scope, "JITOperations", returnPC);
2241 #endif // COMPILER(GCC_OR_CLANG)
2242 }
2243
2244 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
2245 {
2246     VM& vm = exec->vm();
2247     NativeCallFrameTracer tracer(&vm, exec);
2248     JSValue baseValue = JSValue::decode(encodedBaseValue);
2249     if (baseValue.isUndefinedOrNull())
2250         return JSValue::encode(jsBoolean(false));
2251
2252     JSObject* base = baseValue.toObject(exec);
2253     if (!base)
2254         return JSValue::encode(JSValue());
2255     return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
2256 }
2257
2258 EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
2259 {
2260     VM& vm = exec->vm();
2261     NativeCallFrameTracer tracer(&vm, exec);
2262     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
2263     return JSValue::encode(jsBoolean(object->hasPropertyGeneric(exec, subscript, PropertySlot::InternalMethodType::GetOwnProperty)));
2264 }
2265     
2266 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)
2267 {
2268     VM& vm = exec->vm();
2269     NativeCallFrameTracer tracer(&vm, exec);
2270
2271     JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
2272
2273     return propertyNameEnumerator(exec, base);
2274 }
2275
2276 EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
2277 {
2278     VM& vm = exec->vm();
2279     NativeCallFrameTracer tracer(&vm, exec);
2280     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
2281     JSString* propertyName = enumerator->propertyNameAtIndex(index);
2282     return JSValue::encode(propertyName ? propertyName : jsNull());
2283 }
2284
2285 JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
2286 {
2287     VM& vm = exec->vm();
2288     NativeCallFrameTracer tracer(&vm, exec);
2289     return jsString(exec, Identifier::from(exec, index).string());
2290 }
2291
2292 ALWAYS_INLINE static EncodedJSValue unprofiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2293 {
2294     VM* vm = &exec->vm();
2295     NativeCallFrameTracer tracer(vm, exec);
2296     
2297     JSValue op1 = JSValue::decode(encodedOp1);
2298     JSValue op2 = JSValue::decode(encodedOp2);
2299     
2300     return JSValue::encode(jsAdd(exec, op1, op2));
2301 }
2302
2303 ALWAYS_INLINE static EncodedJSValue profiledAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile)
2304 {
2305     VM* vm = &exec->vm();
2306     NativeCallFrameTracer tracer(vm, exec);
2307     
2308     JSValue op1 = JSValue::decode(encodedOp1);
2309     JSValue op2 = JSValue::decode(encodedOp2);
2310
2311     arithProfile.observeLHSAndRHS(op1, op2);
2312     JSValue result = jsAdd(exec, op1, op2);
2313     arithProfile.observeResult(result);
2314
2315     return JSValue::encode(result);
2316 }
2317
2318 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2319 {
2320     return unprofiledAdd(exec, encodedOp1, encodedOp2);
2321 }
2322
2323 EncodedJSValue JIT_OPERATION operationValueAddProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
2324 {
2325     ASSERT(arithProfile);
2326     return profiledAdd(exec, encodedOp1, encodedOp2, *arithProfile);
2327 }
2328
2329 EncodedJSValue JIT_OPERATION operationValueAddProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC)
2330 {
2331     VM* vm = &exec->vm();
2332     NativeCallFrameTracer tracer(vm, exec);
2333     
2334     JSValue op1 = JSValue::decode(encodedOp1);
2335     JSValue op2 = JSValue::decode(encodedOp2);
2336
2337     ArithProfile* arithProfile = addIC->arithProfile();
2338     ASSERT(arithProfile);
2339     arithProfile->observeLHSAndRHS(op1, op2);
2340     auto nonOptimizeVariant = operationValueAddProfiledNoOptimize;
2341     addIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2342
2343 #if ENABLE(MATH_IC_STATS)
2344     exec->codeBlock()->dumpMathICStats();
2345 #endif
2346     
2347     JSValue result = jsAdd(exec, op1, op2);
2348     arithProfile->observeResult(result);
2349
2350     return JSValue::encode(result);
2351 }
2352
2353 EncodedJSValue JIT_OPERATION operationValueAddProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC)
2354 {
2355     VM* vm = &exec->vm();
2356     NativeCallFrameTracer tracer(vm, exec);
2357
2358     ArithProfile* arithProfile = addIC->arithProfile();
2359     ASSERT(arithProfile);
2360     return profiledAdd(exec, encodedOp1, encodedOp2, *arithProfile);
2361 }
2362
2363 EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC)
2364 {
2365     VM* vm = &exec->vm();
2366     NativeCallFrameTracer tracer(vm, exec);
2367
2368     JSValue op1 = JSValue::decode(encodedOp1);
2369     JSValue op2 = JSValue::decode(encodedOp2);
2370
2371     auto nonOptimizeVariant = operationValueAddNoOptimize;
2372     if (ArithProfile* arithProfile = addIC->arithProfile())
2373         arithProfile->observeLHSAndRHS(op1, op2);
2374     addIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2375
2376 #if ENABLE(MATH_IC_STATS)
2377     exec->codeBlock()->dumpMathICStats();
2378 #endif
2379
2380     return JSValue::encode(jsAdd(exec, op1, op2));
2381 }
2382
2383 EncodedJSValue JIT_OPERATION operationValueAddNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*)
2384 {
2385     VM* vm = &exec->vm();
2386     NativeCallFrameTracer tracer(vm, exec);
2387     
2388     JSValue op1 = JSValue::decode(encodedOp1);
2389     JSValue op2 = JSValue::decode(encodedOp2);
2390     
2391     JSValue result = jsAdd(exec, op1, op2);
2392
2393     return JSValue::encode(result);
2394 }
2395
2396 ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2397 {
2398     auto scope = DECLARE_THROW_SCOPE(vm);
2399     JSValue op1 = JSValue::decode(encodedOp1);
2400     JSValue op2 = JSValue::decode(encodedOp2);
2401
2402     double a = op1.toNumber(exec);
2403     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2404     double b = op2.toNumber(exec);
2405     return JSValue::encode(jsNumber(a * b));
2406 }
2407
2408 ALWAYS_INLINE static EncodedJSValue profiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
2409 {
2410     auto scope = DECLARE_THROW_SCOPE(vm);
2411     JSValue op1 = JSValue::decode(encodedOp1);
2412     JSValue op2 = JSValue::decode(encodedOp2);
2413
2414     if (shouldObserveLHSAndRHSTypes)
2415         arithProfile.observeLHSAndRHS(op1, op2);
2416
2417     double a = op1.toNumber(exec);
2418     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2419     double b = op2.toNumber(exec);
2420     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2421     
2422     JSValue result = jsNumber(a * b);
2423     arithProfile.observeResult(result);
2424     return JSValue::encode(result);
2425 }
2426
2427 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2428 {
2429     VM* vm = &exec->vm();
2430     NativeCallFrameTracer tracer(vm, exec);
2431
2432     return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
2433 }
2434
2435 EncodedJSValue JIT_OPERATION operationValueMulNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*)
2436 {
2437     VM* vm = &exec->vm();
2438     NativeCallFrameTracer tracer(vm, exec);
2439
2440     return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
2441 }
2442
2443 EncodedJSValue JIT_OPERATION operationValueMulOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
2444 {
2445     VM* vm = &exec->vm();
2446     NativeCallFrameTracer tracer(vm, exec);
2447
2448     auto nonOptimizeVariant = operationValueMulNoOptimize;
2449     if (ArithProfile* arithProfile = mulIC->arithProfile())
2450         arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
2451     mulIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2452
2453 #if ENABLE(MATH_IC_STATS)
2454     exec->codeBlock()->dumpMathICStats();
2455 #endif
2456
2457     return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
2458 }
2459
2460 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
2461 {
2462     VM* vm = &exec->vm();
2463     NativeCallFrameTracer tracer(vm, exec);
2464
2465     ASSERT(arithProfile);
2466     return profiledMul(*vm, exec, encodedOp1, encodedOp2, *arithProfile);
2467 }
2468
2469 EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
2470 {
2471     VM* vm = &exec->vm();
2472     NativeCallFrameTracer tracer(vm, exec);
2473
2474     ArithProfile* arithProfile = mulIC->arithProfile();
2475     ASSERT(arithProfile);
2476     arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
2477     auto nonOptimizeVariant = operationValueMulProfiledNoOptimize;
2478     mulIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2479
2480 #if ENABLE(MATH_IC_STATS)
2481     exec->codeBlock()->dumpMathICStats();
2482 #endif
2483
2484     return profiledMul(*vm, exec, encodedOp1, encodedOp2, *arithProfile, false);
2485 }
2486
2487 EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
2488 {
2489     VM* vm = &exec->vm();
2490     NativeCallFrameTracer tracer(vm, exec);
2491
2492     ArithProfile* arithProfile = mulIC->arithProfile();
2493     ASSERT(arithProfile);
2494     return profiledMul(*vm, exec, encodedOp1, encodedOp2, *arithProfile);
2495 }
2496
2497 ALWAYS_INLINE static EncodedJSValue unprofiledNegate(ExecState* exec, EncodedJSValue encodedOperand)
2498 {
2499     VM& vm = exec->vm();
2500     auto scope = DECLARE_THROW_SCOPE(vm);
2501     NativeCallFrameTracer tracer(&vm, exec);
2502     
2503     JSValue operand = JSValue::decode(encodedOperand);
2504     double number = operand.toNumber(exec);
2505     if (UNLIKELY(scope.exception()))
2506         return JSValue::encode(JSValue());
2507     return JSValue::encode(jsNumber(-number));
2508 }
2509
2510 ALWAYS_INLINE static EncodedJSValue profiledNegate(ExecState* exec, EncodedJSValue encodedOperand, ArithProfile& arithProfile)
2511 {
2512     VM& vm = exec->vm();
2513     auto scope = DECLARE_THROW_SCOPE(vm);
2514     NativeCallFrameTracer tracer(&vm, exec);
2515
2516     JSValue operand = JSValue::decode(encodedOperand);
2517     arithProfile.observeLHS(operand);
2518     double number = operand.toNumber(exec);
2519     if (UNLIKELY(scope.exception()))
2520         return JSValue::encode(JSValue());
2521
2522     JSValue result = jsNumber(-number);
2523     arithProfile.observeResult(result);
2524     return JSValue::encode(result);
2525 }
2526
2527 EncodedJSValue JIT_OPERATION operationArithNegate(ExecState* exec, EncodedJSValue operand)
2528 {
2529     return unprofiledNegate(exec, operand);
2530 }
2531
2532 EncodedJSValue JIT_OPERATION operationArithNegateProfiled(ExecState* exec, EncodedJSValue operand, ArithProfile* arithProfile)
2533 {
2534     ASSERT(arithProfile);
2535     return profiledNegate(exec, operand, *arithProfile);
2536 }
2537
2538 EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(ExecState* exec, EncodedJSValue encodedOperand, JITNegIC* negIC)
2539 {
2540     VM& vm = exec->vm();
2541     auto scope = DECLARE_THROW_SCOPE(vm);
2542     NativeCallFrameTracer tracer(&vm, exec);
2543     
2544     JSValue operand = JSValue::decode(encodedOperand);
2545
2546     ArithProfile* arithProfile = negIC->arithProfile();
2547     ASSERT(arithProfile);
2548     arithProfile->observeLHS(operand);
2549     negIC->generateOutOfLine(vm, exec->codeBlock(), operationArithNegateProfiled);
2550
2551 #if ENABLE(MATH_IC_STATS)
2552     exec->codeBlock()->dumpMathICStats();
2553 #endif
2554     
2555     double number = operand.toNumber(exec);
2556     if (UNLIKELY(scope.exception()))
2557         return JSValue::encode(JSValue());
2558     JSValue result = jsNumber(-number);
2559     arithProfile->observeResult(result);
2560     return JSValue::encode(result);
2561 }
2562
2563 EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, EncodedJSValue encodedOperand, JITNegIC* negIC)
2564 {
2565     VM& vm = exec->vm();
2566     auto scope = DECLARE_THROW_SCOPE(vm);
2567     NativeCallFrameTracer tracer(&vm, exec);
2568
2569     JSValue operand = JSValue::decode(encodedOperand);
2570
2571     if (ArithProfile* arithProfile = negIC->arithProfile())
2572         arithProfile->observeLHS(operand);
2573     negIC->generateOutOfLine(vm, exec->codeBlock(), operationArithNegate);
2574
2575 #if ENABLE(MATH_IC_STATS)
2576     exec->codeBlock()->dumpMathICStats();
2577 #endif
2578
2579     double number = operand.toNumber(exec);
2580     if (UNLIKELY(scope.exception()))
2581         return JSValue::encode(JSValue());
2582     return JSValue::encode(jsNumber(-number));
2583 }
2584
2585 ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2586 {
2587     auto scope = DECLARE_THROW_SCOPE(vm);
2588     JSValue op1 = JSValue::decode(encodedOp1);
2589     JSValue op2 = JSValue::decode(encodedOp2);
2590
2591     double a = op1.toNumber(exec);
2592     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2593     double b = op2.toNumber(exec);
2594     return JSValue::encode(jsNumber(a - b));
2595 }
2596
2597 ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
2598 {
2599     auto scope = DECLARE_THROW_SCOPE(vm);
2600     JSValue op1 = JSValue::decode(encodedOp1);
2601     JSValue op2 = JSValue::decode(encodedOp2);
2602
2603     if (shouldObserveLHSAndRHSTypes)
2604         arithProfile.observeLHSAndRHS(op1, op2);
2605
2606     double a = op1.toNumber(exec);
2607     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2608     double b = op2.toNumber(exec);
2609     RETURN_IF_EXCEPTION(scope, encodedJSValue());
2610     
2611     JSValue result = jsNumber(a - b);
2612     arithProfile.observeResult(result);
2613     return JSValue::encode(result);
2614 }
2615
2616 EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
2617 {
2618     VM* vm = &exec->vm();
2619     NativeCallFrameTracer tracer(vm, exec);
2620     return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
2621 }
2622
2623 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
2624 {
2625     ASSERT(arithProfile);
2626
2627     VM* vm = &exec->vm();
2628     NativeCallFrameTracer tracer(vm, exec);
2629
2630     return profiledSub(*vm, exec, encodedOp1, encodedOp2, *arithProfile);
2631 }
2632
2633 EncodedJSValue JIT_OPERATION operationValueSubOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC)
2634 {
2635     VM* vm = &exec->vm();
2636     NativeCallFrameTracer tracer(vm, exec);
2637
2638     auto nonOptimizeVariant = operationValueSubNoOptimize;
2639     if (ArithProfile* arithProfile = subIC->arithProfile())
2640         arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
2641     subIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2642
2643 #if ENABLE(MATH_IC_STATS)
2644     exec->codeBlock()->dumpMathICStats();
2645 #endif
2646
2647     return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
2648 }
2649
2650 EncodedJSValue JIT_OPERATION operationValueSubNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*)
2651 {
2652     VM* vm = &exec->vm();
2653     NativeCallFrameTracer tracer(vm, exec);
2654
2655     return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
2656 }
2657
2658 EncodedJSValue JIT_OPERATION operationValueSubProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC)
2659 {
2660     VM* vm = &exec->vm();
2661     NativeCallFrameTracer tracer(vm, exec);
2662
2663     ArithProfile* arithProfile = subIC->arithProfile();
2664     ASSERT(arithProfile);
2665     arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
2666     auto nonOptimizeVariant = operationValueSubProfiledNoOptimize;
2667     subIC->generateOutOfLine(*vm, exec->codeBlock(), nonOptimizeVariant);
2668
2669 #if ENABLE(MATH_IC_STATS)
2670     exec->codeBlock()->dumpMathICStats();
2671 #endif
2672
2673     return profiledSub(*vm, exec, encodedOp1, encodedOp2, *arithProfile, false);
2674 }
2675
2676 EncodedJSValue JIT_OPERATION operationValueSubProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC)
2677 {
2678     VM* vm = &exec->vm();
2679     NativeCallFrameTracer tracer(vm, exec);
2680
2681     ArithProfile* arithProfile = subIC->arithProfile();
2682     ASSERT(arithProfile);
2683     return profiledSub(*vm, exec, encodedOp1, encodedOp2, *arithProfile);
2684 }
2685
2686 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
2687 {
2688     VM& vm = exec->vm();
2689     NativeCallFrameTracer tracer(&vm, exec);
2690     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside baseline JIT"));
2691 }
2692
2693 void JIT_OPERATION operationProcessShadowChickenLog(ExecState* exec)
2694 {
2695     VM& vm = exec->vm();
2696     NativeCallFrameTracer tracer(&vm, exec);
2697     vm.shadowChicken().update(vm, exec);
2698 }
2699
2700 int32_t JIT_OPERATION operationCheckIfExceptionIsUncatchableAndNotifyProfiler(ExecState* exec)
2701 {
2702     VM& vm = exec->vm();
2703     NativeCallFrameTracer tracer(&vm, exec);
2704     auto scope = DECLARE_THROW_SCOPE(vm);
2705     RELEASE_ASSERT(!!scope.exception());
2706
2707     if (isTerminatedExecutionException(scope.exception())) {
2708         genericUnwind(&vm, exec);
2709         return 1;
2710     }
2711     return 0;
2712 }
2713
2714 } // extern "C"
2715
2716 // Note: getHostCallReturnValueWithExecState() needs to be placed before the
2717 // definition of getHostCallReturnValue() below because the Windows build
2718 // requires it.
2719 extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
2720 {
2721     if (!exec)
2722         return JSValue::encode(JSValue());
2723     return JSValue::encode(exec->vm().hostCallReturnValue);
2724 }
2725
2726 #if COMPILER(GCC_OR_CLANG) && CPU(X86_64)
2727 asm (
2728 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2729 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2730 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2731     "lea -8(%rsp), %rdi\n"
2732     "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2733 );
2734
2735 #elif COMPILER(GCC_OR_CLANG) && CPU(X86)
2736 asm (
2737 ".text" "\n" \
2738 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2739 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2740 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2741     "push %ebp\n"
2742     "mov %esp, %eax\n"
2743     "leal -4(%esp), %esp\n"
2744     "push %eax\n"
2745     "call " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2746     "leal 8(%esp), %esp\n"
2747     "pop %ebp\n"
2748     "ret\n"
2749 );
2750
2751 #elif COMPILER(GCC_OR_CLANG) && CPU(ARM_THUMB2)
2752 asm (
2753 ".text" "\n"
2754 ".align 2" "\n"
2755 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2756 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2757 ".thumb" "\n"
2758 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
2759 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2760     "sub r0, sp, #8" "\n"
2761     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2762 );
2763
2764 #elif COMPILER(GCC_OR_CLANG) && CPU(ARM_TRADITIONAL)
2765 asm (
2766 ".text" "\n"
2767 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2768 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2769 INLINE_ARM_FUNCTION(getHostCallReturnValue)
2770 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2771     "sub r0, sp, #8" "\n"
2772     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2773 );
2774
2775 #elif CPU(ARM64)
2776 asm (
2777 ".text" "\n"
2778 ".align 2" "\n"
2779 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2780 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2781 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2782      "sub x0, sp, #16" "\n"
2783      "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2784 );
2785
2786 #elif COMPILER(GCC_OR_CLANG) && CPU(MIPS)
2787
2788 #if WTF_MIPS_PIC
2789 #define LOAD_FUNCTION_TO_T9(function) \
2790         ".set noreorder" "\n" \
2791         ".cpload $25" "\n" \
2792         ".set reorder" "\n" \
2793         "la $t9, " LOCAL_REFERENCE(function) "\n"
2794 #else
2795 #define LOAD_FUNCTION_TO_T9(function) "" "\n"
2796 #endif
2797
2798 asm (
2799 ".text" "\n"
2800 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2801 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2802 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2803     LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
2804     "addi $a0, $sp, -8" "\n"
2805     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2806 );
2807
2808 #elif COMPILER(MSVC) && CPU(X86)
2809 extern "C" {
2810     __declspec(naked) EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue()
2811     {
2812         __asm lea eax, [esp - 4]
2813         __asm mov [esp + 4], eax;
2814         __asm jmp getHostCallReturnValueWithExecState
2815     }
2816 }
2817 #endif
2818
2819 } // namespace JSC
2820
2821 #endif // ENABLE(JIT)