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