Constant fold CheckTypeInfoFlags on ImplementsDefaultHasInstance
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011-2018 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 "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "BinarySwitch.h"
32 #include "DFGAbstractInterpreterInlines.h"
33 #include "DFGArrayifySlowPathGenerator.h"
34 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
35 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
36 #include "DFGCapabilities.h"
37 #include "DFGMayExit.h"
38 #include "DFGOSRExitFuzz.h"
39 #include "DFGSaneStringGetByValSlowPathGenerator.h"
40 #include "DFGSlowPathGenerator.h"
41 #include "DFGSnippetParams.h"
42 #include "DirectArguments.h"
43 #include "JITAddGenerator.h"
44 #include "JITBitAndGenerator.h"
45 #include "JITBitOrGenerator.h"
46 #include "JITBitXorGenerator.h"
47 #include "JITDivGenerator.h"
48 #include "JITLeftShiftGenerator.h"
49 #include "JITMulGenerator.h"
50 #include "JITRightShiftGenerator.h"
51 #include "JITSubGenerator.h"
52 #include "JSAsyncFunction.h"
53 #include "JSAsyncGeneratorFunction.h"
54 #include "JSCInlines.h"
55 #include "JSFixedArray.h"
56 #include "JSGeneratorFunction.h"
57 #include "JSLexicalEnvironment.h"
58 #include "JSPropertyNameEnumerator.h"
59 #include "LinkBuffer.h"
60 #include "RegExpConstructor.h"
61 #include "ScopedArguments.h"
62 #include "ScratchRegisterAllocator.h"
63 #include "SuperSampler.h"
64 #include "TypeProfilerLog.h"
65 #include "WeakMapImpl.h"
66 #include <wtf/BitVector.h>
67 #include <wtf/Box.h>
68 #include <wtf/MathExtras.h>
69
70 namespace JSC { namespace DFG {
71
72 SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
73     : m_compileOkay(true)
74     , m_jit(jit)
75     , m_graph(m_jit.graph())
76     , m_currentNode(0)
77     , m_lastGeneratedNode(LastNodeType)
78     , m_indexInBlock(0)
79     , m_generationInfo(m_jit.graph().frameRegisterCount())
80     , m_state(m_jit.graph())
81     , m_interpreter(m_jit.graph(), m_state)
82     , m_stream(&jit.jitCode()->variableEventStream)
83     , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
84 {
85 }
86
87 SpeculativeJIT::~SpeculativeJIT()
88 {
89 }
90
91 void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, RegisteredStructure structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
92 {
93     IndexingType indexingType = structure->indexingType();
94     bool hasIndexingHeader = hasIndexedProperties(indexingType);
95
96     unsigned inlineCapacity = structure->inlineCapacity();
97     unsigned outOfLineCapacity = structure->outOfLineCapacity();
98     
99     GPRTemporary scratch(this);
100     GPRTemporary scratch2(this);
101     GPRReg scratchGPR = scratch.gpr();
102     GPRReg scratch2GPR = scratch2.gpr();
103
104     ASSERT(vectorLength >= numElements);
105     vectorLength = Butterfly::optimalContiguousVectorLength(structure.get(), vectorLength);
106     
107     JITCompiler::JumpList slowCases;
108
109     size_t size = 0;
110     if (hasIndexingHeader)
111         size += vectorLength * sizeof(JSValue) + sizeof(IndexingHeader);
112     size += outOfLineCapacity * sizeof(JSValue);
113
114     m_jit.move(TrustedImmPtr(nullptr), storageGPR);
115
116     if (size) {
117         if (Allocator allocator = m_jit.vm()->jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(size, AllocatorForMode::AllocatorIfExists)) {
118             m_jit.emitAllocate(storageGPR, JITAllocator::constant(allocator), scratchGPR, scratch2GPR, slowCases);
119             
120             m_jit.addPtr(
121                 TrustedImm32(outOfLineCapacity * sizeof(JSValue) + sizeof(IndexingHeader)),
122                 storageGPR);
123             
124             if (hasIndexingHeader)
125                 m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
126         } else
127             slowCases.append(m_jit.jump());
128     }
129
130     size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
131     Allocator allocator = subspaceFor<JSFinalObject>(*m_jit.vm())->allocatorForNonVirtual(allocationSize, AllocatorForMode::AllocatorIfExists);
132     if (allocator) {
133         emitAllocateJSObject(resultGPR, JITAllocator::constant(allocator), scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
134         m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
135     } else
136         slowCases.append(m_jit.jump());
137
138     // I want a slow path that also loads out the storage pointer, and that's
139     // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
140     // of work for a very small piece of functionality. :-/
141     addSlowPathGenerator(std::make_unique<CallArrayAllocatorSlowPathGenerator>(
142         slowCases, this, operationNewRawObject, resultGPR, storageGPR,
143         structure, vectorLength));
144
145     if (numElements < vectorLength) {
146 #if USE(JSVALUE64)
147         if (hasDouble(structure->indexingType()))
148             m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
149         else
150             m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
151         for (unsigned i = numElements; i < vectorLength; ++i)
152             m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
153 #else
154         EncodedValueDescriptor value;
155         if (hasDouble(structure->indexingType()))
156             value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, PNaN));
157         else
158             value.asInt64 = JSValue::encode(JSValue());
159         for (unsigned i = numElements; i < vectorLength; ++i) {
160             m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
161             m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
162         }
163 #endif
164     }
165     
166     if (hasIndexingHeader)
167         m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
168     
169     m_jit.emitInitializeOutOfLineStorage(storageGPR, structure->outOfLineCapacity());
170     
171     m_jit.mutatorFence(*m_jit.vm());
172 }
173
174 void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis)
175 {
176     if (inlineCallFrame && !inlineCallFrame->isVarargs())
177         m_jit.move(TrustedImm32(inlineCallFrame->argumentCountIncludingThis - !includeThis), lengthGPR);
178     else {
179         VirtualRegister argumentCountRegister = m_jit.argumentCount(inlineCallFrame);
180         m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR);
181         if (!includeThis)
182             m_jit.sub32(TrustedImm32(1), lengthGPR);
183     }
184 }
185
186 void SpeculativeJIT::emitGetLength(CodeOrigin origin, GPRReg lengthGPR, bool includeThis)
187 {
188     emitGetLength(origin.inlineCallFrame, lengthGPR, includeThis);
189 }
190
191 void SpeculativeJIT::emitGetCallee(CodeOrigin origin, GPRReg calleeGPR)
192 {
193     if (origin.inlineCallFrame) {
194         if (origin.inlineCallFrame->isClosureCall) {
195             m_jit.loadPtr(
196                 JITCompiler::addressFor(origin.inlineCallFrame->calleeRecovery.virtualRegister()),
197                 calleeGPR);
198         } else {
199             m_jit.move(
200                 TrustedImmPtr::weakPointer(m_jit.graph(), origin.inlineCallFrame->calleeRecovery.constant().asCell()),
201                 calleeGPR);
202         }
203     } else
204         m_jit.loadPtr(JITCompiler::addressFor(CallFrameSlot::callee), calleeGPR);
205 }
206
207 void SpeculativeJIT::emitGetArgumentStart(CodeOrigin origin, GPRReg startGPR)
208 {
209     m_jit.addPtr(
210         TrustedImm32(
211             JITCompiler::argumentsStart(origin).offset() * static_cast<int>(sizeof(Register))),
212         GPRInfo::callFrameRegister, startGPR);
213 }
214
215 MacroAssembler::Jump SpeculativeJIT::emitOSRExitFuzzCheck()
216 {
217     if (!Options::useOSRExitFuzz()
218         || !canUseOSRExitFuzzing(m_jit.graph().baselineCodeBlockFor(m_origin.semantic))
219         || !doOSRExitFuzzing())
220         return MacroAssembler::Jump();
221     
222     MacroAssembler::Jump result;
223     
224     m_jit.pushToSave(GPRInfo::regT0);
225     m_jit.load32(&g_numberOfOSRExitFuzzChecks, GPRInfo::regT0);
226     m_jit.add32(TrustedImm32(1), GPRInfo::regT0);
227     m_jit.store32(GPRInfo::regT0, &g_numberOfOSRExitFuzzChecks);
228     unsigned atOrAfter = Options::fireOSRExitFuzzAtOrAfter();
229     unsigned at = Options::fireOSRExitFuzzAt();
230     if (at || atOrAfter) {
231         unsigned threshold;
232         MacroAssembler::RelationalCondition condition;
233         if (atOrAfter) {
234             threshold = atOrAfter;
235             condition = MacroAssembler::Below;
236         } else {
237             threshold = at;
238             condition = MacroAssembler::NotEqual;
239         }
240         MacroAssembler::Jump ok = m_jit.branch32(
241             condition, GPRInfo::regT0, MacroAssembler::TrustedImm32(threshold));
242         m_jit.popToRestore(GPRInfo::regT0);
243         result = m_jit.jump();
244         ok.link(&m_jit);
245     }
246     m_jit.popToRestore(GPRInfo::regT0);
247     
248     return result;
249 }
250
251 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
252 {
253     if (!m_compileOkay)
254         return;
255     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
256     if (fuzzJump.isSet()) {
257         JITCompiler::JumpList jumpsToFail;
258         jumpsToFail.append(fuzzJump);
259         jumpsToFail.append(jumpToFail);
260         m_jit.appendExitInfo(jumpsToFail);
261     } else
262         m_jit.appendExitInfo(jumpToFail);
263     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
264 }
265
266 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail)
267 {
268     if (!m_compileOkay)
269         return;
270     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
271     if (fuzzJump.isSet()) {
272         JITCompiler::JumpList myJumpsToFail;
273         myJumpsToFail.append(jumpsToFail);
274         myJumpsToFail.append(fuzzJump);
275         m_jit.appendExitInfo(myJumpsToFail);
276     } else
277         m_jit.appendExitInfo(jumpsToFail);
278     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
279 }
280
281 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
282 {
283     if (!m_compileOkay)
284         return OSRExitJumpPlaceholder();
285     unsigned index = m_jit.jitCode()->osrExit.size();
286     m_jit.appendExitInfo();
287     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
288     return OSRExitJumpPlaceholder(index);
289 }
290
291 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
292 {
293     return speculationCheck(kind, jsValueSource, nodeUse.node());
294 }
295
296 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
297 {
298     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
299 }
300
301 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
302 {
303     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
304 }
305
306 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
307 {
308     if (!m_compileOkay)
309         return;
310     unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
311     m_jit.appendExitInfo(jumpToFail);
312     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size(), recoveryIndex));
313 }
314
315 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
316 {
317     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
318 }
319
320 void SpeculativeJIT::emitInvalidationPoint(Node* node)
321 {
322     if (!m_compileOkay)
323         return;
324     OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
325     m_jit.jitCode()->appendOSRExit(OSRExit(
326         UncountableInvalidation, JSValueSource(), MethodOfGettingAValueProfile(),
327         this, m_stream->size()));
328     info.m_replacementSource = m_jit.watchpointLabel();
329     ASSERT(info.m_replacementSource.isSet());
330     noResult(node);
331 }
332
333 void SpeculativeJIT::unreachable(Node* node)
334 {
335     m_compileOkay = false;
336     m_jit.abortWithReason(DFGUnreachableNode, node->op());
337 }
338
339 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
340 {
341     if (!m_compileOkay)
342         return;
343     speculationCheck(kind, jsValueRegs, node, m_jit.jump());
344     m_compileOkay = false;
345     if (verboseCompilationEnabled())
346         dataLog("Bailing compilation.\n");
347 }
348
349 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
350 {
351     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
352 }
353
354 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind exitKind)
355 {
356     ASSERT(needsTypeCheck(edge, typesPassedThrough));
357     m_interpreter.filter(edge, typesPassedThrough);
358     speculationCheck(exitKind, source, edge.node(), jumpToFail);
359 }
360
361 RegisterSet SpeculativeJIT::usedRegisters()
362 {
363     RegisterSet result;
364     
365     for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
366         GPRReg gpr = GPRInfo::toRegister(i);
367         if (m_gprs.isInUse(gpr))
368             result.set(gpr);
369     }
370     for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
371         FPRReg fpr = FPRInfo::toRegister(i);
372         if (m_fprs.isInUse(fpr))
373             result.set(fpr);
374     }
375     
376     result.merge(RegisterSet::stubUnavailableRegisters());
377     
378     return result;
379 }
380
381 void SpeculativeJIT::addSlowPathGenerator(std::unique_ptr<SlowPathGenerator> slowPathGenerator)
382 {
383     m_slowPathGenerators.append(WTFMove(slowPathGenerator));
384 }
385
386 void SpeculativeJIT::addSlowPathGenerator(std::function<void()> lambda)
387 {
388     m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast<unsigned>(m_stream->size()) });
389 }
390
391 void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder& pcToCodeOriginMapBuilder)
392 {
393     for (auto& slowPathGenerator : m_slowPathGenerators) {
394         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), slowPathGenerator->origin().semantic);
395         slowPathGenerator->generate(this);
396     }
397     for (auto& slowPathLambda : m_slowPathLambdas) {
398         Node* currentNode = slowPathLambda.currentNode;
399         m_currentNode = currentNode;
400         m_outOfLineStreamIndex = slowPathLambda.streamIndex;
401         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), currentNode->origin.semantic);
402         slowPathLambda.generator();
403         m_outOfLineStreamIndex = std::nullopt;
404     }
405 }
406
407 void SpeculativeJIT::clearGenerationInfo()
408 {
409     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
410         m_generationInfo[i] = GenerationInfo();
411     m_gprs = RegisterBank<GPRInfo>();
412     m_fprs = RegisterBank<FPRInfo>();
413 }
414
415 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source)
416 {
417     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
418     Node* node = info.node();
419     DataFormat registerFormat = info.registerFormat();
420     ASSERT(registerFormat != DataFormatNone);
421     ASSERT(registerFormat != DataFormatDouble);
422         
423     SilentSpillAction spillAction;
424     SilentFillAction fillAction;
425         
426     if (!info.needsSpill())
427         spillAction = DoNothingForSpill;
428     else {
429 #if USE(JSVALUE64)
430         ASSERT(info.gpr() == source);
431         if (registerFormat == DataFormatInt32)
432             spillAction = Store32Payload;
433         else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
434             spillAction = StorePtr;
435         else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52)
436             spillAction = Store64;
437         else {
438             ASSERT(registerFormat & DataFormatJS);
439             spillAction = Store64;
440         }
441 #elif USE(JSVALUE32_64)
442         if (registerFormat & DataFormatJS) {
443             ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
444             spillAction = source == info.tagGPR() ? Store32Tag : Store32Payload;
445         } else {
446             ASSERT(info.gpr() == source);
447             spillAction = Store32Payload;
448         }
449 #endif
450     }
451         
452     if (registerFormat == DataFormatInt32) {
453         ASSERT(info.gpr() == source);
454         ASSERT(isJSInt32(info.registerFormat()));
455         if (node->hasConstant()) {
456             ASSERT(node->isInt32Constant());
457             fillAction = SetInt32Constant;
458         } else
459             fillAction = Load32Payload;
460     } else if (registerFormat == DataFormatBoolean) {
461 #if USE(JSVALUE64)
462         RELEASE_ASSERT_NOT_REACHED();
463 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
464         fillAction = DoNothingForFill;
465 #endif
466 #elif USE(JSVALUE32_64)
467         ASSERT(info.gpr() == source);
468         if (node->hasConstant()) {
469             ASSERT(node->isBooleanConstant());
470             fillAction = SetBooleanConstant;
471         } else
472             fillAction = Load32Payload;
473 #endif
474     } else if (registerFormat == DataFormatCell) {
475         ASSERT(info.gpr() == source);
476         if (node->hasConstant()) {
477             DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant());
478             node->asCell(); // To get the assertion.
479             fillAction = SetCellConstant;
480         } else {
481 #if USE(JSVALUE64)
482             fillAction = LoadPtr;
483 #else
484             fillAction = Load32Payload;
485 #endif
486         }
487     } else if (registerFormat == DataFormatStorage) {
488         ASSERT(info.gpr() == source);
489         fillAction = LoadPtr;
490     } else if (registerFormat == DataFormatInt52) {
491         if (node->hasConstant())
492             fillAction = SetInt52Constant;
493         else if (info.spillFormat() == DataFormatInt52)
494             fillAction = Load64;
495         else if (info.spillFormat() == DataFormatStrictInt52)
496             fillAction = Load64ShiftInt52Left;
497         else if (info.spillFormat() == DataFormatNone)
498             fillAction = Load64;
499         else {
500             RELEASE_ASSERT_NOT_REACHED();
501 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
502             fillAction = Load64; // Make GCC happy.
503 #endif
504         }
505     } else if (registerFormat == DataFormatStrictInt52) {
506         if (node->hasConstant())
507             fillAction = SetStrictInt52Constant;
508         else if (info.spillFormat() == DataFormatInt52)
509             fillAction = Load64ShiftInt52Right;
510         else if (info.spillFormat() == DataFormatStrictInt52)
511             fillAction = Load64;
512         else if (info.spillFormat() == DataFormatNone)
513             fillAction = Load64;
514         else {
515             RELEASE_ASSERT_NOT_REACHED();
516 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
517             fillAction = Load64; // Make GCC happy.
518 #endif
519         }
520     } else {
521         ASSERT(registerFormat & DataFormatJS);
522 #if USE(JSVALUE64)
523         ASSERT(info.gpr() == source);
524         if (node->hasConstant()) {
525             if (node->isCellConstant())
526                 fillAction = SetTrustedJSConstant;
527             else
528                 fillAction = SetJSConstant;
529         } else if (info.spillFormat() == DataFormatInt32) {
530             ASSERT(registerFormat == DataFormatJSInt32);
531             fillAction = Load32PayloadBoxInt;
532         } else
533             fillAction = Load64;
534 #else
535         ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
536         if (node->hasConstant())
537             fillAction = info.tagGPR() == source ? SetJSConstantTag : SetJSConstantPayload;
538         else if (info.payloadGPR() == source)
539             fillAction = Load32Payload;
540         else { // Fill the Tag
541             switch (info.spillFormat()) {
542             case DataFormatInt32:
543                 ASSERT(registerFormat == DataFormatJSInt32);
544                 fillAction = SetInt32Tag;
545                 break;
546             case DataFormatCell:
547                 ASSERT(registerFormat == DataFormatJSCell);
548                 fillAction = SetCellTag;
549                 break;
550             case DataFormatBoolean:
551                 ASSERT(registerFormat == DataFormatJSBoolean);
552                 fillAction = SetBooleanTag;
553                 break;
554             default:
555                 fillAction = Load32Tag;
556                 break;
557             }
558         }
559 #endif
560     }
561         
562     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
563 }
564     
565 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForFPR(VirtualRegister spillMe, FPRReg source)
566 {
567     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
568     Node* node = info.node();
569     ASSERT(info.registerFormat() == DataFormatDouble);
570
571     SilentSpillAction spillAction;
572     SilentFillAction fillAction;
573         
574     if (!info.needsSpill())
575         spillAction = DoNothingForSpill;
576     else {
577         ASSERT(!node->hasConstant());
578         ASSERT(info.spillFormat() == DataFormatNone);
579         ASSERT(info.fpr() == source);
580         spillAction = StoreDouble;
581     }
582         
583 #if USE(JSVALUE64)
584     if (node->hasConstant()) {
585         node->asNumber(); // To get the assertion.
586         fillAction = SetDoubleConstant;
587     } else {
588         ASSERT(info.spillFormat() == DataFormatNone || info.spillFormat() == DataFormatDouble);
589         fillAction = LoadDouble;
590     }
591 #elif USE(JSVALUE32_64)
592     ASSERT(info.registerFormat() == DataFormatDouble);
593     if (node->hasConstant()) {
594         node->asNumber(); // To get the assertion.
595         fillAction = SetDoubleConstant;
596     } else
597         fillAction = LoadDouble;
598 #endif
599
600     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
601 }
602     
603 void SpeculativeJIT::silentSpill(const SilentRegisterSavePlan& plan)
604 {
605     switch (plan.spillAction()) {
606     case DoNothingForSpill:
607         break;
608     case Store32Tag:
609         m_jit.store32(plan.gpr(), JITCompiler::tagFor(plan.node()->virtualRegister()));
610         break;
611     case Store32Payload:
612         m_jit.store32(plan.gpr(), JITCompiler::payloadFor(plan.node()->virtualRegister()));
613         break;
614     case StorePtr:
615         m_jit.storePtr(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
616         break;
617 #if USE(JSVALUE64)
618     case Store64:
619         m_jit.store64(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
620         break;
621 #endif
622     case StoreDouble:
623         m_jit.storeDouble(plan.fpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
624         break;
625     default:
626         RELEASE_ASSERT_NOT_REACHED();
627     }
628 }
629     
630 void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan)
631 {
632     switch (plan.fillAction()) {
633     case DoNothingForFill:
634         break;
635     case SetInt32Constant:
636         m_jit.move(Imm32(plan.node()->asInt32()), plan.gpr());
637         break;
638 #if USE(JSVALUE64)
639     case SetInt52Constant:
640         m_jit.move(Imm64(plan.node()->asAnyInt() << JSValue::int52ShiftAmount), plan.gpr());
641         break;
642     case SetStrictInt52Constant:
643         m_jit.move(Imm64(plan.node()->asAnyInt()), plan.gpr());
644         break;
645 #endif // USE(JSVALUE64)
646     case SetBooleanConstant:
647         m_jit.move(TrustedImm32(plan.node()->asBoolean()), plan.gpr());
648         break;
649     case SetCellConstant:
650         ASSERT(plan.node()->constant()->value().isCell());
651         m_jit.move(TrustedImmPtr(plan.node()->constant()), plan.gpr());
652         break;
653 #if USE(JSVALUE64)
654     case SetTrustedJSConstant:
655         m_jit.move(valueOfJSConstantAsImm64(plan.node()).asTrustedImm64(), plan.gpr());
656         break;
657     case SetJSConstant:
658         m_jit.move(valueOfJSConstantAsImm64(plan.node()), plan.gpr());
659         break;
660     case SetDoubleConstant:
661         m_jit.moveDouble(Imm64(reinterpretDoubleToInt64(plan.node()->asNumber())), plan.fpr());
662         break;
663     case Load32PayloadBoxInt:
664         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
665         m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr());
666         break;
667     case Load32PayloadConvertToInt52:
668         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
669         m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
670         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
671         break;
672     case Load32PayloadSignExtend:
673         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
674         m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
675         break;
676 #else
677     case SetJSConstantTag:
678         m_jit.move(Imm32(plan.node()->asJSValue().tag()), plan.gpr());
679         break;
680     case SetJSConstantPayload:
681         m_jit.move(Imm32(plan.node()->asJSValue().payload()), plan.gpr());
682         break;
683     case SetInt32Tag:
684         m_jit.move(TrustedImm32(JSValue::Int32Tag), plan.gpr());
685         break;
686     case SetCellTag:
687         m_jit.move(TrustedImm32(JSValue::CellTag), plan.gpr());
688         break;
689     case SetBooleanTag:
690         m_jit.move(TrustedImm32(JSValue::BooleanTag), plan.gpr());
691         break;
692     case SetDoubleConstant:
693         m_jit.loadDouble(TrustedImmPtr(m_jit.addressOfDoubleConstant(plan.node())), plan.fpr());
694         break;
695 #endif
696     case Load32Tag:
697         m_jit.load32(JITCompiler::tagFor(plan.node()->virtualRegister()), plan.gpr());
698         break;
699     case Load32Payload:
700         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
701         break;
702     case LoadPtr:
703         m_jit.loadPtr(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
704         break;
705 #if USE(JSVALUE64)
706     case Load64:
707         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
708         break;
709     case Load64ShiftInt52Right:
710         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
711         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
712         break;
713     case Load64ShiftInt52Left:
714         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
715         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
716         break;
717 #endif
718     case LoadDouble:
719         m_jit.loadDouble(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.fpr());
720         break;
721     default:
722         RELEASE_ASSERT_NOT_REACHED();
723     }
724 }
725
726 JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode)
727 {
728     JITCompiler::JumpList result;
729     
730     switch (arrayMode.type()) {
731     case Array::Int32:
732     case Array::Double:
733     case Array::Contiguous:
734     case Array::Undecided:
735     case Array::ArrayStorage: {
736         IndexingType shape = arrayMode.shapeMask();
737         switch (arrayMode.arrayClass()) {
738         case Array::OriginalArray:
739             RELEASE_ASSERT_NOT_REACHED();
740             return result;
741
742         case Array::Array:
743             m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
744             result.append(m_jit.branch32(
745                 MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape)));
746             return result;
747
748         case Array::NonArray:
749         case Array::OriginalNonArray:
750             m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
751             result.append(m_jit.branch32(
752                 MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape)));
753             return result;
754
755         case Array::PossiblyArray:
756             m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
757             result.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape)));
758             return result;
759         }
760
761         RELEASE_ASSERT_NOT_REACHED();
762         return result;
763     }
764
765     case Array::SlowPutArrayStorage: {
766         ASSERT(!arrayMode.isJSArrayWithOriginalStructure());
767
768         switch (arrayMode.arrayClass()) {
769         case Array::OriginalArray:
770             RELEASE_ASSERT_NOT_REACHED();
771             return result;
772
773         case Array::Array:
774             result.append(
775                 m_jit.branchTest32(
776                     MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
777             break;
778
779         case Array::NonArray:
780         case Array::OriginalNonArray:
781             result.append(
782                 m_jit.branchTest32(
783                     MacroAssembler::NonZero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
784             break;
785
786         case Array::PossiblyArray:
787             break;
788         }
789
790         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
791         m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
792         result.append(
793             m_jit.branch32(
794                 MacroAssembler::Above, tempGPR,
795                 TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
796         return result;
797     }
798     default:
799         CRASH();
800         break;
801     }
802     
803     return result;
804 }
805
806 void SpeculativeJIT::checkArray(Node* node)
807 {
808     ASSERT(node->arrayMode().isSpecific());
809     ASSERT(!node->arrayMode().doesConversion());
810     
811     SpeculateCellOperand base(this, node->child1());
812     GPRReg baseReg = base.gpr();
813     
814     if (node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))) {
815         noResult(m_currentNode);
816         return;
817     }
818     
819     switch (node->arrayMode().type()) {
820     case Array::AnyTypedArray:
821     case Array::String:
822         RELEASE_ASSERT_NOT_REACHED(); // Should have been a Phantom(String:)
823         return;
824     case Array::Int32:
825     case Array::Double:
826     case Array::Contiguous:
827     case Array::Undecided:
828     case Array::ArrayStorage:
829     case Array::SlowPutArrayStorage: {
830         GPRTemporary temp(this);
831         GPRReg tempGPR = temp.gpr();
832         m_jit.load8(MacroAssembler::Address(baseReg, JSCell::indexingTypeAndMiscOffset()), tempGPR);
833         speculationCheck(
834             BadIndexingType, JSValueSource::unboxedCell(baseReg), 0,
835             jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
836         
837         noResult(m_currentNode);
838         return;
839     }
840     case Array::DirectArguments:
841         speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, DirectArgumentsType);
842         noResult(m_currentNode);
843         return;
844     case Array::ScopedArguments:
845         speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, ScopedArgumentsType);
846         noResult(m_currentNode);
847         return;
848     default:
849         speculateCellTypeWithoutTypeFiltering(
850             node->child1(), baseReg,
851             typeForTypedArrayType(node->arrayMode().typedArrayType()));
852         noResult(m_currentNode);
853         return;
854     }
855 }
856
857 void SpeculativeJIT::arrayify(Node* node, GPRReg baseReg, GPRReg propertyReg)
858 {
859     ASSERT(node->arrayMode().doesConversion());
860     
861     GPRTemporary temp(this);
862     GPRTemporary structure;
863     GPRReg tempGPR = temp.gpr();
864     GPRReg structureGPR = InvalidGPRReg;
865     
866     if (node->op() != ArrayifyToStructure) {
867         GPRTemporary realStructure(this);
868         structure.adopt(realStructure);
869         structureGPR = structure.gpr();
870     }
871         
872     // We can skip all that comes next if we already have array storage.
873     MacroAssembler::JumpList slowPath;
874     
875     if (node->op() == ArrayifyToStructure) {
876         slowPath.append(m_jit.branchWeakStructure(
877             JITCompiler::NotEqual,
878             JITCompiler::Address(baseReg, JSCell::structureIDOffset()),
879             node->structure()));
880     } else {
881         m_jit.load8(
882             MacroAssembler::Address(baseReg, JSCell::indexingTypeAndMiscOffset()), tempGPR);
883         
884         slowPath.append(jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
885     }
886     
887     addSlowPathGenerator(std::make_unique<ArrayifySlowPathGenerator>(
888         slowPath, this, node, baseReg, propertyReg, tempGPR, structureGPR));
889     
890     noResult(m_currentNode);
891 }
892
893 void SpeculativeJIT::arrayify(Node* node)
894 {
895     ASSERT(node->arrayMode().isSpecific());
896     
897     SpeculateCellOperand base(this, node->child1());
898     
899     if (!node->child2()) {
900         arrayify(node, base.gpr(), InvalidGPRReg);
901         return;
902     }
903     
904     SpeculateInt32Operand property(this, node->child2());
905     
906     arrayify(node, base.gpr(), property.gpr());
907 }
908
909 GPRReg SpeculativeJIT::fillStorage(Edge edge)
910 {
911     VirtualRegister virtualRegister = edge->virtualRegister();
912     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
913     
914     switch (info.registerFormat()) {
915     case DataFormatNone: {
916         if (info.spillFormat() == DataFormatStorage) {
917             GPRReg gpr = allocate();
918             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
919             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
920             info.fillStorage(*m_stream, gpr);
921             return gpr;
922         }
923         
924         // Must be a cell; fill it as a cell and then return the pointer.
925         return fillSpeculateCell(edge);
926     }
927         
928     case DataFormatStorage: {
929         GPRReg gpr = info.gpr();
930         m_gprs.lock(gpr);
931         return gpr;
932     }
933         
934     default:
935         return fillSpeculateCell(edge);
936     }
937 }
938
939 void SpeculativeJIT::useChildren(Node* node)
940 {
941     if (node->flags() & NodeHasVarArgs) {
942         for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
943             if (!!m_jit.graph().m_varArgChildren[childIdx])
944                 use(m_jit.graph().m_varArgChildren[childIdx]);
945         }
946     } else {
947         Edge child1 = node->child1();
948         if (!child1) {
949             ASSERT(!node->child2() && !node->child3());
950             return;
951         }
952         use(child1);
953         
954         Edge child2 = node->child2();
955         if (!child2) {
956             ASSERT(!node->child3());
957             return;
958         }
959         use(child2);
960         
961         Edge child3 = node->child3();
962         if (!child3)
963             return;
964         use(child3);
965     }
966 }
967
968 void SpeculativeJIT::compileGetById(Node* node, AccessType accessType)
969 {
970     ASSERT(accessType == AccessType::Get || accessType == AccessType::GetDirect || accessType == AccessType::TryGet);
971
972     switch (node->child1().useKind()) {
973     case CellUse: {
974         SpeculateCellOperand base(this, node->child1());
975         JSValueRegsTemporary result(this, Reuse, base);
976
977         JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
978         JSValueRegs resultRegs = result.regs();
979
980         base.use();
981
982         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, accessType);
983
984         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
985         break;
986     }
987
988     case UntypedUse: {
989         JSValueOperand base(this, node->child1());
990         JSValueRegsTemporary result(this, Reuse, base);
991
992         JSValueRegs baseRegs = base.jsValueRegs();
993         JSValueRegs resultRegs = result.regs();
994
995         base.use();
996
997         JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
998
999         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, accessType);
1000
1001         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
1002         break;
1003     }
1004
1005     default:
1006         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1007         break;
1008     }
1009 }
1010
1011 void SpeculativeJIT::compileGetByIdFlush(Node* node, AccessType accessType)
1012 {
1013     switch (node->child1().useKind()) {
1014     case CellUse: {
1015         SpeculateCellOperand base(this, node->child1());
1016         JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
1017
1018         JSValueRegsFlushedCallResult result(this);
1019         JSValueRegs resultRegs = result.regs();
1020
1021         base.use();
1022
1023         flushRegisters();
1024
1025         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), DontSpill, accessType);
1026
1027         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
1028         break;
1029     }
1030
1031     case UntypedUse: {
1032         JSValueOperand base(this, node->child1());
1033         JSValueRegs baseRegs = base.jsValueRegs();
1034
1035         JSValueRegsFlushedCallResult result(this);
1036         JSValueRegs resultRegs = result.regs();
1037
1038         base.use();
1039
1040         flushRegisters();
1041
1042         JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
1043
1044         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, DontSpill, accessType);
1045
1046         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
1047         break;
1048     }
1049
1050     default:
1051         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1052         break;
1053     }
1054 }
1055
1056 void SpeculativeJIT::compileIn(Node* node)
1057 {
1058     SpeculateCellOperand base(this, node->child1());
1059     GPRReg baseGPR = base.gpr();
1060     
1061     if (JSString* string = node->child2()->dynamicCastConstant<JSString*>(*m_jit.vm())) {
1062         if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
1063             StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo(AccessType::In);
1064             
1065             GPRTemporary result(this);
1066             GPRReg resultGPR = result.gpr();
1067
1068             use(node->child2());
1069             
1070             MacroAssembler::PatchableJump jump = m_jit.patchableJump();
1071             MacroAssembler::Label done = m_jit.label();
1072             
1073             // Since this block is executed only when the result of string->tryGetValueImpl() is atomic,
1074             // we can cast it to const AtomicStringImpl* safely.
1075             auto slowPath = slowPathCall(
1076                 jump.m_jump, this, operationInOptimize,
1077                 JSValueRegs::payloadOnly(resultGPR), stubInfo, baseGPR,
1078                 static_cast<const AtomicStringImpl*>(string->tryGetValueImpl()));
1079             
1080             stubInfo->callSiteIndex = m_jit.addCallSite(node->origin.semantic);
1081             stubInfo->codeOrigin = node->origin.semantic;
1082             stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR);
1083             stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR);
1084             stubInfo->patch.thisGPR = static_cast<int8_t>(InvalidGPRReg);
1085 #if USE(JSVALUE32_64)
1086             stubInfo->patch.valueTagGPR = static_cast<int8_t>(InvalidGPRReg);
1087             stubInfo->patch.baseTagGPR = static_cast<int8_t>(InvalidGPRReg);
1088             stubInfo->patch.thisTagGPR = static_cast<int8_t>(InvalidGPRReg);
1089 #endif
1090             stubInfo->patch.usedRegisters = usedRegisters();
1091
1092             m_jit.addIn(InRecord(jump, done, slowPath.get(), stubInfo));
1093             addSlowPathGenerator(WTFMove(slowPath));
1094
1095             base.use();
1096
1097             blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1098             return;
1099         }
1100     }
1101
1102     JSValueOperand key(this, node->child2());
1103     JSValueRegs regs = key.jsValueRegs();
1104         
1105     GPRFlushedCallResult result(this);
1106     GPRReg resultGPR = result.gpr();
1107         
1108     base.use();
1109     key.use();
1110         
1111     flushRegisters();
1112     callOperation(
1113         operationGenericIn, extractResult(JSValueRegs::payloadOnly(resultGPR)),
1114         baseGPR, regs);
1115     m_jit.exceptionCheck();
1116     blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1117 }
1118
1119 void SpeculativeJIT::compileDeleteById(Node* node)
1120 {
1121     JSValueOperand value(this, node->child1());
1122     GPRFlushedCallResult result(this);
1123
1124     JSValueRegs valueRegs = value.jsValueRegs();
1125     GPRReg resultGPR = result.gpr();
1126
1127     value.use();
1128
1129     flushRegisters();
1130     callOperation(operationDeleteById, resultGPR, valueRegs, identifierUID(node->identifierNumber()));
1131     m_jit.exceptionCheck();
1132
1133     unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1134 }
1135
1136 void SpeculativeJIT::compileDeleteByVal(Node* node)
1137 {
1138     JSValueOperand base(this, node->child1());
1139     JSValueOperand key(this, node->child2());
1140     GPRFlushedCallResult result(this);
1141
1142     JSValueRegs baseRegs = base.jsValueRegs();
1143     JSValueRegs keyRegs = key.jsValueRegs();
1144     GPRReg resultGPR = result.gpr();
1145
1146     base.use();
1147     key.use();
1148
1149     flushRegisters();
1150     callOperation(operationDeleteByVal, resultGPR, baseRegs, keyRegs);
1151     m_jit.exceptionCheck();
1152
1153     unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1154 }
1155
1156 void SpeculativeJIT::compilePushWithScope(Node* node)
1157 {
1158     SpeculateCellOperand currentScope(this, node->child1());
1159     GPRReg currentScopeGPR = currentScope.gpr();
1160
1161     GPRFlushedCallResult result(this);
1162     GPRReg resultGPR = result.gpr();
1163
1164     auto objectEdge = node->child2();
1165     if (objectEdge.useKind() == ObjectUse) {
1166         SpeculateCellOperand object(this, objectEdge);
1167         GPRReg objectGPR = object.gpr();
1168         speculateObject(objectEdge, objectGPR);
1169
1170         flushRegisters();
1171         callOperation(operationPushWithScopeObject, resultGPR, currentScopeGPR, objectGPR);
1172         // No exception check here as we did not have to call toObject().
1173     } else {
1174         ASSERT(objectEdge.useKind() == UntypedUse);
1175         JSValueOperand object(this, objectEdge);
1176         JSValueRegs objectRegs = object.jsValueRegs();
1177
1178         flushRegisters();
1179         callOperation(operationPushWithScope, resultGPR, currentScopeGPR, objectRegs);
1180         m_jit.exceptionCheck();
1181     }
1182     
1183     cellResult(resultGPR, node);
1184 }
1185
1186 bool SpeculativeJIT::nonSpeculativeStrictEq(Node* node, bool invert)
1187 {
1188     unsigned branchIndexInBlock = detectPeepHoleBranch();
1189     if (branchIndexInBlock != UINT_MAX) {
1190         Node* branchNode = m_block->at(branchIndexInBlock);
1191
1192         ASSERT(node->adjustedRefCount() == 1);
1193         
1194         nonSpeculativePeepholeStrictEq(node, branchNode, invert);
1195     
1196         m_indexInBlock = branchIndexInBlock;
1197         m_currentNode = branchNode;
1198         
1199         return true;
1200     }
1201     
1202     nonSpeculativeNonPeepholeStrictEq(node, invert);
1203     
1204     return false;
1205 }
1206
1207 static const char* dataFormatString(DataFormat format)
1208 {
1209     // These values correspond to the DataFormat enum.
1210     const char* strings[] = {
1211         "[  ]",
1212         "[ i]",
1213         "[ d]",
1214         "[ c]",
1215         "Err!",
1216         "Err!",
1217         "Err!",
1218         "Err!",
1219         "[J ]",
1220         "[Ji]",
1221         "[Jd]",
1222         "[Jc]",
1223         "Err!",
1224         "Err!",
1225         "Err!",
1226         "Err!",
1227     };
1228     return strings[format];
1229 }
1230
1231 void SpeculativeJIT::dump(const char* label)
1232 {
1233     if (label)
1234         dataLogF("<%s>\n", label);
1235
1236     dataLogF("  gprs:\n");
1237     m_gprs.dump();
1238     dataLogF("  fprs:\n");
1239     m_fprs.dump();
1240     dataLogF("  VirtualRegisters:\n");
1241     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1242         GenerationInfo& info = m_generationInfo[i];
1243         if (info.alive())
1244             dataLogF("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
1245         else
1246             dataLogF("    % 3d:[__][__]", i);
1247         if (info.registerFormat() == DataFormatDouble)
1248             dataLogF(":fpr%d\n", info.fpr());
1249         else if (info.registerFormat() != DataFormatNone
1250 #if USE(JSVALUE32_64)
1251             && !(info.registerFormat() & DataFormatJS)
1252 #endif
1253             ) {
1254             ASSERT(info.gpr() != InvalidGPRReg);
1255             dataLogF(":%s\n", GPRInfo::debugName(info.gpr()));
1256         } else
1257             dataLogF("\n");
1258     }
1259     if (label)
1260         dataLogF("</%s>\n", label);
1261 }
1262
1263 GPRTemporary::GPRTemporary()
1264     : m_jit(0)
1265     , m_gpr(InvalidGPRReg)
1266 {
1267 }
1268
1269 GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
1270     : m_jit(jit)
1271     , m_gpr(InvalidGPRReg)
1272 {
1273     m_gpr = m_jit->allocate();
1274 }
1275
1276 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
1277     : m_jit(jit)
1278     , m_gpr(InvalidGPRReg)
1279 {
1280     m_gpr = m_jit->allocate(specific);
1281 }
1282
1283 #if USE(JSVALUE32_64)
1284 GPRTemporary::GPRTemporary(
1285     SpeculativeJIT* jit, ReuseTag, JSValueOperand& op1, WhichValueWord which)
1286     : m_jit(jit)
1287     , m_gpr(InvalidGPRReg)
1288 {
1289     if (!op1.isDouble() && m_jit->canReuse(op1.node()))
1290         m_gpr = m_jit->reuse(op1.gpr(which));
1291     else
1292         m_gpr = m_jit->allocate();
1293 }
1294 #else // USE(JSVALUE32_64)
1295 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& op1, WhichValueWord)
1296     : GPRTemporary(jit, Reuse, op1)
1297 {
1298 }
1299 #endif
1300
1301 JSValueRegsTemporary::JSValueRegsTemporary() { }
1302
1303 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit)
1304 #if USE(JSVALUE64)
1305     : m_gpr(jit)
1306 #else
1307     : m_payloadGPR(jit)
1308     , m_tagGPR(jit)
1309 #endif
1310 {
1311 }
1312
1313 #if USE(JSVALUE64)
1314 template<typename T>
1315 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord)
1316     : m_gpr(jit, Reuse, operand)
1317 {
1318 }
1319 #else
1320 template<typename T>
1321 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord)
1322 {
1323     if (resultWord == PayloadWord) {
1324         m_payloadGPR = GPRTemporary(jit, Reuse, operand);
1325         m_tagGPR = GPRTemporary(jit);
1326     } else {
1327         m_payloadGPR = GPRTemporary(jit);
1328         m_tagGPR = GPRTemporary(jit, Reuse, operand);
1329     }
1330 }
1331 #endif
1332
1333 #if USE(JSVALUE64)
1334 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& operand)
1335 {
1336     m_gpr = GPRTemporary(jit, Reuse, operand);
1337 }
1338 #else
1339 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& operand)
1340 {
1341     if (jit->canReuse(operand.node())) {
1342         m_payloadGPR = GPRTemporary(jit, Reuse, operand, PayloadWord);
1343         m_tagGPR = GPRTemporary(jit, Reuse, operand, TagWord);
1344     } else {
1345         m_payloadGPR = GPRTemporary(jit);
1346         m_tagGPR = GPRTemporary(jit);
1347     }
1348 }
1349 #endif
1350
1351 JSValueRegsTemporary::~JSValueRegsTemporary() { }
1352
1353 JSValueRegs JSValueRegsTemporary::regs()
1354 {
1355 #if USE(JSVALUE64)
1356     return JSValueRegs(m_gpr.gpr());
1357 #else
1358     return JSValueRegs(m_tagGPR.gpr(), m_payloadGPR.gpr());
1359 #endif
1360 }
1361
1362 void GPRTemporary::adopt(GPRTemporary& other)
1363 {
1364     ASSERT(!m_jit);
1365     ASSERT(m_gpr == InvalidGPRReg);
1366     ASSERT(other.m_jit);
1367     ASSERT(other.m_gpr != InvalidGPRReg);
1368     m_jit = other.m_jit;
1369     m_gpr = other.m_gpr;
1370     other.m_jit = 0;
1371     other.m_gpr = InvalidGPRReg;
1372 }
1373
1374 FPRTemporary::FPRTemporary(FPRTemporary&& other)
1375 {
1376     ASSERT(other.m_jit);
1377     ASSERT(other.m_fpr != InvalidFPRReg);
1378     m_jit = other.m_jit;
1379     m_fpr = other.m_fpr;
1380
1381     other.m_jit = nullptr;
1382 }
1383
1384 FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
1385     : m_jit(jit)
1386     , m_fpr(InvalidFPRReg)
1387 {
1388     m_fpr = m_jit->fprAllocate();
1389 }
1390
1391 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
1392     : m_jit(jit)
1393     , m_fpr(InvalidFPRReg)
1394 {
1395     if (m_jit->canReuse(op1.node()))
1396         m_fpr = m_jit->reuse(op1.fpr());
1397     else
1398         m_fpr = m_jit->fprAllocate();
1399 }
1400
1401 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
1402     : m_jit(jit)
1403     , m_fpr(InvalidFPRReg)
1404 {
1405     if (m_jit->canReuse(op1.node()))
1406         m_fpr = m_jit->reuse(op1.fpr());
1407     else if (m_jit->canReuse(op2.node()))
1408         m_fpr = m_jit->reuse(op2.fpr());
1409     else if (m_jit->canReuse(op1.node(), op2.node()) && op1.fpr() == op2.fpr())
1410         m_fpr = m_jit->reuse(op1.fpr());
1411     else
1412         m_fpr = m_jit->fprAllocate();
1413 }
1414
1415 #if USE(JSVALUE32_64)
1416 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
1417     : m_jit(jit)
1418     , m_fpr(InvalidFPRReg)
1419 {
1420     if (op1.isDouble() && m_jit->canReuse(op1.node()))
1421         m_fpr = m_jit->reuse(op1.fpr());
1422     else
1423         m_fpr = m_jit->fprAllocate();
1424 }
1425 #endif
1426
1427 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node* node, Node* branchNode, JITCompiler::DoubleCondition condition)
1428 {
1429     BasicBlock* taken = branchNode->branchData()->taken.block;
1430     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1431
1432     if (taken == nextBlock()) {
1433         condition = MacroAssembler::invert(condition);
1434         std::swap(taken, notTaken);
1435     }
1436
1437     SpeculateDoubleOperand op1(this, node->child1());
1438     SpeculateDoubleOperand op2(this, node->child2());
1439     
1440     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
1441     jump(notTaken);
1442 }
1443
1444 void SpeculativeJIT::compilePeepHoleObjectEquality(Node* node, Node* branchNode)
1445 {
1446     BasicBlock* taken = branchNode->branchData()->taken.block;
1447     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1448
1449     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
1450     
1451     if (taken == nextBlock()) {
1452         condition = MacroAssembler::NotEqual;
1453         BasicBlock* tmp = taken;
1454         taken = notTaken;
1455         notTaken = tmp;
1456     }
1457
1458     SpeculateCellOperand op1(this, node->child1());
1459     SpeculateCellOperand op2(this, node->child2());
1460     
1461     GPRReg op1GPR = op1.gpr();
1462     GPRReg op2GPR = op2.gpr();
1463     
1464     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1465         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1466             speculationCheck(
1467                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), m_jit.branchIfNotObject(op1GPR));
1468         }
1469         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1470             speculationCheck(
1471                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), m_jit.branchIfNotObject(op2GPR));
1472         }
1473     } else {
1474         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1475             speculationCheck(
1476                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1477                 m_jit.branchIfNotObject(op1GPR));
1478         }
1479         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1480             m_jit.branchTest8(
1481                 MacroAssembler::NonZero, 
1482                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1483                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1484
1485         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1486             speculationCheck(
1487                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1488                 m_jit.branchIfNotObject(op2GPR));
1489         }
1490         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1491             m_jit.branchTest8(
1492                 MacroAssembler::NonZero, 
1493                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1494                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1495     }
1496
1497     branchPtr(condition, op1GPR, op2GPR, taken);
1498     jump(notTaken);
1499 }
1500
1501 void SpeculativeJIT::compilePeepHoleBooleanBranch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1502 {
1503     BasicBlock* taken = branchNode->branchData()->taken.block;
1504     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1505
1506     // The branch instruction will branch to the taken block.
1507     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1508     if (taken == nextBlock()) {
1509         condition = JITCompiler::invert(condition);
1510         BasicBlock* tmp = taken;
1511         taken = notTaken;
1512         notTaken = tmp;
1513     }
1514
1515     if (node->child1()->isInt32Constant()) {
1516         int32_t imm = node->child1()->asInt32();
1517         SpeculateBooleanOperand op2(this, node->child2());
1518         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1519     } else if (node->child2()->isInt32Constant()) {
1520         SpeculateBooleanOperand op1(this, node->child1());
1521         int32_t imm = node->child2()->asInt32();
1522         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1523     } else {
1524         SpeculateBooleanOperand op1(this, node->child1());
1525         SpeculateBooleanOperand op2(this, node->child2());
1526         branch32(condition, op1.gpr(), op2.gpr(), taken);
1527     }
1528
1529     jump(notTaken);
1530 }
1531
1532 void SpeculativeJIT::compileStringSlice(Node* node)
1533 {
1534     SpeculateCellOperand string(this, node->child1());
1535     GPRTemporary startIndex(this);
1536     GPRTemporary temp(this);
1537     GPRTemporary temp2(this);
1538
1539     GPRReg stringGPR = string.gpr();
1540     GPRReg startIndexGPR = startIndex.gpr();
1541     GPRReg tempGPR = temp.gpr();
1542     GPRReg temp2GPR = temp2.gpr();
1543
1544     speculateString(node->child1(), stringGPR);
1545
1546     {
1547         m_jit.load32(JITCompiler::Address(stringGPR, JSString::offsetOfLength()), temp2GPR);
1548
1549         emitPopulateSliceIndex(node->child2(), temp2GPR, startIndexGPR);
1550         if (node->child3())
1551             emitPopulateSliceIndex(node->child3(), temp2GPR, tempGPR);
1552         else
1553             m_jit.move(temp2GPR, tempGPR);
1554     }
1555
1556     CCallHelpers::JumpList doneCases;
1557     CCallHelpers::JumpList slowCases;
1558
1559     auto nonEmptyCase = m_jit.branch32(MacroAssembler::Below, startIndexGPR, tempGPR);
1560     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), jsEmptyString(&vm())), tempGPR);
1561     doneCases.append(m_jit.jump());
1562
1563     nonEmptyCase.link(&m_jit);
1564     m_jit.sub32(startIndexGPR, tempGPR); // the size of the sliced string.
1565     slowCases.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(1)));
1566
1567     m_jit.loadPtr(MacroAssembler::Address(stringGPR, JSString::offsetOfValue()), temp2GPR);
1568     slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, temp2GPR));
1569
1570     m_jit.loadPtr(MacroAssembler::Address(temp2GPR, StringImpl::dataOffset()), tempGPR);
1571
1572     // Load the character into scratchReg
1573     m_jit.zeroExtend32ToPtr(startIndexGPR, startIndexGPR);
1574     auto is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(temp2GPR, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1575
1576     m_jit.load8(MacroAssembler::BaseIndex(tempGPR, startIndexGPR, MacroAssembler::TimesOne, 0), tempGPR);
1577     auto cont8Bit = m_jit.jump();
1578
1579     is16Bit.link(&m_jit);
1580     m_jit.load16(MacroAssembler::BaseIndex(tempGPR, startIndexGPR, MacroAssembler::TimesTwo, 0), tempGPR);
1581
1582     auto bigCharacter = m_jit.branch32(MacroAssembler::AboveOrEqual, tempGPR, TrustedImm32(0x100));
1583
1584     // 8 bit string values don't need the isASCII check.
1585     cont8Bit.link(&m_jit);
1586
1587     m_jit.lshift32(MacroAssembler::TrustedImm32(sizeof(void*) == 4 ? 2 : 3), tempGPR);
1588     m_jit.addPtr(TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), tempGPR);
1589     m_jit.loadPtr(tempGPR, tempGPR);
1590
1591     addSlowPathGenerator(
1592         slowPathCall(
1593             bigCharacter, this, operationSingleCharacterString, tempGPR, tempGPR));
1594
1595     addSlowPathGenerator(
1596         slowPathCall(
1597             slowCases, this, operationStringSubstr, tempGPR, stringGPR, startIndexGPR, tempGPR));
1598
1599     doneCases.link(&m_jit);
1600     cellResult(tempGPR, node);
1601 }
1602
1603 void SpeculativeJIT::compileToLowerCase(Node* node)
1604 {
1605     ASSERT(node->op() == ToLowerCase);
1606     SpeculateCellOperand string(this, node->child1());
1607     GPRTemporary temp(this);
1608     GPRTemporary index(this);
1609     GPRTemporary charReg(this);
1610     GPRTemporary length(this);
1611
1612     GPRReg stringGPR = string.gpr();
1613     GPRReg tempGPR = temp.gpr();
1614     GPRReg indexGPR = index.gpr();
1615     GPRReg charGPR = charReg.gpr();
1616     GPRReg lengthGPR = length.gpr();
1617
1618     speculateString(node->child1(), stringGPR);
1619
1620     CCallHelpers::JumpList slowPath;
1621
1622     m_jit.move(TrustedImmPtr(nullptr), indexGPR);
1623
1624     m_jit.loadPtr(MacroAssembler::Address(stringGPR, JSString::offsetOfValue()), tempGPR);
1625     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR));
1626
1627     slowPath.append(m_jit.branchTest32(
1628         MacroAssembler::Zero, MacroAssembler::Address(tempGPR, StringImpl::flagsOffset()),
1629         MacroAssembler::TrustedImm32(StringImpl::flagIs8Bit())));
1630     m_jit.load32(MacroAssembler::Address(tempGPR, StringImpl::lengthMemoryOffset()), lengthGPR);
1631     m_jit.loadPtr(MacroAssembler::Address(tempGPR, StringImpl::dataOffset()), tempGPR);
1632
1633     auto loopStart = m_jit.label();
1634     auto loopDone = m_jit.branch32(CCallHelpers::AboveOrEqual, indexGPR, lengthGPR);
1635     m_jit.load8(MacroAssembler::BaseIndex(tempGPR, indexGPR, MacroAssembler::TimesOne), charGPR);
1636     slowPath.append(m_jit.branchTest32(CCallHelpers::NonZero, charGPR, TrustedImm32(~0x7F)));
1637     m_jit.sub32(TrustedImm32('A'), charGPR);
1638     slowPath.append(m_jit.branch32(CCallHelpers::BelowOrEqual, charGPR, TrustedImm32('Z' - 'A')));
1639
1640     m_jit.add32(TrustedImm32(1), indexGPR);
1641     m_jit.jump().linkTo(loopStart, &m_jit);
1642     
1643     slowPath.link(&m_jit);
1644     silentSpillAllRegisters(lengthGPR);
1645     callOperation(operationToLowerCase, lengthGPR, stringGPR, indexGPR);
1646     silentFillAllRegisters();
1647     m_jit.exceptionCheck();
1648     auto done = m_jit.jump();
1649
1650     loopDone.link(&m_jit);
1651     m_jit.move(stringGPR, lengthGPR);
1652
1653     done.link(&m_jit);
1654     cellResult(lengthGPR, node);
1655 }
1656
1657 void SpeculativeJIT::compilePeepHoleInt32Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1658 {
1659     BasicBlock* taken = branchNode->branchData()->taken.block;
1660     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1661
1662     // The branch instruction will branch to the taken block.
1663     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1664     if (taken == nextBlock()) {
1665         condition = JITCompiler::invert(condition);
1666         BasicBlock* tmp = taken;
1667         taken = notTaken;
1668         notTaken = tmp;
1669     }
1670
1671     if (node->child1()->isInt32Constant()) {
1672         int32_t imm = node->child1()->asInt32();
1673         SpeculateInt32Operand op2(this, node->child2());
1674         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1675     } else if (node->child2()->isInt32Constant()) {
1676         SpeculateInt32Operand op1(this, node->child1());
1677         int32_t imm = node->child2()->asInt32();
1678         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1679     } else {
1680         SpeculateInt32Operand op1(this, node->child1());
1681         SpeculateInt32Operand op2(this, node->child2());
1682         branch32(condition, op1.gpr(), op2.gpr(), taken);
1683     }
1684
1685     jump(notTaken);
1686 }
1687
1688 // Returns true if the compare is fused with a subsequent branch.
1689 bool SpeculativeJIT::compilePeepHoleBranch(Node* node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_JITOperation_EJJ operation)
1690 {
1691     // Fused compare & branch.
1692     unsigned branchIndexInBlock = detectPeepHoleBranch();
1693     if (branchIndexInBlock != UINT_MAX) {
1694         Node* branchNode = m_block->at(branchIndexInBlock);
1695
1696         // detectPeepHoleBranch currently only permits the branch to be the very next node,
1697         // so can be no intervening nodes to also reference the compare. 
1698         ASSERT(node->adjustedRefCount() == 1);
1699
1700         if (node->isBinaryUseKind(Int32Use))
1701             compilePeepHoleInt32Branch(node, branchNode, condition);
1702 #if USE(JSVALUE64)
1703         else if (node->isBinaryUseKind(Int52RepUse))
1704             compilePeepHoleInt52Branch(node, branchNode, condition);
1705 #endif // USE(JSVALUE64)
1706         else if (node->isBinaryUseKind(StringUse) || node->isBinaryUseKind(StringIdentUse)) {
1707             // Use non-peephole comparison, for now.
1708             return false;
1709         } else if (node->isBinaryUseKind(DoubleRepUse))
1710             compilePeepHoleDoubleBranch(node, branchNode, doubleCondition);
1711         else if (node->op() == CompareEq) {
1712             if (node->isBinaryUseKind(BooleanUse))
1713                 compilePeepHoleBooleanBranch(node, branchNode, condition);
1714             else if (node->isBinaryUseKind(SymbolUse))
1715                 compilePeepHoleSymbolEquality(node, branchNode);
1716             else if (node->isBinaryUseKind(ObjectUse))
1717                 compilePeepHoleObjectEquality(node, branchNode);
1718             else if (node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse))
1719                 compilePeepHoleObjectToObjectOrOtherEquality(node->child1(), node->child2(), branchNode);
1720             else if (node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse))
1721                 compilePeepHoleObjectToObjectOrOtherEquality(node->child2(), node->child1(), branchNode);
1722             else if (!needsTypeCheck(node->child1(), SpecOther))
1723                 nonSpeculativePeepholeBranchNullOrUndefined(node->child2(), branchNode);
1724             else if (!needsTypeCheck(node->child2(), SpecOther))
1725                 nonSpeculativePeepholeBranchNullOrUndefined(node->child1(), branchNode);
1726             else {
1727                 nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1728                 return true;
1729             }
1730         } else {
1731             nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1732             return true;
1733         }
1734
1735         use(node->child1());
1736         use(node->child2());
1737         m_indexInBlock = branchIndexInBlock;
1738         m_currentNode = branchNode;
1739         return true;
1740     }
1741     return false;
1742 }
1743
1744 void SpeculativeJIT::noticeOSRBirth(Node* node)
1745 {
1746     if (!node->hasVirtualRegister())
1747         return;
1748     
1749     VirtualRegister virtualRegister = node->virtualRegister();
1750     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1751     
1752     info.noticeOSRBirth(*m_stream, node, virtualRegister);
1753 }
1754
1755 void SpeculativeJIT::compileMovHint(Node* node)
1756 {
1757     ASSERT(node->containsMovHint() && node->op() != ZombieHint);
1758     
1759     Node* child = node->child1().node();
1760     noticeOSRBirth(child);
1761     
1762     m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->unlinkedLocal()));
1763 }
1764
1765 void SpeculativeJIT::bail(AbortReason reason)
1766 {
1767     if (verboseCompilationEnabled())
1768         dataLog("Bailing compilation.\n");
1769     m_compileOkay = true;
1770     m_jit.abortWithReason(reason, m_lastGeneratedNode);
1771     clearGenerationInfo();
1772 }
1773
1774 void SpeculativeJIT::compileCurrentBlock()
1775 {
1776     ASSERT(m_compileOkay);
1777     
1778     if (!m_block)
1779         return;
1780     
1781     ASSERT(m_block->isReachable);
1782     
1783     m_jit.blockHeads()[m_block->index] = m_jit.label();
1784
1785     if (!m_block->intersectionOfCFAHasVisited) {
1786         // Don't generate code for basic blocks that are unreachable according to CFA.
1787         // But to be sure that nobody has generated a jump to this block, drop in a
1788         // breakpoint here.
1789         m_jit.abortWithReason(DFGUnreachableBasicBlock);
1790         return;
1791     }
1792
1793     if (m_block->isCatchEntrypoint) {
1794         m_jit.addPtr(CCallHelpers::TrustedImm32(-(m_jit.graph().frameRegisterCount() * sizeof(Register))), GPRInfo::callFrameRegister,  CCallHelpers::stackPointerRegister);
1795         if (Options::zeroStackFrame())
1796             m_jit.clearStackFrame(GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister, GPRInfo::regT0, m_jit.graph().frameRegisterCount() * sizeof(Register));
1797         m_jit.emitSaveCalleeSaves();
1798         m_jit.emitMaterializeTagCheckRegisters();
1799         m_jit.emitPutToCallFrameHeader(m_jit.codeBlock(), CallFrameSlot::codeBlock);
1800     }
1801
1802     m_stream->appendAndLog(VariableEvent::reset());
1803     
1804     m_jit.jitAssertHasValidCallFrame();
1805     m_jit.jitAssertTagsInPlace();
1806     m_jit.jitAssertArgumentCountSane();
1807
1808     m_state.reset();
1809     m_state.beginBasicBlock(m_block);
1810     
1811     for (size_t i = m_block->variablesAtHead.size(); i--;) {
1812         int operand = m_block->variablesAtHead.operandForIndex(i);
1813         Node* node = m_block->variablesAtHead[i];
1814         if (!node)
1815             continue; // No need to record dead SetLocal's.
1816         
1817         VariableAccessData* variable = node->variableAccessData();
1818         DataFormat format;
1819         if (!node->refCount())
1820             continue; // No need to record dead SetLocal's.
1821         format = dataFormatFor(variable->flushFormat());
1822         m_stream->appendAndLog(
1823             VariableEvent::setLocal(
1824                 VirtualRegister(operand),
1825                 variable->machineLocal(),
1826                 format));
1827     }
1828
1829     m_origin = NodeOrigin();
1830     
1831     for (m_indexInBlock = 0; m_indexInBlock < m_block->size(); ++m_indexInBlock) {
1832         m_currentNode = m_block->at(m_indexInBlock);
1833         
1834         // We may have hit a contradiction that the CFA was aware of but that the JIT
1835         // didn't cause directly.
1836         if (!m_state.isValid()) {
1837             bail(DFGBailedAtTopOfBlock);
1838             return;
1839         }
1840
1841         m_interpreter.startExecuting();
1842         m_interpreter.executeKnownEdgeTypes(m_currentNode);
1843         m_jit.setForNode(m_currentNode);
1844         m_origin = m_currentNode->origin;
1845         if (validationEnabled())
1846             m_origin.exitOK &= mayExit(m_jit.graph(), m_currentNode) == Exits;
1847         m_lastGeneratedNode = m_currentNode->op();
1848         
1849         ASSERT(m_currentNode->shouldGenerate());
1850         
1851         if (verboseCompilationEnabled()) {
1852             dataLogF(
1853                 "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
1854                 (int)m_currentNode->index(),
1855                 m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
1856             dataLog("\n");
1857         }
1858
1859         if (Options::validateDFGExceptionHandling() && (mayExit(m_jit.graph(), m_currentNode) != DoesNotExit || m_currentNode->isTerminal()))
1860             m_jit.jitReleaseAssertNoException(*m_jit.vm());
1861
1862         m_jit.pcToCodeOriginMapBuilder().appendItem(m_jit.labelIgnoringWatchpoints(), m_origin.semantic);
1863
1864         compile(m_currentNode);
1865         
1866         if (belongsInMinifiedGraph(m_currentNode->op()))
1867             m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1868         
1869 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1870         m_jit.clearRegisterAllocationOffsets();
1871 #endif
1872         
1873         if (!m_compileOkay) {
1874             bail(DFGBailedAtEndOfNode);
1875             return;
1876         }
1877         
1878         // Make sure that the abstract state is rematerialized for the next node.
1879         m_interpreter.executeEffects(m_indexInBlock);
1880     }
1881     
1882     // Perform the most basic verification that children have been used correctly.
1883     if (!ASSERT_DISABLED) {
1884         for (auto& info : m_generationInfo)
1885             RELEASE_ASSERT(!info.alive());
1886     }
1887 }
1888
1889 // If we are making type predictions about our arguments then
1890 // we need to check that they are correct on function entry.
1891 void SpeculativeJIT::checkArgumentTypes()
1892 {
1893     ASSERT(!m_currentNode);
1894     m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
1895
1896     auto& arguments = m_jit.graph().m_rootToArguments.find(m_jit.graph().block(0))->value;
1897     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1898         Node* node = arguments[i];
1899         if (!node) {
1900             // The argument is dead. We don't do any checks for such arguments.
1901             continue;
1902         }
1903         
1904         ASSERT(node->op() == SetArgument);
1905         ASSERT(node->shouldGenerate());
1906
1907         VariableAccessData* variableAccessData = node->variableAccessData();
1908         FlushFormat format = variableAccessData->flushFormat();
1909         
1910         if (format == FlushedJSValue)
1911             continue;
1912         
1913         VirtualRegister virtualRegister = variableAccessData->local();
1914
1915         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1916         
1917 #if USE(JSVALUE64)
1918         switch (format) {
1919         case FlushedInt32: {
1920             speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1921             break;
1922         }
1923         case FlushedBoolean: {
1924             GPRTemporary temp(this);
1925             m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
1926             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1927             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1928             break;
1929         }
1930         case FlushedCell: {
1931             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
1932             break;
1933         }
1934         default:
1935             RELEASE_ASSERT_NOT_REACHED();
1936             break;
1937         }
1938 #else
1939         switch (format) {
1940         case FlushedInt32: {
1941             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1942             break;
1943         }
1944         case FlushedBoolean: {
1945             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1946             break;
1947         }
1948         case FlushedCell: {
1949             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1950             break;
1951         }
1952         default:
1953             RELEASE_ASSERT_NOT_REACHED();
1954             break;
1955         }
1956 #endif
1957     }
1958
1959     m_origin = NodeOrigin();
1960 }
1961
1962 bool SpeculativeJIT::compile()
1963 {
1964     checkArgumentTypes();
1965     
1966     ASSERT(!m_currentNode);
1967     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1968         m_jit.setForBlockIndex(blockIndex);
1969         m_block = m_jit.graph().block(blockIndex);
1970         compileCurrentBlock();
1971     }
1972     linkBranches();
1973     return true;
1974 }
1975
1976 void SpeculativeJIT::createOSREntries()
1977 {
1978     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1979         BasicBlock* block = m_jit.graph().block(blockIndex);
1980         if (!block)
1981             continue;
1982         if (block->isOSRTarget || block->isCatchEntrypoint) {
1983             // Currently we don't have OSR entry trampolines. We could add them
1984             // here if need be.
1985             m_osrEntryHeads.append(m_jit.blockHeads()[blockIndex]);
1986         }
1987     }
1988 }
1989
1990 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1991 {
1992     unsigned osrEntryIndex = 0;
1993     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1994         BasicBlock* block = m_jit.graph().block(blockIndex);
1995         if (!block)
1996             continue;
1997         if (!block->isOSRTarget && !block->isCatchEntrypoint)
1998             continue;
1999         if (block->isCatchEntrypoint) {
2000             auto& argumentsVector = m_jit.graph().m_rootToArguments.find(block)->value;
2001             Vector<FlushFormat> argumentFormats;
2002             argumentFormats.reserveInitialCapacity(argumentsVector.size());
2003             for (Node* setArgument : argumentsVector) {
2004                 if (setArgument) {
2005                     FlushFormat flushFormat = setArgument->variableAccessData()->flushFormat();
2006                     ASSERT(flushFormat == FlushedInt32 || flushFormat == FlushedCell || flushFormat == FlushedBoolean || flushFormat == FlushedJSValue);
2007                     argumentFormats.uncheckedAppend(flushFormat);
2008                 } else
2009                     argumentFormats.uncheckedAppend(DeadFlush);
2010             }
2011             m_jit.noticeCatchEntrypoint(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer, WTFMove(argumentFormats));
2012         } else {
2013             ASSERT(block->isOSRTarget);
2014             m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
2015         }
2016     }
2017
2018     m_jit.jitCode()->finalizeOSREntrypoints();
2019     m_jit.jitCode()->common.finalizeCatchEntrypoints();
2020
2021     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
2022     
2023     if (verboseCompilationEnabled()) {
2024         DumpContext dumpContext;
2025         dataLog("OSR Entries:\n");
2026         for (OSREntryData& entryData : m_jit.jitCode()->osrEntry)
2027             dataLog("    ", inContext(entryData, &dumpContext), "\n");
2028         if (!dumpContext.isEmpty())
2029             dumpContext.dump(WTF::dataFile());
2030     }
2031 }
2032     
2033 void SpeculativeJIT::compileCheckTraps(Node*)
2034 {
2035     ASSERT(Options::usePollingTraps());
2036     GPRTemporary unused(this);
2037     GPRReg unusedGPR = unused.gpr();
2038
2039     JITCompiler::Jump needTrapHandling = m_jit.branchTest8(JITCompiler::NonZero,
2040         JITCompiler::AbsoluteAddress(m_jit.vm()->needTrapHandlingAddress()));
2041
2042     addSlowPathGenerator(slowPathCall(needTrapHandling, this, operationHandleTraps, unusedGPR));
2043 }
2044
2045 void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
2046 {
2047     Edge child3 = m_jit.graph().varArgChild(node, 2);
2048     Edge child4 = m_jit.graph().varArgChild(node, 3);
2049
2050     ArrayMode arrayMode = node->arrayMode();
2051     
2052     GPRReg baseReg = base.gpr();
2053     GPRReg propertyReg = property.gpr();
2054     
2055     SpeculateDoubleOperand value(this, child3);
2056
2057     FPRReg valueReg = value.fpr();
2058     
2059     DFG_TYPE_CHECK(
2060         JSValueRegs(), child3, SpecFullRealNumber,
2061         m_jit.branchDouble(
2062             MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
2063     
2064     if (!m_compileOkay)
2065         return;
2066     
2067     StorageOperand storage(this, child4);
2068     GPRReg storageReg = storage.gpr();
2069
2070     if (node->op() == PutByValAlias) {
2071         // Store the value to the array.
2072         GPRReg propertyReg = property.gpr();
2073         FPRReg valueReg = value.fpr();
2074         m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2075         
2076         noResult(m_currentNode);
2077         return;
2078     }
2079     
2080     GPRTemporary temporary;
2081     GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2082
2083     MacroAssembler::Jump slowCase;
2084     
2085     if (arrayMode.isInBounds()) {
2086         speculationCheck(
2087             OutOfBounds, JSValueRegs(), 0,
2088             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2089     } else {
2090         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2091         
2092         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2093         
2094         if (!arrayMode.isOutOfBounds())
2095             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2096         
2097         m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2098         m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2099
2100         inBounds.link(&m_jit);
2101     }
2102     
2103     m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2104
2105     base.use();
2106     property.use();
2107     value.use();
2108     storage.use();
2109     
2110     if (arrayMode.isOutOfBounds()) {
2111         addSlowPathGenerator(
2112             slowPathCall(
2113                 slowCase, this,
2114                 m_jit.codeBlock()->isStrictMode()
2115                     ? (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict)
2116                     : (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict),
2117                 NoResult, baseReg, propertyReg, valueReg));
2118     }
2119
2120     noResult(m_currentNode, UseChildrenCalledExplicitly);
2121 }
2122
2123 void SpeculativeJIT::compileGetCharCodeAt(Node* node)
2124 {
2125     SpeculateCellOperand string(this, node->child1());
2126     SpeculateStrictInt32Operand index(this, node->child2());
2127     StorageOperand storage(this, node->child3());
2128
2129     GPRReg stringReg = string.gpr();
2130     GPRReg indexReg = index.gpr();
2131     GPRReg storageReg = storage.gpr();
2132     
2133     ASSERT(speculationChecked(m_state.forNode(node->child1()).m_type, SpecString));
2134
2135     // unsigned comparison so we can filter out negative indices and indices that are too large
2136     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
2137
2138     GPRTemporary scratch(this);
2139     GPRReg scratchReg = scratch.gpr();
2140
2141     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
2142
2143     // Load the character into scratchReg
2144     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2145
2146     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
2147     JITCompiler::Jump cont8Bit = m_jit.jump();
2148
2149     is16Bit.link(&m_jit);
2150
2151     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
2152
2153     cont8Bit.link(&m_jit);
2154
2155     int32Result(scratchReg, m_currentNode);
2156 }
2157
2158 void SpeculativeJIT::compileGetByValOnString(Node* node)
2159 {
2160     SpeculateCellOperand base(this, m_graph.child(node, 0));
2161     SpeculateStrictInt32Operand property(this, m_graph.child(node, 1));
2162     StorageOperand storage(this, m_graph.child(node, 2));
2163     GPRReg baseReg = base.gpr();
2164     GPRReg propertyReg = property.gpr();
2165     GPRReg storageReg = storage.gpr();
2166
2167     GPRTemporary scratch(this);
2168     GPRReg scratchReg = scratch.gpr();
2169 #if USE(JSVALUE32_64)
2170     GPRTemporary resultTag;
2171     GPRReg resultTagReg = InvalidGPRReg;
2172     if (node->arrayMode().isOutOfBounds()) {
2173         GPRTemporary realResultTag(this);
2174         resultTag.adopt(realResultTag);
2175         resultTagReg = resultTag.gpr();
2176     }
2177 #endif
2178
2179     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(m_graph.child(node, 0))));
2180
2181     // unsigned comparison so we can filter out negative indices and indices that are too large
2182     JITCompiler::Jump outOfBounds = m_jit.branch32(
2183         MacroAssembler::AboveOrEqual, propertyReg,
2184         MacroAssembler::Address(baseReg, JSString::offsetOfLength()));
2185     if (node->arrayMode().isInBounds())
2186         speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
2187
2188     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
2189
2190     // Load the character into scratchReg
2191     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2192
2193     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
2194     JITCompiler::Jump cont8Bit = m_jit.jump();
2195
2196     is16Bit.link(&m_jit);
2197
2198     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
2199
2200     JITCompiler::Jump bigCharacter =
2201         m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100));
2202
2203     // 8 bit string values don't need the isASCII check.
2204     cont8Bit.link(&m_jit);
2205
2206     m_jit.lshift32(MacroAssembler::TrustedImm32(sizeof(void*) == 4 ? 2 : 3), scratchReg);
2207     m_jit.addPtr(TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), scratchReg);
2208     m_jit.loadPtr(scratchReg, scratchReg);
2209
2210     addSlowPathGenerator(
2211         slowPathCall(
2212             bigCharacter, this, operationSingleCharacterString, scratchReg, scratchReg));
2213
2214     if (node->arrayMode().isOutOfBounds()) {
2215 #if USE(JSVALUE32_64)
2216         m_jit.move(TrustedImm32(JSValue::CellTag), resultTagReg);
2217 #endif
2218
2219         JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic);
2220         bool prototypeChainIsSane = false;
2221         if (globalObject->stringPrototypeChainIsSane()) {
2222             // FIXME: This could be captured using a Speculation mode that means "out-of-bounds
2223             // loads return a trivial value". Something like SaneChainOutOfBounds. This should
2224             // speculate that we don't take negative out-of-bounds, or better yet, it should rely
2225             // on a stringPrototypeChainIsSane() guaranteeing that the prototypes have no negative
2226             // indexed properties either.
2227             // https://bugs.webkit.org/show_bug.cgi?id=144668
2228             m_jit.graph().registerAndWatchStructureTransition(globalObject->stringPrototype()->structure());
2229             m_jit.graph().registerAndWatchStructureTransition(globalObject->objectPrototype()->structure());
2230             prototypeChainIsSane = globalObject->stringPrototypeChainIsSane();
2231         }
2232         if (prototypeChainIsSane) {
2233 #if USE(JSVALUE64)
2234             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2235                 outOfBounds, this, JSValueRegs(scratchReg), baseReg, propertyReg));
2236 #else
2237             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2238                 outOfBounds, this, JSValueRegs(resultTagReg, scratchReg),
2239                 baseReg, propertyReg));
2240 #endif
2241         } else {
2242 #if USE(JSVALUE64)
2243             addSlowPathGenerator(
2244                 slowPathCall(
2245                     outOfBounds, this, operationGetByValStringInt,
2246                     scratchReg, baseReg, propertyReg));
2247 #else
2248             addSlowPathGenerator(
2249                 slowPathCall(
2250                     outOfBounds, this, operationGetByValStringInt,
2251                     JSValueRegs(resultTagReg, scratchReg), baseReg, propertyReg));
2252 #endif
2253         }
2254         
2255 #if USE(JSVALUE64)
2256         jsValueResult(scratchReg, m_currentNode);
2257 #else
2258         jsValueResult(resultTagReg, scratchReg, m_currentNode);
2259 #endif
2260     } else
2261         cellResult(scratchReg, m_currentNode);
2262 }
2263
2264 void SpeculativeJIT::compileFromCharCode(Node* node)
2265 {
2266     Edge& child = node->child1();
2267     if (child.useKind() == UntypedUse) {
2268         JSValueOperand opr(this, child);
2269         JSValueRegs oprRegs = opr.jsValueRegs();
2270
2271         flushRegisters();
2272         JSValueRegsFlushedCallResult result(this);
2273         JSValueRegs resultRegs = result.regs();
2274         callOperation(operationStringFromCharCodeUntyped, resultRegs, oprRegs);
2275         m_jit.exceptionCheck();
2276         
2277         jsValueResult(resultRegs, node);
2278         return;
2279     }
2280
2281     SpeculateStrictInt32Operand property(this, child);
2282     GPRReg propertyReg = property.gpr();
2283     GPRTemporary smallStrings(this);
2284     GPRTemporary scratch(this);
2285     GPRReg scratchReg = scratch.gpr();
2286     GPRReg smallStringsReg = smallStrings.gpr();
2287
2288     JITCompiler::JumpList slowCases;
2289     slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(0xff)));
2290     m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
2291     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, propertyReg, MacroAssembler::ScalePtr, 0), scratchReg);
2292
2293     slowCases.append(m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2294     addSlowPathGenerator(slowPathCall(slowCases, this, operationStringFromCharCode, scratchReg, propertyReg));
2295     cellResult(scratchReg, m_currentNode);
2296 }
2297
2298 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)
2299 {
2300     VirtualRegister virtualRegister = node->virtualRegister();
2301     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2302
2303     switch (info.registerFormat()) {
2304     case DataFormatStorage:
2305         RELEASE_ASSERT_NOT_REACHED();
2306
2307     case DataFormatBoolean:
2308     case DataFormatCell:
2309         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2310         return GeneratedOperandTypeUnknown;
2311
2312     case DataFormatNone:
2313     case DataFormatJSCell:
2314     case DataFormatJS:
2315     case DataFormatJSBoolean:
2316     case DataFormatJSDouble:
2317         return GeneratedOperandJSValue;
2318
2319     case DataFormatJSInt32:
2320     case DataFormatInt32:
2321         return GeneratedOperandInteger;
2322
2323     default:
2324         RELEASE_ASSERT_NOT_REACHED();
2325         return GeneratedOperandTypeUnknown;
2326     }
2327 }
2328
2329 void SpeculativeJIT::compileValueToInt32(Node* node)
2330 {
2331     switch (node->child1().useKind()) {
2332 #if USE(JSVALUE64)
2333     case Int52RepUse: {
2334         SpeculateStrictInt52Operand op1(this, node->child1());
2335         GPRTemporary result(this, Reuse, op1);
2336         GPRReg op1GPR = op1.gpr();
2337         GPRReg resultGPR = result.gpr();
2338         m_jit.zeroExtend32ToPtr(op1GPR, resultGPR);
2339         int32Result(resultGPR, node, DataFormatInt32);
2340         return;
2341     }
2342 #endif // USE(JSVALUE64)
2343         
2344     case DoubleRepUse: {
2345         GPRTemporary result(this);
2346         SpeculateDoubleOperand op1(this, node->child1());
2347         FPRReg fpr = op1.fpr();
2348         GPRReg gpr = result.gpr();
2349         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
2350         
2351         addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this,
2352             hasSensibleDoubleToInt() ? operationToInt32SensibleSlow : operationToInt32, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded, gpr, fpr));
2353         
2354         int32Result(gpr, node);
2355         return;
2356     }
2357     
2358     case NumberUse:
2359     case NotCellUse: {
2360         switch (checkGeneratedTypeForToInt32(node->child1().node())) {
2361         case GeneratedOperandInteger: {
2362             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2363             GPRTemporary result(this, Reuse, op1);
2364             m_jit.move(op1.gpr(), result.gpr());
2365             int32Result(result.gpr(), node, op1.format());
2366             return;
2367         }
2368         case GeneratedOperandJSValue: {
2369             GPRTemporary result(this);
2370 #if USE(JSVALUE64)
2371             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2372
2373             GPRReg gpr = op1.gpr();
2374             GPRReg resultGpr = result.gpr();
2375             FPRTemporary tempFpr(this);
2376             FPRReg fpr = tempFpr.fpr();
2377
2378             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
2379             JITCompiler::JumpList converted;
2380
2381             if (node->child1().useKind() == NumberUse) {
2382                 DFG_TYPE_CHECK(
2383                     JSValueRegs(gpr), node->child1(), SpecBytecodeNumber,
2384                     m_jit.branchTest64(
2385                         MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
2386             } else {
2387                 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
2388                 
2389                 DFG_TYPE_CHECK(
2390                     JSValueRegs(gpr), node->child1(), ~SpecCellCheck, m_jit.branchIfCell(JSValueRegs(gpr)));
2391                 
2392                 // It's not a cell: so true turns into 1 and all else turns into 0.
2393                 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
2394                 converted.append(m_jit.jump());
2395                 
2396                 isNumber.link(&m_jit);
2397             }
2398
2399             // First, if we get here we have a double encoded as a JSValue
2400             unboxDouble(gpr, resultGpr, fpr);
2401
2402             silentSpillAllRegisters(resultGpr);
2403             callOperation(operationToInt32, resultGpr, fpr);
2404             silentFillAllRegisters();
2405
2406             converted.append(m_jit.jump());
2407
2408             isInteger.link(&m_jit);
2409             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
2410
2411             converted.link(&m_jit);
2412 #else
2413             Node* childNode = node->child1().node();
2414             VirtualRegister virtualRegister = childNode->virtualRegister();
2415             GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2416
2417             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2418
2419             GPRReg payloadGPR = op1.payloadGPR();
2420             GPRReg resultGpr = result.gpr();
2421         
2422             JITCompiler::JumpList converted;
2423
2424             if (info.registerFormat() == DataFormatJSInt32)
2425                 m_jit.move(payloadGPR, resultGpr);
2426             else {
2427                 GPRReg tagGPR = op1.tagGPR();
2428                 FPRTemporary tempFpr(this);
2429                 FPRReg fpr = tempFpr.fpr();
2430                 FPRTemporary scratch(this);
2431
2432                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
2433
2434                 if (node->child1().useKind() == NumberUse) {
2435                     DFG_TYPE_CHECK(
2436                         op1.jsValueRegs(), node->child1(), SpecBytecodeNumber,
2437                         m_jit.branch32(
2438                             MacroAssembler::AboveOrEqual, tagGPR,
2439                             TrustedImm32(JSValue::LowestTag)));
2440                 } else {
2441                     JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
2442                     
2443                     DFG_TYPE_CHECK(
2444                         op1.jsValueRegs(), node->child1(), ~SpecCell,
2445                         m_jit.branchIfCell(op1.jsValueRegs()));
2446                     
2447                     // It's not a cell: so true turns into 1 and all else turns into 0.
2448                     JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
2449                     m_jit.move(TrustedImm32(0), resultGpr);
2450                     converted.append(m_jit.jump());
2451                     
2452                     isBoolean.link(&m_jit);
2453                     m_jit.move(payloadGPR, resultGpr);
2454                     converted.append(m_jit.jump());
2455                     
2456                     isNumber.link(&m_jit);
2457                 }
2458
2459                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
2460
2461                 silentSpillAllRegisters(resultGpr);
2462                 callOperation(operationToInt32, resultGpr, fpr);
2463                 silentFillAllRegisters();
2464
2465                 converted.append(m_jit.jump());
2466
2467                 isInteger.link(&m_jit);
2468                 m_jit.move(payloadGPR, resultGpr);
2469
2470                 converted.link(&m_jit);
2471             }
2472 #endif
2473             int32Result(resultGpr, node);
2474             return;
2475         }
2476         case GeneratedOperandTypeUnknown:
2477             RELEASE_ASSERT(!m_compileOkay);
2478             return;
2479         }
2480         RELEASE_ASSERT_NOT_REACHED();
2481         return;
2482     }
2483     
2484     default:
2485         ASSERT(!m_compileOkay);
2486         return;
2487     }
2488 }
2489
2490 void SpeculativeJIT::compileUInt32ToNumber(Node* node)
2491 {
2492     if (doesOverflow(node->arithMode())) {
2493         if (enableInt52()) {
2494             SpeculateInt32Operand op1(this, node->child1());
2495             GPRTemporary result(this, Reuse, op1);
2496             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2497             strictInt52Result(result.gpr(), node);
2498             return;
2499         }
2500         SpeculateInt32Operand op1(this, node->child1());
2501         FPRTemporary result(this);
2502             
2503         GPRReg inputGPR = op1.gpr();
2504         FPRReg outputFPR = result.fpr();
2505             
2506         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2507             
2508         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2509         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
2510         positive.link(&m_jit);
2511             
2512         doubleResult(outputFPR, node);
2513         return;
2514     }
2515     
2516     RELEASE_ASSERT(node->arithMode() == Arith::CheckOverflow);
2517
2518     SpeculateInt32Operand op1(this, node->child1());
2519     GPRTemporary result(this);
2520
2521     m_jit.move(op1.gpr(), result.gpr());
2522
2523     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)));
2524
2525     int32Result(result.gpr(), node, op1.format());
2526 }
2527
2528 void SpeculativeJIT::compileDoubleAsInt32(Node* node)
2529 {
2530     SpeculateDoubleOperand op1(this, node->child1());
2531     FPRTemporary scratch(this);
2532     GPRTemporary result(this);
2533     
2534     FPRReg valueFPR = op1.fpr();
2535     FPRReg scratchFPR = scratch.fpr();
2536     GPRReg resultGPR = result.gpr();
2537
2538     JITCompiler::JumpList failureCases;
2539     RELEASE_ASSERT(shouldCheckOverflow(node->arithMode()));
2540     m_jit.branchConvertDoubleToInt32(
2541         valueFPR, resultGPR, failureCases, scratchFPR,
2542         shouldCheckNegativeZero(node->arithMode()));
2543     speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
2544
2545     int32Result(resultGPR, node);
2546 }
2547
2548 void SpeculativeJIT::compileDoubleRep(Node* node)
2549 {
2550     switch (node->child1().useKind()) {
2551     case RealNumberUse: {
2552         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2553         FPRTemporary result(this);
2554         
2555         JSValueRegs op1Regs = op1.jsValueRegs();
2556         FPRReg resultFPR = result.fpr();
2557         
2558 #if USE(JSVALUE64)
2559         GPRTemporary temp(this);
2560         GPRReg tempGPR = temp.gpr();
2561         m_jit.unboxDoubleWithoutAssertions(op1Regs.gpr(), tempGPR, resultFPR);
2562 #else
2563         FPRTemporary temp(this);
2564         FPRReg tempFPR = temp.fpr();
2565         unboxDouble(op1Regs.tagGPR(), op1Regs.payloadGPR(), resultFPR, tempFPR);
2566 #endif
2567         
2568         JITCompiler::Jump done = m_jit.branchDouble(
2569             JITCompiler::DoubleEqual, resultFPR, resultFPR);
2570         
2571         DFG_TYPE_CHECK(
2572             op1Regs, node->child1(), SpecBytecodeRealNumber, m_jit.branchIfNotInt32(op1Regs));
2573         m_jit.convertInt32ToDouble(op1Regs.payloadGPR(), resultFPR);
2574         
2575         done.link(&m_jit);
2576         
2577         doubleResult(resultFPR, node);
2578         return;
2579     }
2580     
2581     case NotCellUse:
2582     case NumberUse: {
2583         ASSERT(!node->child1()->isNumberConstant()); // This should have been constant folded.
2584
2585         SpeculatedType possibleTypes = m_state.forNode(node->child1()).m_type;
2586         if (isInt32Speculation(possibleTypes)) {
2587             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2588             FPRTemporary result(this);
2589             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
2590             doubleResult(result.fpr(), node);
2591             return;
2592         }
2593
2594         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2595         FPRTemporary result(this);
2596
2597 #if USE(JSVALUE64)
2598         GPRTemporary temp(this);
2599
2600         GPRReg op1GPR = op1.gpr();
2601         GPRReg tempGPR = temp.gpr();
2602         FPRReg resultFPR = result.fpr();
2603         JITCompiler::JumpList done;
2604
2605         JITCompiler::Jump isInteger = m_jit.branch64(
2606             MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
2607
2608         if (node->child1().useKind() == NotCellUse) {
2609             JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagTypeNumberRegister);
2610             JITCompiler::Jump isUndefined = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueUndefined));
2611
2612             static const double zero = 0;
2613             m_jit.loadDouble(TrustedImmPtr(&zero), resultFPR);
2614
2615             JITCompiler::Jump isNull = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueNull));
2616             done.append(isNull);
2617
2618             DFG_TYPE_CHECK(JSValueRegs(op1GPR), node->child1(), ~SpecCellCheck,
2619                 m_jit.branchTest64(JITCompiler::Zero, op1GPR, TrustedImm32(static_cast<int32_t>(TagBitBool))));
2620
2621             JITCompiler::Jump isFalse = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueFalse));
2622             static const double one = 1;
2623             m_jit.loadDouble(TrustedImmPtr(&one), resultFPR);
2624             done.append(m_jit.jump());
2625             done.append(isFalse);
2626
2627             isUndefined.link(&m_jit);
2628             static const double NaN = PNaN;
2629             m_jit.loadDouble(TrustedImmPtr(&NaN), resultFPR);
2630             done.append(m_jit.jump());
2631
2632             isNumber.link(&m_jit);
2633         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2634             typeCheck(
2635                 JSValueRegs(op1GPR), node->child1(), SpecBytecodeNumber,
2636                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
2637         }
2638
2639         unboxDouble(op1GPR, tempGPR, resultFPR);
2640         done.append(m_jit.jump());
2641     
2642         isInteger.link(&m_jit);
2643         m_jit.convertInt32ToDouble(op1GPR, resultFPR);
2644         done.link(&m_jit);
2645 #else // USE(JSVALUE64) -> this is the 32_64 case
2646         FPRTemporary temp(this);
2647     
2648         GPRReg op1TagGPR = op1.tagGPR();
2649         GPRReg op1PayloadGPR = op1.payloadGPR();
2650         FPRReg tempFPR = temp.fpr();
2651         FPRReg resultFPR = result.fpr();
2652         JITCompiler::JumpList done;
2653     
2654         JITCompiler::Jump isInteger = m_jit.branch32(
2655             MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
2656
2657         if (node->child1().useKind() == NotCellUse) {
2658             JITCompiler::Jump isNumber = m_jit.branch32(JITCompiler::Below, op1TagGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
2659             JITCompiler::Jump isUndefined = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::UndefinedTag));
2660
2661             static const double zero = 0;
2662             m_jit.loadDouble(TrustedImmPtr(&zero), resultFPR);
2663
2664             JITCompiler::Jump isNull = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::NullTag));
2665             done.append(isNull);
2666
2667             DFG_TYPE_CHECK(JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), ~SpecCell, m_jit.branch32(JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::BooleanTag)));
2668
2669             JITCompiler::Jump isFalse = m_jit.branchTest32(JITCompiler::Zero, op1PayloadGPR, TrustedImm32(1));
2670             static const double one = 1;
2671             m_jit.loadDouble(TrustedImmPtr(&one), resultFPR);
2672             done.append(m_jit.jump());
2673             done.append(isFalse);
2674
2675             isUndefined.link(&m_jit);
2676             static const double NaN = PNaN;
2677             m_jit.loadDouble(TrustedImmPtr(&NaN), resultFPR);
2678             done.append(m_jit.jump());
2679
2680             isNumber.link(&m_jit);
2681         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2682             typeCheck(
2683                 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecBytecodeNumber,
2684                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
2685         }
2686
2687         unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
2688         done.append(m_jit.jump());
2689     
2690         isInteger.link(&m_jit);
2691         m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
2692         done.link(&m_jit);
2693 #endif // USE(JSVALUE64)
2694     
2695         doubleResult(resultFPR, node);
2696         return;
2697     }
2698         
2699 #if USE(JSVALUE64)
2700     case Int52RepUse: {
2701         SpeculateStrictInt52Operand value(this, node->child1());
2702         FPRTemporary result(this);
2703         
2704         GPRReg valueGPR = value.gpr();
2705         FPRReg resultFPR = result.fpr();
2706
2707         m_jit.convertInt64ToDouble(valueGPR, resultFPR);
2708         
2709         doubleResult(resultFPR, node);
2710         return;
2711     }
2712 #endif // USE(JSVALUE64)
2713         
2714     default:
2715         RELEASE_ASSERT_NOT_REACHED();
2716         return;
2717     }
2718 }
2719
2720 void SpeculativeJIT::compileValueRep(Node* node)
2721 {
2722     switch (node->child1().useKind()) {
2723     case DoubleRepUse: {
2724         SpeculateDoubleOperand value(this, node->child1());
2725         JSValueRegsTemporary result(this);
2726         
2727         FPRReg valueFPR = value.fpr();
2728         JSValueRegs resultRegs = result.regs();
2729         
2730         // It's very tempting to in-place filter the value to indicate that it's not impure NaN
2731         // anymore. Unfortunately, this would be unsound. If it's a GetLocal or if the value was
2732         // subject to a prior SetLocal, filtering the value would imply that the corresponding
2733         // local was purified.
2734         if (needsTypeCheck(node->child1(), ~SpecDoubleImpureNaN))
2735             m_jit.purifyNaN(valueFPR);
2736
2737         boxDouble(valueFPR, resultRegs);
2738         
2739         jsValueResult(resultRegs, node);
2740         return;
2741     }
2742         
2743 #if USE(JSVALUE64)
2744     case Int52RepUse: {
2745         SpeculateStrictInt52Operand value(this, node->child1());
2746         GPRTemporary result(this);
2747         
2748         GPRReg valueGPR = value.gpr();
2749         GPRReg resultGPR = result.gpr();
2750         
2751         boxInt52(valueGPR, resultGPR, DataFormatStrictInt52);
2752         
2753         jsValueResult(resultGPR, node);
2754         return;
2755     }
2756 #endif // USE(JSVALUE64)
2757         
2758     default:
2759         RELEASE_ASSERT_NOT_REACHED();
2760         return;
2761     }
2762 }
2763
2764 static double clampDoubleToByte(double d)
2765 {
2766     d += 0.5;
2767     if (!(d > 0))
2768         d = 0;
2769     else if (d > 255)
2770         d = 255;
2771     return d;
2772 }
2773
2774 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
2775 {
2776     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
2777     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
2778     jit.xorPtr(result, result);
2779     MacroAssembler::Jump clamped = jit.jump();
2780     tooBig.link(&jit);
2781     jit.move(JITCompiler::TrustedImm32(255), result);
2782     clamped.link(&jit);
2783     inBounds.link(&jit);
2784 }
2785
2786 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
2787 {
2788     // Unordered compare so we pick up NaN
2789     static const double zero = 0;
2790     static const double byteMax = 255;
2791     static const double half = 0.5;
2792     jit.loadDouble(JITCompiler::TrustedImmPtr(&zero), scratch);
2793     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
2794     jit.loadDouble(JITCompiler::TrustedImmPtr(&byteMax), scratch);
2795     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
2796     
2797     jit.loadDouble(JITCompiler::TrustedImmPtr(&half), scratch);
2798     // FIXME: This should probably just use a floating point round!
2799     // https://bugs.webkit.org/show_bug.cgi?id=72054
2800     jit.addDouble(source, scratch);
2801     jit.truncateDoubleToInt32(scratch, result);   
2802     MacroAssembler::Jump truncatedInt = jit.jump();
2803     
2804     tooSmall.link(&jit);
2805     jit.xorPtr(result, result);
2806     MacroAssembler::Jump zeroed = jit.jump();
2807     
2808     tooBig.link(&jit);
2809     jit.move(JITCompiler::TrustedImm32(255), result);
2810     
2811     truncatedInt.link(&jit);
2812     zeroed.link(&jit);
2813
2814 }
2815
2816 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2817 {
2818     if (node->op() == PutByValAlias)
2819         return JITCompiler::Jump();
2820     JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(
2821         m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode());
2822     if (view) {
2823         uint32_t length = view->length();
2824         Node* indexNode = m_jit.graph().child(node, 1).node();
2825         if (indexNode->isInt32Constant() && indexNode->asUInt32() < length)
2826             return JITCompiler::Jump();
2827         return m_jit.branch32(
2828             MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length));
2829     }
2830     return m_jit.branch32(
2831         MacroAssembler::AboveOrEqual, indexGPR,
2832         MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
2833 }
2834
2835 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2836 {
2837     JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR);
2838     if (!jump.isSet())
2839         return;
2840     speculationCheck(OutOfBounds, JSValueRegs(), 0, jump);
2841 }
2842
2843 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds(Node* node, GPRReg base, JITCompiler::Jump outOfBounds)
2844 {
2845     JITCompiler::Jump done;
2846     if (outOfBounds.isSet()) {
2847         done = m_jit.jump();
2848         if (node->arrayMode().isInBounds())
2849             speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
2850         else {
2851             outOfBounds.link(&m_jit);
2852
2853             JITCompiler::Jump notWasteful = m_jit.branch32(
2854                 MacroAssembler::NotEqual,
2855                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfMode()),
2856                 TrustedImm32(WastefulTypedArray));
2857
2858             JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
2859                 MacroAssembler::Zero,
2860                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
2861             speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
2862             notWasteful.link(&m_jit);
2863         }
2864     }
2865     return done;
2866 }
2867
2868 void SpeculativeJIT::loadFromIntTypedArray(GPRReg storageReg, GPRReg propertyReg, GPRReg resultReg, TypedArrayType type)
2869 {
2870     switch (elementSize(type)) {
2871     case 1:
2872         if (isSigned(type))
2873             m_jit.load8SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2874         else
2875             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2876         break;
2877     case 2:
2878         if (isSigned(type))
2879             m_jit.load16SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2880         else
2881             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2882         break;
2883     case 4:
2884         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2885         break;
2886     default:
2887         CRASH();
2888     }
2889 }
2890
2891 void SpeculativeJIT::setIntTypedArrayLoadResult(Node* node, GPRReg resultReg, TypedArrayType type, bool canSpeculate)
2892 {
2893     if (elementSize(type) < 4 || isSigned(type)) {
2894         int32Result(resultReg, node);
2895         return;
2896     }
2897     
2898     ASSERT(elementSize(type) == 4 && !isSigned(type));
2899     if (node->shouldSpeculateInt32() && canSpeculate) {
2900         speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)));
2901         int32Result(resultReg, node);
2902         return;
2903     }
2904     
2905 #if USE(JSVALUE64)
2906     if (node->shouldSpeculateAnyInt()) {
2907         m_jit.zeroExtend32ToPtr(resultReg, resultReg);
2908         strictInt52Result(resultReg, node);
2909         return;
2910     }
2911 #endif
2912     
2913     FPRTemporary fresult(this);
2914     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
2915     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
2916     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
2917     positive.link(&m_jit);
2918     doubleResult(fresult.fpr(), node);
2919 }
2920
2921 void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type)
2922 {
2923     ASSERT(isInt(type));
2924     
2925     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2926     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2927     StorageOperand storage(this, m_graph.varArgChild(node, 2));
2928
2929     GPRReg baseReg = base.gpr();
2930     GPRReg propertyReg = property.gpr();
2931     GPRReg storageReg = storage.gpr();
2932
2933     GPRTemporary result(this);
2934     GPRReg resultReg = result.gpr();
2935
2936     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(m_graph.varArgChild(node, 0))));
2937
2938     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
2939     loadFromIntTypedArray(storageReg, propertyReg, resultReg, type);
2940     bool canSpeculate = true;
2941     setIntTypedArrayLoadResult(node, resultReg, type, canSpeculate);
2942 }
2943
2944 bool SpeculativeJIT::getIntTypedArrayStoreOperand(
2945     GPRTemporary& value,
2946     GPRReg property,
2947 #if USE(JSVALUE32_64)
2948     GPRTemporary& propertyTag,
2949     GPRTemporary& valueTag,
2950 #endif
2951     Edge valueUse, JITCompiler::JumpList& slowPathCases, bool isClamped)
2952 {
2953     bool isAppropriateConstant = false;
2954     if (valueUse->isConstant()) {
2955         JSValue jsValue = valueUse->asJSValue();
2956         SpeculatedType expectedType = typeFilterFor(valueUse.useKind());
2957         SpeculatedType actualType = speculationFromValue(jsValue);
2958         isAppropriateConstant = (expectedType | actualType) == expectedType;
2959     }
2960     
2961     if (isAppropriateConstant) {
2962         JSValue jsValue = valueUse->asJSValue();
2963         if (!jsValue.isNumber()) {
2964             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2965             return false;
2966         }
2967         double d = jsValue.asNumber();
2968         if (isClamped)
2969             d = clampDoubleToByte(d);
2970         GPRTemporary scratch(this);
2971         GPRReg scratchReg = scratch.gpr();
2972         m_jit.move(Imm32(toInt32(d)), scratchReg);
2973         value.adopt(scratch);
2974     } else {
2975         switch (valueUse.useKind()) {
2976         case Int32Use: {
2977             SpeculateInt32Operand valueOp(this, valueUse);
2978             GPRTemporary scratch(this);
2979             GPRReg scratchReg = scratch.gpr();
2980             m_jit.move(valueOp.gpr(), scratchReg);
2981             if (isClamped)
2982                 compileClampIntegerToByte(m_jit, scratchReg);
2983             value.adopt(scratch);
2984             break;
2985         }
2986             
2987 #if USE(JSVALUE64)
2988         case Int52RepUse: {
2989             SpeculateStrictInt52Operand valueOp(this, valueUse);
2990             GPRTemporary scratch(this);
2991             GPRReg scratchReg = scratch.gpr();
2992             m_jit.move(valueOp.gpr(), scratchReg);
2993             if (isClamped) {
2994                 MacroAssembler::Jump inBounds = m_jit.branch64(
2995                     MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff));
2996                 MacroAssembler::Jump tooBig = m_jit.branch64(
2997                     MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff));
2998                 m_jit.move(TrustedImm32(0), scratchReg);
2999                 MacroAssembler::Jump clamped = m_jit.jump();
3000                 tooBig.link(&m_jit);
3001                 m_jit.move(JITCompiler::TrustedImm32(255), scratchReg);
3002                 clamped.link(&m_jit);
3003                 inBounds.link(&m_jit);
3004             }
3005             value.adopt(scratch);
3006             break;
3007         }
3008 #endif // USE(JSVALUE64)
3009             
3010         case DoubleRepUse: {
3011             RELEASE_ASSERT(!isAtomicsIntrinsic(m_currentNode->op()));
3012             if (isClamped) {
3013                 SpeculateDoubleOperand valueOp(this, valueUse);
3014                 GPRTemporary result(this);
3015                 FPRTemporary floatScratch(this);
3016                 FPRReg fpr = valueOp.fpr();
3017                 GPRReg gpr = result.gpr();
3018                 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
3019                 value.adopt(result);
3020             } else {
3021 #if USE(JSVALUE32_64)
3022                 GPRTemporary realPropertyTag(this);
3023                 propertyTag.adopt(realPropertyTag);
3024                 GPRReg propertyTagGPR = propertyTag.gpr();
3025
3026                 GPRTemporary realValueTag(this);
3027                 valueTag.adopt(realValueTag);
3028                 GPRReg valueTagGPR = valueTag.gpr();
3029 #endif
3030                 SpeculateDoubleOperand valueOp(this, valueUse);
3031                 GPRTemporary result(this);
3032                 FPRReg fpr = valueOp.fpr();
3033                 GPRReg gpr = result.gpr();
3034                 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
3035                 m_jit.xorPtr(gpr, gpr);
3036                 MacroAssembler::JumpList fixed(m_jit.jump());
3037                 notNaN.link(&m_jit);
3038
3039                 fixed.append(m_jit.branchTruncateDoubleToInt32(
3040                     fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful));
3041
3042 #if USE(JSVALUE64)
3043                 m_jit.or64(GPRInfo::tagTypeNumberRegister, property);
3044                 boxDouble(fpr, gpr);
3045 #else
3046                 UNUSED_PARAM(property);
3047                 m_jit.move(TrustedImm32(JSValue::Int32Tag), propertyTagGPR);
3048                 boxDouble(fpr, valueTagGPR, gpr);
3049 #endif
3050                 slowPathCases.append(m_jit.jump());
3051
3052                 fixed.link(&m_jit);
3053                 value.adopt(result);
3054             }
3055             break;
3056         }
3057             
3058         default:
3059             RELEASE_ASSERT_NOT_REACHED();
3060             break;
3061         }
3062     }
3063     return true;
3064 }
3065
3066 void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
3067 {
3068     ASSERT(isInt(type));
3069     
3070     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
3071     GPRReg storageReg = storage.gpr();
3072     
3073     Edge valueUse = m_jit.graph().varArgChild(node, 2);
3074     
3075     GPRTemporary value;
3076 #if USE(JSVALUE32_64)
3077     GPRTemporary propertyTag;
3078     GPRTemporary valueTag;
3079 #endif
3080
3081     JITCompiler::JumpList slowPathCases;
3082     
3083     bool result = getIntTypedArrayStoreOperand(
3084         value, property,
3085 #if USE(JSVALUE32_64)
3086         propertyTag, valueTag,
3087 #endif
3088         valueUse, slowPathCases, isClamped(type));
3089     if (!result) {
3090         noResult(node);
3091         return;
3092     }
3093
3094     GPRReg valueGPR = value.gpr();
3095 #if USE(JSVALUE32_64)
3096     GPRReg propertyTagGPR = propertyTag.gpr();
3097     GPRReg valueTagGPR = valueTag.gpr();
3098 #endif
3099
3100     ASSERT_UNUSED(valueGPR, valueGPR != property);
3101     ASSERT(valueGPR != base);
3102     ASSERT(valueGPR != storageReg);
3103     JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
3104
3105     switch (elementSize(type)) {
3106     case 1:
3107         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
3108         break;
3109     case 2:
3110         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
3111         break;
3112     case 4:
3113         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
3114         break;
3115     default:
3116         CRASH();
3117     }
3118
3119     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
3120     if (done.isSet())
3121         done.link(&m_jit);
3122
3123     if (!slowPathCases.empty()) {
3124 #if USE(JSVALUE64)
3125         if (node->op() == PutByValDirect) {
3126             addSlowPathGenerator(slowPathCall(
3127                 slowPathCases, this,
3128                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict,
3129                 NoResult, base, property, valueGPR));
3130         } else {
3131             addSlowPathGenerator(slowPathCall(
3132                 slowPathCases, this,
3133                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict,
3134                 NoResult, base, property, valueGPR));
3135         }
3136 #else // not USE(JSVALUE64)
3137         if (node->op() == PutByValDirect) {
3138             addSlowPathGenerator(slowPathCall(
3139                 slowPathCases, this,
3140                 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict,
3141                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
3142         } else {
3143             addSlowPathGenerator(slowPathCall(
3144                 slowPathCases, this,
3145                 m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict,
3146                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
3147         }
3148 #endif
3149     }
3150     
3151     noResult(node);
3152 }
3153
3154 void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type)
3155 {
3156     ASSERT(isFloat(type));
3157     
3158     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
3159     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
3160     StorageOperand storage(this, m_graph.varArgChild(node, 2));
3161
3162     GPRReg baseReg = base.gpr();
3163     GPRReg propertyReg = property.gpr();
3164     GPRReg storageReg = storage.gpr();
3165
3166     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(m_graph.varArgChild(node, 0))));
3167
3168     FPRTemporary result(this);
3169     FPRReg resultReg = result.fpr();
3170     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
3171     switch (elementSize(type)) {
3172     case 4:
3173         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
3174         m_jit.convertFloatToDouble(resultReg, resultReg);
3175         break;
3176     case 8: {
3177         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
3178         break;
3179     }
3180     default:
3181         RELEASE_ASSERT_NOT_REACHED();
3182     }
3183     
3184     doubleResult(resultReg, node);
3185 }
3186
3187 void SpeculativeJIT::compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
3188 {
3189     ASSERT(isFloat(type));
3190     
3191     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
3192     GPRReg storageReg = storage.gpr();
3193     
3194     Edge baseUse = m_jit.graph().varArgChild(node, 0);
3195     Edge valueUse = m_jit.graph().varArgChild(node, 2);
3196
3197     SpeculateDoubleOperand valueOp(this, valueUse);
3198     FPRTemporary scratch(this);
3199     FPRReg valueFPR = valueOp.fpr();
3200     FPRReg scratchFPR = scratch.fpr();
3201
3202     ASSERT_UNUSED(baseUse, node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(baseUse)));
3203     
3204     MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
3205     
3206     switch (elementSize(type)) {
3207     case 4: {
3208         m_jit.moveDouble(valueFPR, scratchFPR);
3209         m_jit.convertDoubleToFloat(valueFPR, scratchFPR);
3210         m_jit.storeFloat(scratchFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
3211         break;
3212     }
3213     case 8:
3214         m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
3215         break;
3216     default:
3217         RELEASE_ASSERT_NOT_REACHED();
3218     }
3219
3220     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
3221     if (done.isSet())
3222         done.link(&m_jit);
3223     noResult(node);
3224 }
3225
3226 void SpeculativeJIT::compileGetByValForObjectWithString(Node* node)
3227 {
3228     SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0));
3229     SpeculateCellOperand arg2(this, m_graph.varArgChild(node, 1));
3230
3231     GPRReg arg1GPR = arg1.gpr();
3232     GPRReg arg2GPR = arg2.gpr();
3233
3234     speculateObject(m_graph.varArgChild(node, 0), arg1GPR);
3235     speculateString(m_graph.varArgChild(node, 1), arg2GPR);
3236
3237     flushRegisters();
3238     JSValueRegsFlushedCallResult result(this);
3239     JSValueRegs resultRegs = result.regs();
3240     callOperation(operationGetByValObjectString, resultRegs, arg1GPR, arg2GPR);
3241     m_jit.exceptionCheck();
3242
3243     jsValueResult(resultRegs, node);
3244 }
3245
3246 void SpeculativeJIT::compileGetByValForObjectWithSymbol(Node* node)
3247 {
3248     SpeculateCellOperand arg1(this, m_graph.varArgChild(node, 0));
3249     SpeculateCellOperand arg2(this, m_graph.varArgChild(node, 1));
3250
3251     GPRReg arg1GPR = arg1.gpr();
3252     GPRReg arg2GPR = arg2.gpr();
3253
3254     speculateObject(m_graph.varArgChild(node, 0), arg1GPR);
3255     speculateSymbol(m_graph.varArgChild(node, 1), arg2GPR);
3256
3257     flushRegisters();
3258     JSValueRegsFlushedCallResult result(this);
3259     JSValueRegs resultRegs = result.regs();
3260     callOperation(operationGetByValObjectSymbol, resultRegs, arg1GPR, arg2GPR);
3261     m_jit.exceptionCheck();
3262
3263     jsValueResult(resultRegs, node);
3264 }
3265
3266 void SpeculativeJIT::compilePutByValForCellWithString(Node* node, Edge& child1, Edge& child2, Edge& child3)
3267 {
3268     SpeculateCellOperand arg1(this, child1);
3269     SpeculateCellOperand arg2(this, child2);
3270     JSValueOperand arg3(this, child3);
3271
3272     GPRReg arg1GPR = arg1.gpr();
3273     GPRReg arg2GPR = arg2.gpr();
3274     JSValueRegs arg3Regs = arg3.jsValueRegs();
3275
3276     speculateString(child2, arg2GPR);
3277
3278     flushRegisters();
3279     callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellStringStrict : operationPutByValCellStringNonStrict, arg1GPR, arg2GPR, arg3Regs);
3280     m_jit.exceptionCheck();
3281
3282     noResult(node);
3283 }
3284
3285 void SpeculativeJIT::compilePutByValForCellWithSymbol(Node* node, Edge& child1, Edge& child2, Edge& child3)
3286 {
3287     SpeculateCellOperand arg1(this, child1);
3288     SpeculateCellOperand arg2(this, child2);
3289     JSValueOperand arg3(this, child3);
3290
3291     GPRReg arg1GPR = arg1.gpr();
3292     GPRReg arg2GPR = arg2.gpr();
3293     JSValueRegs arg3Regs = arg3.jsValueRegs();
3294
3295     speculateSymbol(child2, arg2GPR);
3296
3297     flushRegisters();
3298     callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellSymbolStrict : operationPutByValCellSymbolNonStrict, arg1GPR, arg2GPR, arg3Regs);
3299     m_jit.exceptionCheck();
3300
3301     noResult(node);
3302 }
3303
3304 void SpeculativeJIT::compileGetByValWithThis(Node* node)
3305 {
3306     JSValueOperand base(this, node->child1());
3307     JSValueRegs baseRegs = base.jsValueRegs();
3308     JSValueOperand thisValue(this, node->child2());
3309     JSValueRegs thisValueRegs = thisValue.jsValueRegs();
3310     JSValueOperand subscript(this, node->child3());
3311     JSValueRegs subscriptRegs = subscript.jsValueRegs();
3312
3313     flushRegisters();
3314     JSValueRegsFlushedCallResult result(this);
3315     JSValueRegs resultRegs = result.regs();
3316     callOperation(operationGetByValWithThis, resultRegs, baseRegs, thisValueRegs, subscriptRegs);
3317     m_jit.exceptionCheck();
3318
3319     jsValueResult(resultRegs, node);
3320 }
3321
3322 void SpeculativeJIT::compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg, GPRReg scratch2Reg, GPRReg scratch3Reg)
3323 {
3324     // Check that prototype is an object.
3325     speculationCheck(BadType, JSValueRegs(), 0, m_jit.branchIfNotObject(prototypeReg));
3326     
3327     // Initialize scratchReg with the value being checked.
3328     m_jit.move(valueReg, scratchReg);
3329     
3330     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
3331     MacroAssembler::Label loop(&m_jit);
3332     MacroAssembler::Jump performDefaultHasInstance = m_jit.branch8(MacroAssembler::Equal,
3333         MacroAssembler::Address(scratchReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ProxyObjectType));
3334     m_jit.emitLoadStructure(*m_jit.vm(), scratchReg, scratch3Reg, scratch2Reg);
3335 #if USE(JSVALUE64)
3336     m_jit.load64(MacroAssembler::Address(scratch3Reg, Structure::prototypeOffset()), scratch3Reg);
3337     auto hasMonoProto = m_jit.branchTest64(JITCompiler::NonZero, scratch3Reg);
3338     m_jit.load64(JITCompiler::Address(scratchReg, offsetRelativeToBase(knownPolyProtoOffset)), scratch3Reg);
3339     hasMonoProto.link(&m_jit);
3340     m_jit.move(scratch3Reg, scratchReg);
3341 #else
3342     m_jit.load32(MacroAssembler::Address(scratch3Reg, Structure::prototypeOffset() + TagOffset), scratch2Reg);
3343     m_jit.load32(MacroAssembler::Address(scratch3Reg, Structure::prototypeOffset() + PayloadOffset), scratch3Reg);
3344     auto hasMonoProto = m_jit.branch32(CCallHelpers::NotEqual, scratch2Reg, TrustedImm32(JSValue::EmptyValueTag));
3345     m_jit.load32(JITCompiler::Address(scratchReg, offsetRelativeToBase(knownPolyProtoOffset) + PayloadOffset), scratch3Reg);
3346     hasMonoProto.link(&m_jit);
3347     m_jit.move(scratch3Reg, scratchReg);
3348 #endif
3349
3350     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
3351 #if USE(JSVALUE64)
3352     m_jit.branchIfCell(JSValueRegs(scratchReg)).linkTo(loop, &m_jit);
3353 #else
3354     m_jit.branchTestPtr(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
3355 #endif
3356     
3357     // No match - result is false.
3358 #if USE(JSVALUE64)
3359     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
3360 #else
3361     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
3362 #endif
3363     MacroAssembler::JumpList doneJumps; 
3364     doneJumps.append(m_jit.jump());
3365
3366     performDefaultHasInstance.link(&m_jit);
3367     silentSpillAllRegisters(scratchReg);
3368     callOperation(operationDefaultHasInstance, scratchReg, valueReg, prototypeReg); 
3369     silentFillAllRegisters();
3370     m_jit.exceptionCheck();
3371 #if USE(JSVALUE64)
3372     m_jit.or32(TrustedImm32(ValueFalse), scratchReg);
3373 #endif
3374     doneJumps.append(m_jit.jump());
3375     
3376     isInstance.link(&m_jit);
3377 #if USE(JSVALUE64)
3378     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), scratchReg);
3379 #else
3380     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
3381 #endif
3382     
3383     doneJumps.link(&m_jit);
3384 }
3385
3386 void SpeculativeJIT::compileCheckTypeInfoFlags(Node* node)
3387 {
3388     SpeculateCellOperand base(this, node->child1());
3389
3390     GPRReg baseGPR = base.gpr();
3391
3392     // FIXME: This only works for checking if a single bit is set. If we want to check more
3393     // than one bit at once, we'll need to fix this:
3394     // https://bugs.webkit.org/show_bug.cgi?id=185705
3395     speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
3396
3397     noResult(node);
3398 }
3399
3400 void SpeculativeJIT::compileParseInt(Node* node)
3401 {
3402     RELEASE_ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == StringUse);
3403     if (node->child2()) {
3404         SpeculateInt32Operand radix(this, node->child2());
3405         GPRReg radixGPR = radix.gpr();
3406         if (node->child1().useKind() == UntypedUse) {
3407             JSValueOperand value(this, node->child1());
3408             JSValueRegs valueRegs = value.jsValueRegs();
3409
3410             flushRegisters();
3411             JSValueRegsFlushedCallResult result(this);
3412             JSValueRegs resultRegs = result.regs();
3413             callOperation(operationParseIntGeneric, resultRegs, valueRegs, radixGPR);
3414             m_jit.exceptionCheck();
3415             jsValueResult(resultRegs, node);
3416             return;
3417         }
3418
3419         SpeculateCellOperand value(this, node->child1());
3420         GPRReg valueGPR = value.gpr();
3421         speculateString(node->child1(), valueGPR);
3422
3423         flushRegisters();
3424         JSValueRegsFlushedCallResult result(this);
3425         JSValueRegs resultRegs = result.regs();
3426         callOperation(operationParseIntString, resultRegs, valueGPR, radixGPR);
3427         m_jit.exceptionCheck();
3428         jsValueResult(resultRegs, node);
3429         return;
3430     }
3431
3432     if (node->child1().useKind() == UntypedUse) {
3433         JSValueOperand value(this, node->child1());
3434         JSValueRegs valueRegs = value.jsValueRegs();
3435
3436         flushRegisters();
3437         JSValueRegsFlushedCallResult result(this);
3438         JSValueRegs resultRegs = result.regs();
3439         callOperation(operationParseIntNoRadixGeneric, resultRegs, valueRegs);
3440         m_jit.exceptionCheck();
3441         jsValueResult(resultRegs, node);
3442         return;
3443     }
3444
3445     SpeculateCellOperand value(this, node->child1());
3446     GPRReg valueGPR = value.gpr();
3447     speculateString(node->child1(), valueGPR);
3448
3449     flushRegisters();
3450     JSValueRegsFlushedCallResult result(this);
3451     JSValueRegs resultRegs = result.regs();
3452     callOperation(operationParseIntStringNoRadix, resultRegs, valueGPR);
3453     m_jit.exceptionCheck();
3454     jsValueResult(resultRegs, node);
3455 }
3456
3457 void SpeculativeJIT::compileOverridesHasInstance(Node* node)
3458 {
3459     Node* hasInstanceValueNode = node->child2().node();
3460     JSFunction* defaultHasInstanceFunction = jsCast<JSFunction*>(node->cellOperand()->value());
3461
3462     MacroAssembler::JumpList notDefault;
3463     SpeculateCellOperand base(this, node->child1());
3464     JSValueOperand hasInstanceValue(this, node->child2());
3465     GPRTemporary result(this);
3466
3467     GPRReg baseGPR = base.gpr();
3468     GPRReg resultGPR = result.gpr();
3469
3470     // It would be great if constant folding handled automatically the case where we knew the hasInstance function
3471     // was a constant. Unfortunately, the folding rule for OverridesHasInstance is in the strength reduction phase
3472     // since it relies on OSR information. https://bugs.webkit.org/show_bug.cgi?id=154832
3473     if (!hasInstanceValueNode->isCellConstant() || defaultHasInstanceFunction != hasInstanceValueNode->asCell()) {
3474         JSValueRegs hasInstanceValueRegs = hasInstanceValue.jsValueRegs();
3475 #if USE(JSVALUE64)
3476         notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.gpr(), TrustedImmPtr(node->cellOperand())));
3477 #else
3478         notDefault.append(m_jit.branchIfNotCell(hasInstanceValueRegs));
3479         notDefault.append(m_jit.branchPtr(MacroAssembler::NotEqual, hasInstanceValueRegs.payloadGPR(), TrustedImmPtr(node->cellOperand())));
3480 #endif
3481     }
3482
3483     // Check that base 'ImplementsDefaultHasInstance'.
3484     m_jit.test8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance), resultGPR);
3485     MacroAssembler::Jump done = m_jit.jump();
3486
3487     if (!notDefault.empty()) {
3488         notDefault.link(&m_jit);
3489         m_jit.move(TrustedImm32(1), resultGPR);
3490     }
3491
3492     done.link(&m_jit);
3493     unblessedBooleanResult(resultGPR, node);
3494 }
3495
3496 void SpeculativeJIT::compileInstanceOf(Node* node)
3497 {
3498     if (node->child1().useKind() == UntypedUse) {
3499         // It might not be a cell. Speculate less aggressively.
3500         // Or: it might only be used once (i.e. by us), so we get zero benefit
3501         // from speculating any more aggressively than we absolutely need to.
3502         
3503         JSValueOperand value(this, node->child1());
3504         SpeculateCellOperand prototype(this, node->child2());
3505         GPRTemporary scratch(this);
3506         GPRTemporary scratch2(this);
3507         GPRTemporary scratch3(this);
3508         
3509         GPRReg prototypeReg = prototype.gpr();
3510         GPRReg scratchReg = scratch.gpr();
3511         GPRReg scratch2Reg = scratch2.gpr();
3512         GPRReg scratch3Reg = scratch3.gpr();
3513         
3514         MacroAssembler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3515         GPRReg valueReg = value.jsValueRegs().payloadGPR();
3516         moveFalseTo(scratchReg);
3517
3518         MacroAssembler::Jump done = m_jit.jump();
3519         
3520         isCell.link(&m_jit);
3521         
3522         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg, scratch3Reg);
3523         
3524         done.link(&m_jit);
3525
3526         blessedBooleanResult(scratchReg, node);
3527         return;
3528     }
3529     
3530     SpeculateCellOperand value(this, node->child1());
3531     SpeculateCellOperand prototype(this, node->child2());
3532     
3533     GPRTemporary scratch(this);
3534     GPRTemporary scratch2(this);
3535     GPRTemporary scratch3(this);
3536     
3537     GPRReg valueReg = value.gpr();
3538     GPRReg prototypeReg = prototype.gpr();
3539     GPRReg scratchReg = scratch.gpr();
3540     GPRReg scratch2Reg = scratch2.gpr();
3541     GPRReg scratch3Reg = scratch3.gpr();
3542     
3543     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg, scratch3Reg);
3544
3545     blessedBooleanResult(scratchReg, node);
3546 }
3547
3548 template<typename SnippetGenerator, J_JITOperation_EJJ snippetSlowPathFunction>
3549 void SpeculativeJIT::emitUntypedBitOp(Node* node)
3550 {
3551     Edge& leftChild = node->child1();
3552     Edge& rightChild = node->child2();
3553
3554     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3555         JSValueOperand left(this, leftChild);
3556         JSValueOperand right(this, rightChild);
3557         JSValueRegs leftRegs = left.jsValueRegs();
3558         JSValueRegs rightRegs = right.jsValueRegs();
3559
3560         flushRegisters();
3561         JSValueRegsFlushedCallResult result(this);
3562         JSValueRegs resultRegs = result.regs();
3563         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3564         m_jit.exceptionCheck();
3565
3566         jsValueResult(resultRegs, node);
3567         return;
3568     }
3569
3570     std::optional<JSValueOperand> left;
3571     std::optional<JSValueOperand> right;
3572
3573     JSValueRegs leftRegs;
3574     JSValueRegs rightRegs;
3575
3576 #if USE(JSVALUE64)
3577     GPRTemporary result(this);
3578     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3579     GPRTemporary scratch(this);
3580     GPRReg scratchGPR = scratch.gpr();
3581 #else
3582     GPRTemporary resultTag(this);
3583     GPRTemporary resultPayload(this);
3584     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3585     GPRReg scratchGPR = resultTag.gpr();
3586 #endif
3587
3588     SnippetOperand leftOperand;
3589     SnippetOperand rightOperand;
3590
3591     // The snippet generator does not support both operands being constant. If the left
3592     // operand is already const, we'll ignore the right operand's constness.
3593     if (leftChild->isInt32Constant())
3594         leftOperand.setConstInt32(leftChild->asInt32());
3595     else if (rightChild->isInt32Constant())
3596         rightOperand.setConstInt32(rightChild->asInt32());
3597
3598     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3599
3600     if (!leftOperand.isConst()) {
3601         left.emplace(this, leftChild);
3602         leftRegs = left->jsValueRegs();
3603     }
3604     if (!rightOperand.isConst()) {
3605         right.emplace(this, rightChild);
3606         rightRegs = right->jsValueRegs();
3607     }
3608
3609     SnippetGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, scratchGPR);
3610     gen.generateFastPath(m_jit);
3611
3612     ASSERT(gen.didEmitFastPath());
3613     gen.endJumpList().append(m_jit.jump());
3614
3615     gen.slowPathJumpList().link(&m_jit);
3616     silentSpillAllRegisters(resultRegs);
3617
3618     if (leftOperand.isConst()) {
3619         leftRegs = resultRegs;
3620         m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3621     } else if (rightOperand.isConst()) {
3622         rightRegs = resultRegs;
3623         m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3624     }
3625
3626     callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3627
3628     silentFillAllRegisters();
3629     m_jit.exceptionCheck();
3630
3631     gen.endJumpList().link(&m_jit);
3632     jsValueResult(resultRegs, node);
3633 }
3634
3635 void SpeculativeJIT::compileBitwiseOp(Node* node)
3636 {
3637     NodeType op = node->op();
3638     Edge& leftChild = node->child1();
3639     Edge& rightChild = node->child2();
3640
3641     if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
3642         switch (op) {
3643         case BitAnd:
3644             emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
3645             return;
3646         case BitOr:
3647             emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
3648             return;
3649         case BitXor:
3650             emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
3651             return;
3652         default:
3653             RELEASE_ASSERT_NOT_REACHED();
3654         }
3655     }
3656
3657     if (leftChild->isInt32Constant()) {
3658         SpeculateInt32Operand op2(this, rightChild);
3659         GPRTemporary result(this, Reuse, op2);
3660
3661         bitOp(op, leftChild->asInt32(), op2.gpr(), result.gpr());
3662
3663         int32Result(result.gpr(), node);
3664
3665     } else if (rightChild->isInt32Constant()) {
3666         SpeculateInt32Operand op1(this, leftChild);
3667         GPRTemporary result(this, Reuse, op1);
3668
3669         bitOp(op, rightChild->asInt32(), op1.gpr(), result.gpr());
3670
3671         int32Result(result.gpr(), node);
3672
3673     } else {
3674         SpeculateInt32Operand op1(this, leftChild);
3675         SpeculateInt32Operand op2(this, rightChild);
3676         GPRTemporary result(this, Reuse, op1, op2);
3677         
3678         GPRReg reg1 = op1.gpr();
3679         GPRReg reg2 = op2.gpr();
3680         bitOp(op, reg1, reg2, result.gpr());
3681         
3682         int32Result(result.gpr(), node);
3683     }
3684 }
3685
3686 void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
3687 {
3688     J_JITOperation_EJJ snippetSlowPathFunction = node->op() == BitRShift
3689         ? operationValueBitRShift : operationValueBitURShift;
3690     JITRightShiftGenerator::ShiftType shiftType = node->op() == BitRShift
3691         ? JITRightShiftGenerator::SignedShift : JITRightShiftGenerator::UnsignedShift;
3692
3693     Edge& leftChild = node->child1();
3694     Edge& rightChild = node->child2();
3695
3696     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3697         JSValueOperand left(this, leftChild);
3698         JSValueOperand right(this, rightChild);
3699         JSValueRegs leftRegs = left.jsValueRegs();
3700         JSValueRegs rightRegs = right.jsValueRegs();
3701
3702         flushRegisters();
3703         JSValueRegsFlushedCallResult result(this);
3704         JSValueRegs resultRegs = result.regs();
3705         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3706         m_jit.exceptionCheck();
3707
3708         jsValueResult(resultRegs, node);
3709         return;
3710     }
3711
3712     std::optional<JSValueOperand> left;
3713     std::optional<JSValueOperand> right;
3714
3715     JSValueRegs leftRegs;
3716     JSValueRegs rightRegs;
3717
3718     FPRTemporary leftNumber(this);
3719     FPRReg leftFPR = leftNumber.fpr();
3720
3721 #if USE(JSVALUE64)
3722     GPRTemporary result(this);
3723     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3724     GPRTemporary scratch(this);
3725     GPRReg scratchGPR = scratch.gpr();
3726     FPRReg scratchFPR = InvalidFPRReg;
3727 #else
3728     GPRTemporary resultTag(this);
3729     GPRTemporary resultPayload(this);
3730     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3731     GPRReg scratchGPR = resultTag.gpr();
3732     FPRTemporary fprScratch(this);
3733     FPRReg scratchFPR = fprScratch.fpr();
3734 #endif
3735
3736     SnippetOperand leftOperand;
3737     SnippetOperand rightOperand;
3738
3739     // The snippet generator does not support both operands being constant. If the left
3740     // operand is already const, we'll ignore the right operand's constness.
3741     if (leftChild->isInt32Constant())
3742         leftOperand.setConstInt32(leftChild->asInt32());
3743     else if (rightChild->isInt32Constant())
3744         rightOperand.setConstInt32(rightChild->asInt32());
3745
3746     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3747
3748     if (!leftOperand.isConst()) {
3749         left.emplace(this, leftChild);
3750         leftRegs = left->jsValueRegs();
3751     }
3752     if (!rightOperand.isConst()) {
3753         right.emplace(this, rightChild);
3754         rightRegs = right->jsValueRegs();
3755     }
3756
3757     JITRightShiftGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
3758         leftFPR, scratchGPR, scratchFPR, shiftType);
3759     gen.generateFastPath(m_jit);
3760
3761     ASSERT(gen.didEmitFastPath());
3762     gen.endJumpList().append(m_jit.jump());
3763
3764     gen.slowPathJumpList().link(&m_jit);
3765     silentSpillAllRegisters(resultRegs);
3766
3767     if (leftOperand.isConst()) {
3768         leftRegs = resultRegs;
3769         m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3770     } else if (rightOperand.isConst()) {
3771         rightRegs = resultRegs;
3772         m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3773     }
3774
3775     callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3776
3777     silentFillAllRegisters();
3778     m_jit.exceptionCheck();
3779
3780     gen.endJumpList().link(&m_jit);
3781     jsValueResult(resultRegs, node);
3782     return;
3783 }
3784
3785 void SpeculativeJIT::compileShiftOp(Node* node)
3786 {
3787     NodeType op = node->op();
3788     Edge& leftChild = node->child1();
3789     Edge& rightChild = node->child2();
3790
3791     if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
3792         switch (op) {
3793         case BitLShift:
3794             emitUntypedBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
3795             return;
3796         case BitRShift:
3797         case BitURShift:
3798             emitUntypedRightShiftBitOp(node);
3799             return;
3800         default:
3801             RELEASE_ASSERT_NOT_REACHED();
3802         }
3803     }
3804
3805     if (rightChild->isInt32Constant()) {
3806         SpeculateInt32Operand op1(this, leftChild);
3807         GPRTemporary result(this, Reuse, op1);
3808
3809         shiftOp(op, op1.gpr(), rightChild->asInt32() & 0x1f, result.gpr());
3810
3811         int32Result(result.gpr(), node);
3812     } else {
3813         // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
3814         SpeculateInt32Operand op1(this, leftChild);
3815         SpeculateInt32Operand op2(this, rightChild);
3816         GPRTemporary result(this, Reuse, op1);
3817
3818         GPRReg reg1 = op1.gpr();
3819         GPRReg reg2 = op2.gpr();
3820         shiftOp(op, reg1, reg2, result.gpr());
3821
3822         int32Result(result.gpr(), node);
3823     }
3824 }
3825
3826 void SpeculativeJIT::compileValueAdd(Node* node)
3827 {
3828     Edge& leftChild = node->child1();
3829     Edge& rightChild = node->child2();
3830
3831     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3832         JSValueOperand left(this, leftChild);
3833         JSValueOperand right(this, rightChild);
3834         JSValueRegs leftRegs = left.jsValueRegs();
3835         JSValueRegs rightRegs = right.jsValueRegs();
3836
3837         flushRegisters();
3838         JSValueRegsFlushedCallResult result(this);
3839         JSValueRegs resultRegs = result.regs();
3840         callOperation(operationValueAddNotNumber, resultRegs, leftRegs, rightRegs);
3841         m_jit.exceptionCheck();
3842     
3843         jsValueResult(resultRegs, node);
3844         return;
3845     }
3846
3847 #if USE(JSVALUE64)
3848     bool needsScratchGPRReg = true;
3849     bool needsScratchFPRReg = false;
3850 #else
3851     bool needsScratchGPRReg = true;
3852     bool needsScratchFPRReg = true;
3853 #endif
3854
3855     CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
3856     ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
3857     Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex];
3858     JITAddIC* addIC = m_jit.codeBlock()->addJITAddIC(arithProfile, instruction);
3859     auto repatchingFunction = operationValueAddOptimize;
3860     auto nonRepatchingFunction = operationValueAdd;
3861     
3862     compileMathIC(node, addIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
3863 }
3864
3865 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
3866 void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
3867 {
3868     Edge& leftChild = node->child1();
3869     Edge& rightChild = node->child2();
3870
3871     std::optional<JSValueOperand> left;
3872     std::optional<JSValueOperand> right;
3873
3874     JSValueRegs leftRegs;
3875     JSValueRegs rightRegs;
3876
3877     FPRTemporary leftNumber(this);
3878     FPRTemporary rightNumber(this);
3879     FPRReg leftFPR = leftNumber.fpr();
3880     FPRReg rightFPR = rightNumber.fpr();
3881
3882     GPRReg scratchGPR = InvalidGPRReg;
3883     FPRReg scratchFPR = InvalidFPRReg;
3884
3885     std::optional<FPRTemporary> fprScratch;
3886     if (needsScratchFPRReg) {
3887         fprScratch.emplace(this);
3888         scratchFPR = fprScratch->fpr();
3889     }
3890
3891 #if USE(JSVALUE64)
3892     std::optional<GPRTemporary> gprScratch;
3893     if (needsScratchGPRReg) {
3894         gprScratch.emplace(this);
3895         scratchGPR = gprScratch->gpr();
3896     }
3897     GPRTemporary result(this);
3898     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3899 #else
3900     GPRTemporary&n