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