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