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