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