Executing known edge types may reveal a contradiction causing us to emit an exit...
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT64.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 "ArrayPrototype.h"
32 #include "AtomicsObject.h"
33 #include "CallFrameShuffler.h"
34 #include "DFGAbstractInterpreterInlines.h"
35 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
36 #include "DFGOperations.h"
37 #include "DFGSlowPathGenerator.h"
38 #include "DirectArguments.h"
39 #include "GetterSetter.h"
40 #include "HasOwnPropertyCache.h"
41 #include "JSCInlines.h"
42 #include "JSLexicalEnvironment.h"
43 #include "JSMap.h"
44 #include "JSPropertyNameEnumerator.h"
45 #include "JSSet.h"
46 #include "ObjectPrototype.h"
47 #include "SetupVarargsFrame.h"
48 #include "SpillRegistersMode.h"
49 #include "StringPrototype.h"
50 #include "TypeProfilerLog.h"
51 #include "Watchdog.h"
52
53 namespace JSC { namespace DFG {
54
55 #if USE(JSVALUE64)
56
57 void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format)
58 {
59     GPRReg tempGPR;
60     if (sourceGPR == targetGPR)
61         tempGPR = allocate();
62     else
63         tempGPR = targetGPR;
64     
65     FPRReg fpr = fprAllocate();
66
67     if (format == DataFormatInt52)
68         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
69     else
70         ASSERT(format == DataFormatStrictInt52);
71     
72     m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr);
73     
74     if (format == DataFormatInt52 && sourceGPR != targetGPR)
75         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
76     
77     if (tempGPR != targetGPR)
78         unlock(tempGPR);
79     
80     unlock(fpr);
81 }
82
83 GPRReg SpeculativeJIT::fillJSValue(Edge edge)
84 {
85     VirtualRegister virtualRegister = edge->virtualRegister();
86     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
87     
88     switch (info.registerFormat()) {
89     case DataFormatNone: {
90         GPRReg gpr = allocate();
91
92         if (edge->hasConstant()) {
93             JSValue jsValue = edge->asJSValue();
94             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
95             info.fillJSValue(*m_stream, gpr, DataFormatJS);
96             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
97         } else {
98             DataFormat spillFormat = info.spillFormat();
99             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
100             switch (spillFormat) {
101             case DataFormatInt32: {
102                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
103                 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
104                 spillFormat = DataFormatJSInt32;
105                 break;
106             }
107                 
108             default:
109                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
110                 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS, spillFormat);
111                 break;
112             }
113             info.fillJSValue(*m_stream, gpr, spillFormat);
114         }
115         return gpr;
116     }
117
118     case DataFormatInt32: {
119         GPRReg gpr = info.gpr();
120         // If the register has already been locked we need to take a copy.
121         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
122         if (m_gprs.isLocked(gpr)) {
123             GPRReg result = allocate();
124             m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
125             return result;
126         }
127         m_gprs.lock(gpr);
128         m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
129         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
130         return gpr;
131     }
132
133     case DataFormatCell:
134         // No retag required on JSVALUE64!
135     case DataFormatJS:
136     case DataFormatJSInt32:
137     case DataFormatJSDouble:
138     case DataFormatJSCell:
139     case DataFormatJSBoolean: {
140         GPRReg gpr = info.gpr();
141         m_gprs.lock(gpr);
142         return gpr;
143     }
144         
145     case DataFormatBoolean:
146     case DataFormatStorage:
147     case DataFormatDouble:
148     case DataFormatInt52:
149         // this type currently never occurs
150         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
151         
152     default:
153         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
154         return InvalidGPRReg;
155     }
156 }
157
158 void SpeculativeJIT::cachedGetById(CodeOrigin origin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget , SpillRegistersMode mode, AccessType type)
159 {
160     cachedGetById(origin, base.gpr(), result.gpr(), identifierNumber, slowPathTarget, mode, type);
161 }
162
163 void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode, AccessType type)
164 {
165     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
166     RegisterSet usedRegisters = this->usedRegisters();
167     if (spillMode == DontSpill) {
168         // We've already flushed registers to the stack, we don't need to spill these.
169         usedRegisters.set(baseGPR, false);
170         usedRegisters.set(resultGPR, false);
171     }
172     JITGetByIdGenerator gen(
173         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
174         JSValueRegs(baseGPR), JSValueRegs(resultGPR), type);
175     gen.generateFastPath(m_jit);
176     
177     JITCompiler::JumpList slowCases;
178     if (slowPathTarget.isSet())
179         slowCases.append(slowPathTarget);
180     slowCases.append(gen.slowPathJump());
181
182     auto slowPath = slowPathCall(
183         slowCases, this, appropriateOptimizingGetByIdFunction(type), GetPropertyPtrTag,
184         spillMode, ExceptionCheckRequirement::CheckNeeded,
185         resultGPR, gen.stubInfo(), baseGPR, identifierUID(identifierNumber));
186     
187     m_jit.addGetById(gen, slowPath.get());
188     addSlowPathGenerator(WTFMove(slowPath));
189 }
190
191 void SpeculativeJIT::cachedGetByIdWithThis(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::JumpList slowPathTarget)
192 {
193     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
194     RegisterSet usedRegisters = this->usedRegisters();
195     // We've already flushed registers to the stack, we don't need to spill these.
196     usedRegisters.set(baseGPR, false);
197     usedRegisters.set(thisGPR, false);
198     usedRegisters.set(resultGPR, false);
199     
200     JITGetByIdWithThisGenerator gen(
201         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
202         JSValueRegs(resultGPR), JSValueRegs(baseGPR), JSValueRegs(thisGPR), AccessType::GetWithThis);
203     gen.generateFastPath(m_jit);
204     
205     JITCompiler::JumpList slowCases;
206     if (!slowPathTarget.empty())
207         slowCases.append(slowPathTarget);
208     slowCases.append(gen.slowPathJump());
209     
210     auto slowPath = slowPathCall(
211         slowCases, this, operationGetByIdWithThisOptimize, GetPropertyPtrTag,
212         DontSpill, ExceptionCheckRequirement::CheckNeeded,
213         resultGPR, gen.stubInfo(), baseGPR, thisGPR, identifierUID(identifierNumber));
214     
215     m_jit.addGetByIdWithThis(gen, slowPath.get());
216     addSlowPathGenerator(WTFMove(slowPath));
217 }
218
219 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
220 {
221     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
222     RegisterSet usedRegisters = this->usedRegisters();
223     if (spillMode == DontSpill) {
224         // We've already flushed registers to the stack, we don't need to spill these.
225         usedRegisters.set(baseGPR, false);
226         usedRegisters.set(valueGPR, false);
227     }
228
229     JITPutByIdGenerator gen(
230         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),
231         JSValueRegs(valueGPR), scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);
232
233     gen.generateFastPath(m_jit);
234     
235     JITCompiler::JumpList slowCases;
236     if (slowPathTarget.isSet())
237         slowCases.append(slowPathTarget);
238     slowCases.append(gen.slowPathJump());
239     
240     auto slowPath = slowPathCall(
241         slowCases, this, gen.slowPathFunction(), PutPropertyPtrTag, NoResult, gen.stubInfo(), valueGPR, baseGPR,
242         identifierUID(identifierNumber));
243
244     m_jit.addPutById(gen, slowPath.get());
245     addSlowPathGenerator(WTFMove(slowPath));
246 }
247
248 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
249 {
250     ASSERT_WITH_MESSAGE(!masqueradesAsUndefinedWatchpointIsStillValid() || !isKnownCell(operand.node()), "The Compare should have been eliminated, it is known to be always false.");
251
252     JSValueOperand arg(this, operand, ManualOperandSpeculation);
253     GPRReg argGPR = arg.gpr();
254     
255     GPRTemporary result(this);
256     GPRReg resultGPR = result.gpr();
257
258     m_jit.move(TrustedImm32(0), resultGPR);
259
260     JITCompiler::JumpList done;
261     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
262         if (!isKnownNotCell(operand.node()))
263             done.append(m_jit.branchIfCell(JSValueRegs(argGPR)));
264     } else {
265         GPRTemporary localGlobalObject(this);
266         GPRTemporary remoteGlobalObject(this);
267         GPRTemporary scratch(this);
268
269         JITCompiler::Jump notCell;
270         if (!isKnownCell(operand.node()))
271             notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
272         
273         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
274             JITCompiler::Zero,
275             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
276             JITCompiler::TrustedImm32(MasqueradesAsUndefined));
277         done.append(isNotMasqueradesAsUndefined);
278
279         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
280         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
281         m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
282         m_jit.emitLoadStructure(*m_jit.vm(), argGPR, resultGPR, scratch.gpr());
283         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
284         m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
285         done.append(m_jit.jump());
286         if (!isKnownCell(operand.node()))
287             notCell.link(&m_jit);
288     }
289  
290     if (!isKnownNotOther(operand.node())) {
291         m_jit.move(argGPR, resultGPR);
292         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
293         m_jit.compare64(JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
294     }
295
296     done.link(&m_jit);
297  
298     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
299     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
300 }
301
302 void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode)
303 {
304     BasicBlock* taken = branchNode->branchData()->taken.block;
305     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
306
307     JSValueOperand arg(this, operand, ManualOperandSpeculation);
308     GPRReg argGPR = arg.gpr();
309     
310     GPRTemporary result(this, Reuse, arg);
311     GPRReg resultGPR = result.gpr();
312
313     // First, handle the case where "operand" is a cell.
314     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
315         if (!isKnownNotCell(operand.node())) {
316             JITCompiler::Jump isCell = m_jit.branchIfCell(JSValueRegs(argGPR));
317             addBranch(isCell, notTaken);
318         }
319     } else {
320         GPRTemporary localGlobalObject(this);
321         GPRTemporary remoteGlobalObject(this);
322         GPRTemporary scratch(this);
323
324         JITCompiler::Jump notCell;
325         if (!isKnownCell(operand.node()))
326             notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
327         
328         branchTest8(JITCompiler::Zero, 
329             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
330             JITCompiler::TrustedImm32(MasqueradesAsUndefined), notTaken);
331
332         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
333         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
334         m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
335         m_jit.emitLoadStructure(*m_jit.vm(), argGPR, resultGPR, scratch.gpr());
336         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
337         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
338
339         if (!isKnownCell(operand.node())) {
340             jump(notTaken, ForceJump);
341             notCell.link(&m_jit);
342         }
343     }
344
345     if (isKnownNotOther(operand.node()))
346         jump(notTaken);
347     else {
348         JITCompiler::RelationalCondition condition = JITCompiler::Equal;
349         if (taken == nextBlock()) {
350             condition = JITCompiler::NotEqual;
351             std::swap(taken, notTaken);
352         }
353         m_jit.move(argGPR, resultGPR);
354         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
355         branch64(condition, resultGPR, JITCompiler::TrustedImm64(ValueNull), taken);
356         jump(notTaken);
357     }
358 }
359
360 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
361 {
362     BasicBlock* taken = branchNode->branchData()->taken.block;
363     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
364
365     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
366
367     // The branch instruction will branch to the taken block.
368     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
369     if (taken == nextBlock()) {
370         cond = JITCompiler::invert(cond);
371         callResultCondition = JITCompiler::Zero;
372         BasicBlock* tmp = taken;
373         taken = notTaken;
374         notTaken = tmp;
375     }
376
377     JSValueOperand arg1(this, node->child1());
378     JSValueOperand arg2(this, node->child2());
379     GPRReg arg1GPR = arg1.gpr();
380     GPRReg arg2GPR = arg2.gpr();
381     
382     JITCompiler::JumpList slowPath;
383     
384     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
385         GPRFlushedCallResult result(this);
386         GPRReg resultGPR = result.gpr();
387     
388         arg1.use();
389         arg2.use();
390     
391         flushRegisters();
392         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
393         m_jit.exceptionCheck();
394
395         branchTest32(callResultCondition, resultGPR, taken);
396     } else {
397         GPRTemporary result(this, Reuse, arg2);
398         GPRReg resultGPR = result.gpr();
399     
400         arg1.use();
401         arg2.use();
402     
403         if (!isKnownInteger(node->child1().node()))
404             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
405         if (!isKnownInteger(node->child2().node()))
406             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
407     
408         branch32(cond, arg1GPR, arg2GPR, taken);
409     
410         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
411             jump(notTaken, ForceJump);
412     
413             slowPath.link(&m_jit);
414     
415             silentSpillAllRegisters(resultGPR);
416             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
417             silentFillAllRegisters();
418             m_jit.exceptionCheck();
419         
420             branchTest32(callResultCondition, resultGPR, taken);
421         }
422     }
423
424     jump(notTaken);
425
426     m_indexInBlock = m_block->size() - 1;
427     m_currentNode = branchNode;
428 }
429
430 template<typename JumpType>
431 class CompareAndBoxBooleanSlowPathGenerator
432     : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {
433 public:
434     CompareAndBoxBooleanSlowPathGenerator(
435         JumpType from, SpeculativeJIT* jit,
436         S_JITOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)
437         : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(
438             from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)
439         , m_arg1(arg1)
440         , m_arg2(arg2)
441     {
442     }
443     
444 protected:
445     void generateInternal(SpeculativeJIT* jit) override
446     {
447         this->setUp(jit);
448         this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));
449         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
450         jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);
451         this->tearDown(jit);
452     }
453    
454 private:
455     GPRReg m_arg1;
456     GPRReg m_arg2;
457 };
458
459 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
460 {
461     ASSERT(node->isBinaryUseKind(UntypedUse));
462     JSValueOperand arg1(this, node->child1());
463     JSValueOperand arg2(this, node->child2());
464     GPRReg arg1GPR = arg1.gpr();
465     GPRReg arg2GPR = arg2.gpr();
466     
467     JITCompiler::JumpList slowPath;
468     
469     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
470         GPRFlushedCallResult result(this);
471         GPRReg resultGPR = result.gpr();
472     
473         arg1.use();
474         arg2.use();
475     
476         flushRegisters();
477         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
478         m_jit.exceptionCheck();
479         
480         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
481         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
482     } else {
483         GPRTemporary result(this, Reuse, arg2);
484         GPRReg resultGPR = result.gpr();
485
486         arg1.use();
487         arg2.use();
488     
489         if (!isKnownInteger(node->child1().node()))
490             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
491         if (!isKnownInteger(node->child2().node()))
492             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
493     
494         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
495         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
496         
497         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
498             addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(
499                 slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR));
500         }
501
502         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
503     }
504 }
505
506 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
507 {
508     BasicBlock* taken = branchNode->branchData()->taken.block;
509     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
510
511     // The branch instruction will branch to the taken block.
512     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
513     if (taken == nextBlock()) {
514         invert = !invert;
515         BasicBlock* tmp = taken;
516         taken = notTaken;
517         notTaken = tmp;
518     }
519     
520     JSValueOperand arg1(this, node->child1());
521     JSValueOperand arg2(this, node->child2());
522     GPRReg arg1GPR = arg1.gpr();
523     GPRReg arg2GPR = arg2.gpr();
524     
525     GPRTemporary result(this);
526     GPRReg resultGPR = result.gpr();
527     
528     arg1.use();
529     arg2.use();
530     
531     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
532         // see if we get lucky: if the arguments are cells and they reference the same
533         // cell, then they must be strictly equal.
534         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
535         
536         silentSpillAllRegisters(resultGPR);
537         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
538         silentFillAllRegisters();
539         m_jit.exceptionCheck();
540         
541         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
542     } else {
543         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
544         
545         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
546         
547         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
548         JITCompiler::Jump leftDouble = m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
549         leftOK.link(&m_jit);
550         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
551         JITCompiler::Jump rightDouble = m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
552         rightOK.link(&m_jit);
553         
554         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
555         jump(notTaken, ForceJump);
556         
557         twoCellsCase.link(&m_jit);
558         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
559         
560         leftDouble.link(&m_jit);
561         rightDouble.link(&m_jit);
562         
563         silentSpillAllRegisters(resultGPR);
564         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
565         silentFillAllRegisters();
566         m_jit.exceptionCheck();
567         
568         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
569     }
570     
571     jump(notTaken);
572 }
573
574 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
575 {
576     JSValueOperand arg1(this, node->child1());
577     JSValueOperand arg2(this, node->child2());
578     GPRReg arg1GPR = arg1.gpr();
579     GPRReg arg2GPR = arg2.gpr();
580     
581     GPRTemporary result(this);
582     GPRReg resultGPR = result.gpr();
583     
584     arg1.use();
585     arg2.use();
586     
587     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
588         // see if we get lucky: if the arguments are cells and they reference the same
589         // cell, then they must be strictly equal.
590         // FIXME: this should flush registers instead of silent spill/fill.
591         JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR);
592         
593         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
594         
595         JITCompiler::Jump done = m_jit.jump();
596
597         notEqualCase.link(&m_jit);
598         
599         silentSpillAllRegisters(resultGPR);
600         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
601         silentFillAllRegisters();
602         m_jit.exceptionCheck();
603         
604         m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);
605         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
606         
607         done.link(&m_jit);
608     } else {
609         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
610         
611         JITCompiler::JumpList slowPathCases;
612         
613         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
614         
615         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
616         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister));
617         leftOK.link(&m_jit);
618         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
619         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister));
620         rightOK.link(&m_jit);
621         
622         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
623         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
624         
625         JITCompiler::Jump done = m_jit.jump();
626         
627         twoCellsCase.link(&m_jit);
628         slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR));
629         
630         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
631         
632         addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>>(
633                     slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR,
634                     arg2GPR));
635         
636         done.link(&m_jit);
637     }
638     
639     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
640 }
641
642 void SpeculativeJIT::compileMiscStrictEq(Node* node)
643 {
644     JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
645     JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
646     GPRTemporary result(this);
647     
648     if (node->child1().useKind() == MiscUse)
649         speculateMisc(node->child1(), op1.jsValueRegs());
650     if (node->child2().useKind() == MiscUse)
651         speculateMisc(node->child2(), op2.jsValueRegs());
652     
653     m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
654     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
655     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
656 }
657
658 void SpeculativeJIT::emitCall(Node* node)
659 {
660     CallLinkInfo::CallType callType;
661     bool isVarargs = false;
662     bool isForwardVarargs = false;
663     bool isTail = false;
664     bool isEmulatedTail = false;
665     bool isDirect = false;
666     switch (node->op()) {
667     case Call:
668     case CallEval:
669         callType = CallLinkInfo::Call;
670         break;
671     case TailCall:
672         callType = CallLinkInfo::TailCall;
673         isTail = true;
674         break;
675     case TailCallInlinedCaller:
676         callType = CallLinkInfo::Call;
677         isEmulatedTail = true;
678         break;
679     case Construct:
680         callType = CallLinkInfo::Construct;
681         break;
682     case CallVarargs:
683         callType = CallLinkInfo::CallVarargs;
684         isVarargs = true;
685         break;
686     case TailCallVarargs:
687         callType = CallLinkInfo::TailCallVarargs;
688         isVarargs = true;
689         isTail = true;
690         break;
691     case TailCallVarargsInlinedCaller:
692         callType = CallLinkInfo::CallVarargs;
693         isVarargs = true;
694         isEmulatedTail = true;
695         break;
696     case ConstructVarargs:
697         callType = CallLinkInfo::ConstructVarargs;
698         isVarargs = true;
699         break;
700     case CallForwardVarargs:
701         callType = CallLinkInfo::CallVarargs;
702         isForwardVarargs = true;
703         break;
704     case ConstructForwardVarargs:
705         callType = CallLinkInfo::ConstructVarargs;
706         isForwardVarargs = true;
707         break;
708     case TailCallForwardVarargs:
709         callType = CallLinkInfo::TailCallVarargs;
710         isTail = true;
711         isForwardVarargs = true;
712         break;
713     case TailCallForwardVarargsInlinedCaller:
714         callType = CallLinkInfo::CallVarargs;
715         isEmulatedTail = true;
716         isForwardVarargs = true;
717         break;
718     case DirectCall:
719         callType = CallLinkInfo::DirectCall;
720         isDirect = true;
721         break;
722     case DirectConstruct:
723         callType = CallLinkInfo::DirectConstruct;
724         isDirect = true;
725         break;
726     case DirectTailCall:
727         callType = CallLinkInfo::DirectTailCall;
728         isTail = true;
729         isDirect = true;
730         break;
731     case DirectTailCallInlinedCaller:
732         callType = CallLinkInfo::DirectCall;
733         isEmulatedTail = true;
734         isDirect = true;
735         break;
736     default:
737         DFG_CRASH(m_jit.graph(), node, "bad node type");
738         break;
739     }
740
741     GPRReg calleeGPR = InvalidGPRReg;
742     CallFrameShuffleData shuffleData;
743     
744     ExecutableBase* executable = nullptr;
745     FunctionExecutable* functionExecutable = nullptr;
746     if (isDirect) {
747         executable = node->castOperand<ExecutableBase*>();
748         functionExecutable = jsDynamicCast<FunctionExecutable*>(*m_jit.vm(), executable);
749     }
750     
751     unsigned numPassedArgs = 0;
752     unsigned numAllocatedArgs = 0;
753     
754     // Gotta load the arguments somehow. Varargs is trickier.
755     if (isVarargs || isForwardVarargs) {
756         RELEASE_ASSERT(!isDirect);
757         CallVarargsData* data = node->callVarargsData();
758
759         int numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
760         
761         if (isForwardVarargs) {
762             flushRegisters();
763             if (node->child3())
764                 use(node->child3());
765             
766             GPRReg scratchGPR1;
767             GPRReg scratchGPR2;
768             GPRReg scratchGPR3;
769             
770             scratchGPR1 = JITCompiler::selectScratchGPR();
771             scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1);
772             scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2);
773             
774             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
775             JITCompiler::JumpList slowCase;
776             InlineCallFrame* inlineCallFrame;
777             if (node->child3())
778                 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame;
779             else
780                 inlineCallFrame = node->origin.semantic.inlineCallFrame;
781             // emitSetupVarargsFrameFastCase modifies the stack pointer if it succeeds.
782             emitSetupVarargsFrameFastCase(*m_jit.vm(), m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
783             JITCompiler::Jump done = m_jit.jump();
784             slowCase.link(&m_jit);
785             callOperation(operationThrowStackOverflowForVarargs);
786             m_jit.exceptionCheck();
787             m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
788             done.link(&m_jit);
789         } else {
790             GPRReg argumentsGPR;
791             GPRReg scratchGPR1;
792             GPRReg scratchGPR2;
793             GPRReg scratchGPR3;
794             
795             auto loadArgumentsGPR = [&] (GPRReg reservedGPR) {
796                 if (reservedGPR != InvalidGPRReg)
797                     lock(reservedGPR);
798                 JSValueOperand arguments(this, node->child3());
799                 argumentsGPR = arguments.gpr();
800                 if (reservedGPR != InvalidGPRReg)
801                     unlock(reservedGPR);
802                 flushRegisters();
803                 
804                 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsGPR, reservedGPR);
805                 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, reservedGPR);
806                 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, scratchGPR2, reservedGPR);
807             };
808             
809             loadArgumentsGPR(InvalidGPRReg);
810             
811             DFG_ASSERT(m_jit.graph(), node, isFlushed());
812             
813             // Right now, arguments is in argumentsGPR and the register file is flushed.
814             callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsGPR, numUsedStackSlots, data->firstVarArgOffset);
815             m_jit.exceptionCheck();
816             
817             // Now we have the argument count of the callee frame, but we've lost the arguments operand.
818             // Reconstruct the arguments operand while preserving the callee frame.
819             loadArgumentsGPR(GPRInfo::returnValueGPR);
820             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);
821             emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);
822             m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);
823             
824             callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR);
825             m_jit.exceptionCheck();
826             m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::returnValueGPR, JITCompiler::stackPointerRegister);
827         }
828         
829         DFG_ASSERT(m_jit.graph(), node, isFlushed());
830         
831         // We don't need the arguments array anymore.
832         if (isVarargs)
833             use(node->child3());
834
835         // Now set up the "this" argument.
836         JSValueOperand thisArgument(this, node->child2());
837         GPRReg thisArgumentGPR = thisArgument.gpr();
838         thisArgument.use();
839         
840         m_jit.store64(thisArgumentGPR, JITCompiler::calleeArgumentSlot(0));
841     } else {
842         // The call instruction's first child is the function; the subsequent children are the
843         // arguments.
844         numPassedArgs = node->numChildren() - 1;
845         numAllocatedArgs = numPassedArgs;
846         
847         if (functionExecutable) {
848             // Allocate more args if this would let us avoid arity checks. This is throttled by
849             // CallLinkInfo's limit. It's probably good to throttle it - if the callee wants a
850             // ginormous amount of argument space then it's better for them to do it so that when we
851             // make calls to other things, we don't waste space.
852             unsigned desiredNumAllocatedArgs = static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
853             if (desiredNumAllocatedArgs <= Options::maximumDirectCallStackSize()) {
854                 numAllocatedArgs = std::max(numAllocatedArgs, desiredNumAllocatedArgs);
855                 
856                 // Whoever converts to DirectCall should do this adjustment. It's too late for us to
857                 // do this adjustment now since we will have already emitted code that relied on the
858                 // value of m_parameterSlots.
859                 DFG_ASSERT(
860                     m_jit.graph(), node,
861                     Graph::parameterSlotsForArgCount(numAllocatedArgs)
862                     <= m_jit.graph().m_parameterSlots);
863             }
864         }
865
866         if (isTail) {
867             Edge calleeEdge = m_jit.graph().child(node, 0);
868             JSValueOperand callee(this, calleeEdge);
869             calleeGPR = callee.gpr();
870             if (!isDirect)
871                 callee.use();
872
873             shuffleData.tagTypeNumber = GPRInfo::tagTypeNumberRegister;
874             shuffleData.numLocals = m_jit.graph().frameRegisterCount();
875             shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatJS);
876             shuffleData.args.resize(numAllocatedArgs);
877             shuffleData.numPassedArgs = numPassedArgs;
878             
879             for (unsigned i = 0; i < numPassedArgs; ++i) {
880                 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
881                 GenerationInfo& info = generationInfo(argEdge.node());
882                 if (!isDirect)
883                     use(argEdge);
884                 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
885             }
886             
887             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
888                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
889
890             shuffleData.setupCalleeSaveRegisters(m_jit.codeBlock());
891         } else {
892             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCount));
893
894             for (unsigned i = 0; i < numPassedArgs; i++) {
895                 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
896                 JSValueOperand arg(this, argEdge);
897                 GPRReg argGPR = arg.gpr();
898                 use(argEdge);
899                 
900                 m_jit.store64(argGPR, JITCompiler::calleeArgumentSlot(i));
901             }
902             
903             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
904                 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
905         }
906     }
907     
908     if (!isTail || isVarargs || isForwardVarargs) {
909         Edge calleeEdge = m_jit.graph().child(node, 0);
910         JSValueOperand callee(this, calleeEdge);
911         calleeGPR = callee.gpr();
912         callee.use();
913         m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
914
915         flushRegisters();
916     }
917
918     CodeOrigin staticOrigin = node->origin.semantic;
919     ASSERT(!isTail || !staticOrigin.inlineCallFrame || !staticOrigin.inlineCallFrame->getCallerSkippingTailCalls());
920     ASSERT(!isEmulatedTail || (staticOrigin.inlineCallFrame && staticOrigin.inlineCallFrame->getCallerSkippingTailCalls()));
921     CodeOrigin dynamicOrigin =
922         isEmulatedTail ? *staticOrigin.inlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
923
924     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
925     
926     auto setResultAndResetStack = [&] () {
927         GPRFlushedCallResult result(this);
928         GPRReg resultGPR = result.gpr();
929         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
930
931         jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
932
933         // After the calls are done, we need to reestablish our stack
934         // pointer. We rely on this for varargs calls, calls with arity
935         // mismatch (the callframe is slided) and tail calls.
936         m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
937     };
938     
939     CallLinkInfo* callLinkInfo = m_jit.codeBlock()->addCallLinkInfo();
940     callLinkInfo->setUpCall(callType, m_currentNode->origin.semantic, calleeGPR);
941
942     if (node->op() == CallEval) {
943         // We want to call operationCallEval but we don't want to overwrite the parameter area in
944         // which we have created a prototypical eval call frame. This means that we have to
945         // subtract stack to make room for the call. Lucky for us, at this point we have the whole
946         // register file to ourselves.
947         
948         m_jit.emitStoreCallSiteIndex(callSite);
949         m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
950         m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
951         
952         // Now we need to make room for:
953         // - The caller frame and PC of a call to operationCallEval.
954         // - Potentially two arguments on the stack.
955         unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
956         requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
957         m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
958         m_jit.setupArguments<decltype(operationCallEval)>(GPRInfo::regT0);
959         prepareForExternalCall();
960         m_jit.appendCall(operationCallEval);
961         m_jit.exceptionCheck();
962         JITCompiler::Jump done = m_jit.branchTest64(JITCompiler::NonZero, GPRInfo::returnValueGPR);
963         
964         // This is the part where we meant to make a normal call. Oops.
965         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
966         m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
967         m_jit.emitDumbVirtualCall(*m_jit.vm(), callLinkInfo);
968         
969         done.link(&m_jit);
970         setResultAndResetStack();
971         return;
972     }
973     
974     if (isDirect) {
975         callLinkInfo->setExecutableDuringCompilation(executable);
976         callLinkInfo->setMaxNumArguments(numAllocatedArgs);
977
978         if (isTail) {
979             RELEASE_ASSERT(node->op() == DirectTailCall);
980             
981             JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
982             JITCompiler::Label mainPath = m_jit.label();
983             
984             m_jit.emitStoreCallSiteIndex(callSite);
985             
986             callLinkInfo->setFrameShuffleData(shuffleData);
987             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
988             
989             JITCompiler::Call call = m_jit.nearTailCall();
990             
991             JITCompiler::Label slowPath = m_jit.label();
992             patchableJump.m_jump.linkTo(slowPath, &m_jit);
993             
994             silentSpillAllRegisters(InvalidGPRReg);
995             callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
996             silentFillAllRegisters();
997             m_jit.exceptionCheck();
998             m_jit.jump().linkTo(mainPath, &m_jit);
999             
1000             useChildren(node);
1001             
1002             m_jit.addJSDirectTailCall(patchableJump, call, slowPath, callLinkInfo);
1003             return;
1004         }
1005         
1006         JITCompiler::Label mainPath = m_jit.label();
1007         
1008         m_jit.emitStoreCallSiteIndex(callSite);
1009         
1010         JITCompiler::Call call = m_jit.nearCall();
1011         JITCompiler::Jump done = m_jit.jump();
1012         
1013         JITCompiler::Label slowPath = m_jit.label();
1014         if (isX86())
1015             m_jit.pop(JITCompiler::selectScratchGPR(calleeGPR));
1016
1017         callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
1018         m_jit.exceptionCheck();
1019         m_jit.jump().linkTo(mainPath, &m_jit);
1020         
1021         done.link(&m_jit);
1022         
1023         setResultAndResetStack();
1024         
1025         m_jit.addJSDirectCall(call, slowPath, callLinkInfo);
1026         return;
1027     }
1028     
1029     m_jit.emitStoreCallSiteIndex(callSite);
1030     
1031     JITCompiler::DataLabelPtr targetToCheck;
1032     JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, TrustedImmPtr(nullptr));
1033
1034     if (isTail) {
1035         if (node->op() == TailCall) {
1036             callLinkInfo->setFrameShuffleData(shuffleData);
1037             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
1038         } else {
1039             m_jit.emitRestoreCalleeSaves();
1040             m_jit.prepareForTailCallSlow();
1041         }
1042     }
1043
1044     JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
1045
1046     JITCompiler::Jump done = m_jit.jump();
1047
1048     slowPath.link(&m_jit);
1049
1050     if (node->op() == TailCall) {
1051         CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
1052         callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
1053         callFrameShuffler.prepareForSlowPath();
1054     } else {
1055         m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
1056
1057         if (isTail)
1058             m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
1059     }
1060
1061     m_jit.move(TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
1062     JITCompiler::Call slowCall = m_jit.nearCall();
1063
1064     done.link(&m_jit);
1065
1066     if (isTail)
1067         m_jit.abortWithReason(JITDidReturnFromTailCall);
1068     else
1069         setResultAndResetStack();
1070
1071     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
1072 }
1073
1074 // Clang should allow unreachable [[clang::fallthrough]] in template functions if any template expansion uses it
1075 // http://llvm.org/bugs/show_bug.cgi?id=18619
1076 #if COMPILER(CLANG) && defined(__has_warning)
1077 #pragma clang diagnostic push
1078 #if __has_warning("-Wimplicit-fallthrough")
1079 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
1080 #endif
1081 #endif
1082 template<bool strict>
1083 GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
1084 {
1085     AbstractValue& value = m_state.forNode(edge);
1086     SpeculatedType type = value.m_type;
1087     ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
1088
1089     m_interpreter.filter(value, SpecInt32Only);
1090     if (value.isClear()) {
1091         if (mayHaveTypeCheck(edge.useKind()))
1092             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1093         returnFormat = DataFormatInt32;
1094         return allocate();
1095     }
1096
1097     VirtualRegister virtualRegister = edge->virtualRegister();
1098     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1099
1100     switch (info.registerFormat()) {
1101     case DataFormatNone: {
1102         GPRReg gpr = allocate();
1103
1104         if (edge->hasConstant()) {
1105             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1106             ASSERT(edge->isInt32Constant());
1107             m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
1108             info.fillInt32(*m_stream, gpr);
1109             returnFormat = DataFormatInt32;
1110             return gpr;
1111         }
1112         
1113         DataFormat spillFormat = info.spillFormat();
1114         
1115         DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32, spillFormat);
1116         
1117         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1118         
1119         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
1120             // If we know this was spilled as an integer we can fill without checking.
1121             if (strict) {
1122                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1123                 info.fillInt32(*m_stream, gpr);
1124                 returnFormat = DataFormatInt32;
1125                 return gpr;
1126             }
1127             if (spillFormat == DataFormatInt32) {
1128                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1129                 info.fillInt32(*m_stream, gpr);
1130                 returnFormat = DataFormatInt32;
1131             } else {
1132                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1133                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1134                 returnFormat = DataFormatJSInt32;
1135             }
1136             return gpr;
1137         }
1138         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1139
1140         // Fill as JSValue, and fall through.
1141         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1142         m_gprs.unlock(gpr);
1143         FALLTHROUGH;
1144     }
1145
1146     case DataFormatJS: {
1147         DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
1148         // Check the value is an integer.
1149         GPRReg gpr = info.gpr();
1150         m_gprs.lock(gpr);
1151         if (type & ~SpecInt32Only)
1152             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1153         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1154         // If !strict we're done, return.
1155         if (!strict) {
1156             returnFormat = DataFormatJSInt32;
1157             return gpr;
1158         }
1159         // else fall through & handle as DataFormatJSInt32.
1160         m_gprs.unlock(gpr);
1161         FALLTHROUGH;
1162     }
1163
1164     case DataFormatJSInt32: {
1165         // In a strict fill we need to strip off the value tag.
1166         if (strict) {
1167             GPRReg gpr = info.gpr();
1168             GPRReg result;
1169             // If the register has already been locked we need to take a copy.
1170             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
1171             if (m_gprs.isLocked(gpr))
1172                 result = allocate();
1173             else {
1174                 m_gprs.lock(gpr);
1175                 info.fillInt32(*m_stream, gpr);
1176                 result = gpr;
1177             }
1178             m_jit.zeroExtend32ToPtr(gpr, result);
1179             returnFormat = DataFormatInt32;
1180             return result;
1181         }
1182
1183         GPRReg gpr = info.gpr();
1184         m_gprs.lock(gpr);
1185         returnFormat = DataFormatJSInt32;
1186         return gpr;
1187     }
1188
1189     case DataFormatInt32: {
1190         GPRReg gpr = info.gpr();
1191         m_gprs.lock(gpr);
1192         returnFormat = DataFormatInt32;
1193         return gpr;
1194     }
1195         
1196     case DataFormatJSDouble:
1197     case DataFormatCell:
1198     case DataFormatBoolean:
1199     case DataFormatJSCell:
1200     case DataFormatJSBoolean:
1201     case DataFormatDouble:
1202     case DataFormatStorage:
1203     case DataFormatInt52:
1204     case DataFormatStrictInt52:
1205         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1206         
1207     default:
1208         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1209         return InvalidGPRReg;
1210     }
1211 }
1212 #if COMPILER(CLANG) && defined(__has_warning)
1213 #pragma clang diagnostic pop
1214 #endif
1215
1216 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1217 {
1218     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1219 }
1220
1221 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1222 {
1223     DataFormat mustBeDataFormatInt32;
1224     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1225     DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32, mustBeDataFormatInt32);
1226     return result;
1227 }
1228
1229 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1230 {
1231     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1232     AbstractValue& value = m_state.forNode(edge);
1233
1234     m_interpreter.filter(value, SpecAnyInt);
1235     if (value.isClear()) {
1236         if (mayHaveTypeCheck(edge.useKind()))
1237             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1238         return allocate();
1239     }
1240
1241     VirtualRegister virtualRegister = edge->virtualRegister();
1242     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1243
1244     switch (info.registerFormat()) {
1245     case DataFormatNone: {
1246         GPRReg gpr = allocate();
1247
1248         if (edge->hasConstant()) {
1249             JSValue jsValue = edge->asJSValue();
1250             ASSERT(jsValue.isAnyInt());
1251             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1252             int64_t value = jsValue.asAnyInt();
1253             if (desiredFormat == DataFormatInt52)
1254                 value = value << JSValue::int52ShiftAmount;
1255             m_jit.move(MacroAssembler::Imm64(value), gpr);
1256             info.fillGPR(*m_stream, gpr, desiredFormat);
1257             return gpr;
1258         }
1259         
1260         DataFormat spillFormat = info.spillFormat();
1261         
1262         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52, spillFormat);
1263         
1264         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1265         
1266         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1267         if (desiredFormat == DataFormatStrictInt52) {
1268             if (spillFormat == DataFormatInt52)
1269                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1270             info.fillStrictInt52(*m_stream, gpr);
1271             return gpr;
1272         }
1273         if (spillFormat == DataFormatStrictInt52)
1274             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1275         info.fillInt52(*m_stream, gpr);
1276         return gpr;
1277     }
1278
1279     case DataFormatStrictInt52: {
1280         GPRReg gpr = info.gpr();
1281         bool wasLocked = m_gprs.isLocked(gpr);
1282         lock(gpr);
1283         if (desiredFormat == DataFormatStrictInt52)
1284             return gpr;
1285         if (wasLocked) {
1286             GPRReg result = allocate();
1287             m_jit.move(gpr, result);
1288             unlock(gpr);
1289             gpr = result;
1290         } else
1291             info.fillInt52(*m_stream, gpr);
1292         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1293         return gpr;
1294     }
1295         
1296     case DataFormatInt52: {
1297         GPRReg gpr = info.gpr();
1298         bool wasLocked = m_gprs.isLocked(gpr);
1299         lock(gpr);
1300         if (desiredFormat == DataFormatInt52)
1301             return gpr;
1302         if (wasLocked) {
1303             GPRReg result = allocate();
1304             m_jit.move(gpr, result);
1305             unlock(gpr);
1306             gpr = result;
1307         } else
1308             info.fillStrictInt52(*m_stream, gpr);
1309         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1310         return gpr;
1311     }
1312
1313     default:
1314         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1315         return InvalidGPRReg;
1316     }
1317 }
1318
1319 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1320 {
1321     ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1322     ASSERT(edge->hasDoubleResult());
1323     VirtualRegister virtualRegister = edge->virtualRegister();
1324     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1325
1326     if (info.registerFormat() == DataFormatNone) {
1327         if (edge->hasConstant()) {
1328             if (edge->isNumberConstant()) {
1329                 FPRReg fpr = fprAllocate();
1330                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1331                 if (!doubleAsInt)
1332                     m_jit.moveZeroToDouble(fpr);
1333                 else {
1334                     GPRReg gpr = allocate();
1335                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1336                     m_jit.move64ToDouble(gpr, fpr);
1337                     unlock(gpr);
1338                 }
1339
1340                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1341                 info.fillDouble(*m_stream, fpr);
1342                 return fpr;
1343             }
1344             if (mayHaveTypeCheck(edge.useKind()))
1345                 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1346             return fprAllocate();
1347         }
1348         
1349         DataFormat spillFormat = info.spillFormat();
1350         if (spillFormat != DataFormatDouble) {
1351             DFG_CRASH(
1352                 m_jit.graph(), m_currentNode, toCString(
1353                     "Expected ", edge, " to have double format but instead it is spilled as ",
1354                     dataFormatToString(spillFormat)).data());
1355         }
1356         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble, spillFormat);
1357         FPRReg fpr = fprAllocate();
1358         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1359         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1360         info.fillDouble(*m_stream, fpr);
1361         return fpr;
1362     }
1363
1364     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble, info.registerFormat());
1365     FPRReg fpr = info.fpr();
1366     m_fprs.lock(fpr);
1367     return fpr;
1368 }
1369
1370 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1371 {
1372     AbstractValue& value = m_state.forNode(edge);
1373     SpeculatedType type = value.m_type;
1374     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCellCheck));
1375
1376     m_interpreter.filter(value, SpecCellCheck);
1377     if (value.isClear()) {
1378         if (mayHaveTypeCheck(edge.useKind()))
1379             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1380         return allocate();
1381     }
1382
1383     VirtualRegister virtualRegister = edge->virtualRegister();
1384     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1385
1386     switch (info.registerFormat()) {
1387     case DataFormatNone: {
1388         GPRReg gpr = allocate();
1389
1390         if (edge->hasConstant()) {
1391             JSValue jsValue = edge->asJSValue();
1392             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1393             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1394             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1395             return gpr;
1396         }
1397
1398         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1399         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1400
1401         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1402         if (type & ~SpecCellCheck)
1403             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1404         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1405         return gpr;
1406     }
1407
1408     case DataFormatCell:
1409     case DataFormatJSCell: {
1410         GPRReg gpr = info.gpr();
1411         m_gprs.lock(gpr);
1412         if (!ASSERT_DISABLED) {
1413             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1414             m_jit.abortWithReason(DFGIsNotCell);
1415             checkCell.link(&m_jit);
1416         }
1417         return gpr;
1418     }
1419
1420     case DataFormatJS: {
1421         GPRReg gpr = info.gpr();
1422         m_gprs.lock(gpr);
1423         if (type & ~SpecCellCheck)
1424             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1425         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1426         return gpr;
1427     }
1428
1429     case DataFormatJSInt32:
1430     case DataFormatInt32:
1431     case DataFormatJSDouble:
1432     case DataFormatJSBoolean:
1433     case DataFormatBoolean:
1434     case DataFormatDouble:
1435     case DataFormatStorage:
1436     case DataFormatInt52:
1437     case DataFormatStrictInt52:
1438         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1439         
1440     default:
1441         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1442         return InvalidGPRReg;
1443     }
1444 }
1445
1446 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1447 {
1448     AbstractValue& value = m_state.forNode(edge);
1449     SpeculatedType type = value.m_type;
1450     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1451
1452     m_interpreter.filter(value, SpecBoolean);
1453     if (value.isClear()) {
1454         if (mayHaveTypeCheck(edge.useKind()))
1455             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1456         return allocate();
1457     }
1458
1459     VirtualRegister virtualRegister = edge->virtualRegister();
1460     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1461
1462     switch (info.registerFormat()) {
1463     case DataFormatNone: {
1464         GPRReg gpr = allocate();
1465
1466         if (edge->hasConstant()) {
1467             JSValue jsValue = edge->asJSValue();
1468             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1469             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1470             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1471             return gpr;
1472         }
1473         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS, info.spillFormat());
1474         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1475         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1476
1477         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1478         if (type & ~SpecBoolean) {
1479             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1480             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1481             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1482         }
1483         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1484         return gpr;
1485     }
1486
1487     case DataFormatBoolean:
1488     case DataFormatJSBoolean: {
1489         GPRReg gpr = info.gpr();
1490         m_gprs.lock(gpr);
1491         return gpr;
1492     }
1493
1494     case DataFormatJS: {
1495         GPRReg gpr = info.gpr();
1496         m_gprs.lock(gpr);
1497         if (type & ~SpecBoolean) {
1498             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1499             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1500             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1501         }
1502         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1503         return gpr;
1504     }
1505
1506     case DataFormatJSInt32:
1507     case DataFormatInt32:
1508     case DataFormatJSDouble:
1509     case DataFormatJSCell:
1510     case DataFormatCell:
1511     case DataFormatDouble:
1512     case DataFormatStorage:
1513     case DataFormatInt52:
1514     case DataFormatStrictInt52:
1515         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1516         
1517     default:
1518         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1519         return InvalidGPRReg;
1520     }
1521 }
1522
1523 void SpeculativeJIT::compileObjectEquality(Node* node)
1524 {
1525     SpeculateCellOperand op1(this, node->child1());
1526     SpeculateCellOperand op2(this, node->child2());
1527     GPRTemporary result(this, Reuse, op1);
1528     
1529     GPRReg op1GPR = op1.gpr();
1530     GPRReg op2GPR = op2.gpr();
1531     GPRReg resultGPR = result.gpr();
1532    
1533     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1534         DFG_TYPE_CHECK(
1535             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1536         DFG_TYPE_CHECK(
1537             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1538     } else {
1539         DFG_TYPE_CHECK(
1540             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1541         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1542             m_jit.branchTest8(
1543                 MacroAssembler::NonZero, 
1544                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1545                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1546
1547         DFG_TYPE_CHECK(
1548             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1549         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1550             m_jit.branchTest8(
1551                 MacroAssembler::NonZero, 
1552                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1553                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1554     }
1555
1556     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1557     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1558     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1559 }
1560
1561 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1562 {
1563     SpeculateCellOperand op1(this, objectChild);
1564     JSValueOperand op2(this, otherChild);
1565     GPRTemporary result(this);
1566
1567     GPRReg op1GPR = op1.gpr();
1568     GPRReg op2GPR = op2.gpr();
1569     GPRReg resultGPR = result.gpr();
1570
1571     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1572
1573     // At this point we know that we can perform a straight-forward equality comparison on pointer
1574     // values because we are doing strict equality.
1575     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1576     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1577     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1578 }
1579     
1580 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1581 {
1582     BasicBlock* taken = branchNode->branchData()->taken.block;
1583     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1584     
1585     SpeculateCellOperand op1(this, objectChild);
1586     JSValueOperand op2(this, otherChild);
1587     
1588     GPRReg op1GPR = op1.gpr();
1589     GPRReg op2GPR = op2.gpr();
1590     
1591     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1592
1593     if (taken == nextBlock()) {
1594         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1595         jump(taken);
1596     } else {
1597         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1598         jump(notTaken);
1599     }
1600 }
1601
1602 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1603 {
1604     SpeculateCellOperand op1(this, leftChild);
1605     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1606     GPRTemporary result(this);
1607     
1608     GPRReg op1GPR = op1.gpr();
1609     GPRReg op2GPR = op2.gpr();
1610     GPRReg resultGPR = result.gpr();
1611
1612     bool masqueradesAsUndefinedWatchpointValid =
1613         masqueradesAsUndefinedWatchpointIsStillValid();
1614
1615     if (masqueradesAsUndefinedWatchpointValid) {
1616         DFG_TYPE_CHECK(
1617             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1618     } else {
1619         DFG_TYPE_CHECK(
1620             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1621         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1622             m_jit.branchTest8(
1623                 MacroAssembler::NonZero, 
1624                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1625                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1626     }
1627     
1628     // It seems that most of the time when programs do a == b where b may be either null/undefined
1629     // or an object, b is usually an object. Balance the branches to make that case fast.
1630     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1631     
1632     // We know that within this branch, rightChild must be a cell. 
1633     if (masqueradesAsUndefinedWatchpointValid) {
1634         DFG_TYPE_CHECK(
1635             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1636     } else {
1637         DFG_TYPE_CHECK(
1638             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1639         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1640             m_jit.branchTest8(
1641                 MacroAssembler::NonZero, 
1642                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1643                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1644     }
1645     
1646     // At this point we know that we can perform a straight-forward equality comparison on pointer
1647     // values because both left and right are pointers to objects that have no special equality
1648     // protocols.
1649     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1650     MacroAssembler::Jump done = m_jit.jump();
1651     
1652     rightNotCell.link(&m_jit);
1653     
1654     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1655     // prove that it is either null or undefined.
1656     if (needsTypeCheck(rightChild, SpecCellCheck | SpecOther)) {
1657         m_jit.move(op2GPR, resultGPR);
1658         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1659         
1660         typeCheck(
1661             JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther,
1662             m_jit.branch64(
1663                 MacroAssembler::NotEqual, resultGPR,
1664                 MacroAssembler::TrustedImm64(ValueNull)));
1665     }
1666     m_jit.move(TrustedImm32(0), result.gpr());
1667
1668     done.link(&m_jit);
1669     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1670     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1671 }
1672
1673 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1674 {
1675     BasicBlock* taken = branchNode->branchData()->taken.block;
1676     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1677     
1678     SpeculateCellOperand op1(this, leftChild);
1679     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1680     GPRTemporary result(this);
1681     
1682     GPRReg op1GPR = op1.gpr();
1683     GPRReg op2GPR = op2.gpr();
1684     GPRReg resultGPR = result.gpr();
1685     
1686     bool masqueradesAsUndefinedWatchpointValid = 
1687         masqueradesAsUndefinedWatchpointIsStillValid();
1688
1689     if (masqueradesAsUndefinedWatchpointValid) {
1690         DFG_TYPE_CHECK(
1691             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1692     } else {
1693         DFG_TYPE_CHECK(
1694             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1695         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1696             m_jit.branchTest8(
1697                 MacroAssembler::NonZero, 
1698                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1699                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1700     }
1701
1702     // It seems that most of the time when programs do a == b where b may be either null/undefined
1703     // or an object, b is usually an object. Balance the branches to make that case fast.
1704     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1705     
1706     // We know that within this branch, rightChild must be a cell. 
1707     if (masqueradesAsUndefinedWatchpointValid) {
1708         DFG_TYPE_CHECK(
1709             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1710     } else {
1711         DFG_TYPE_CHECK(
1712             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1713         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1714             m_jit.branchTest8(
1715                 MacroAssembler::NonZero, 
1716                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1717                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1718     }
1719     
1720     // At this point we know that we can perform a straight-forward equality comparison on pointer
1721     // values because both left and right are pointers to objects that have no special equality
1722     // protocols.
1723     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1724     
1725     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1726     // prove that it is either null or undefined.
1727     if (!needsTypeCheck(rightChild, SpecCellCheck | SpecOther))
1728         rightNotCell.link(&m_jit);
1729     else {
1730         jump(notTaken, ForceJump);
1731         
1732         rightNotCell.link(&m_jit);
1733         m_jit.move(op2GPR, resultGPR);
1734         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1735         
1736         typeCheck(
1737             JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther, m_jit.branch64(
1738                 MacroAssembler::NotEqual, resultGPR,
1739                 MacroAssembler::TrustedImm64(ValueNull)));
1740     }
1741     
1742     jump(notTaken);
1743 }
1744
1745 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1746 {
1747     SpeculateCellOperand symbol(this, symbolEdge);
1748     JSValueOperand untyped(this, untypedEdge);
1749     GPRTemporary result(this, Reuse, symbol, untyped);
1750
1751     GPRReg symbolGPR = symbol.gpr();
1752     GPRReg untypedGPR = untyped.gpr();
1753     GPRReg resultGPR = result.gpr();
1754
1755     speculateSymbol(symbolEdge, symbolGPR);
1756
1757     // At this point we know that we can perform a straight-forward equality comparison on pointer
1758     // values because we are doing strict equality.
1759     m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
1760     unblessedBooleanResult(resultGPR, node);
1761 }
1762
1763 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1764 {
1765     if (node->child1()->isInt32Constant()) {
1766         SpeculateInt32Operand op2(this, node->child2());
1767         GPRTemporary result(this, Reuse, op2);
1768         int32_t imm = node->child1()->asInt32();
1769         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1770
1771         // If we add a DataFormatBool, we should use it here.
1772         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1773         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1774     } else if (node->child2()->isInt32Constant()) {
1775         SpeculateInt32Operand op1(this, node->child1());
1776         GPRTemporary result(this, Reuse, op1);
1777         int32_t imm = node->child2()->asInt32();
1778         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1779
1780         // If we add a DataFormatBool, we should use it here.
1781         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1782         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1783     } else {
1784         SpeculateInt32Operand op1(this, node->child1());
1785         SpeculateInt32Operand op2(this, node->child2());
1786         GPRTemporary result(this, Reuse, op1, op2);
1787         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1788
1789         // If we add a DataFormatBool, we should use it here.
1790         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1791         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1792     }
1793 }
1794
1795 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1796 {
1797     SpeculateWhicheverInt52Operand op1(this, node->child1());
1798     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1799     GPRTemporary result(this, Reuse, op1, op2);
1800     
1801     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1802     
1803     // If we add a DataFormatBool, we should use it here.
1804     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1805     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1806 }
1807
1808 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1809 {
1810     BasicBlock* taken = branchNode->branchData()->taken.block;
1811     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1812
1813     // The branch instruction will branch to the taken block.
1814     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1815     if (taken == nextBlock()) {
1816         condition = JITCompiler::invert(condition);
1817         BasicBlock* tmp = taken;
1818         taken = notTaken;
1819         notTaken = tmp;
1820     }
1821     
1822     SpeculateWhicheverInt52Operand op1(this, node->child1());
1823     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1824     
1825     branch64(condition, op1.gpr(), op2.gpr(), taken);
1826     jump(notTaken);
1827 }
1828
1829 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1830 {
1831     SpeculateDoubleOperand op1(this, node->child1());
1832     SpeculateDoubleOperand op2(this, node->child2());
1833     GPRTemporary result(this);
1834     
1835     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1836     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1837     m_jit.xor64(TrustedImm32(true), result.gpr());
1838     trueCase.link(&m_jit);
1839     
1840     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1841 }
1842
1843 void SpeculativeJIT::compileCompareEqPtr(Node* node)
1844 {
1845     JSValueOperand value(this, node->child1());
1846     GPRTemporary result(this);
1847     GPRReg valueGPR = value.gpr();
1848     GPRReg resultGPR = result.gpr();
1849
1850     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), node->cellOperand()->cell()), resultGPR);
1851     m_jit.compare64(MacroAssembler::Equal, valueGPR, resultGPR, resultGPR);
1852     unblessedBooleanResult(resultGPR, node);
1853 }
1854
1855 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1856 {
1857     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1858     GPRTemporary result(this);
1859     GPRReg valueGPR = value.gpr();
1860     GPRReg resultGPR = result.gpr();
1861     GPRTemporary structure;
1862     GPRReg structureGPR = InvalidGPRReg;
1863     GPRTemporary scratch;
1864     GPRReg scratchGPR = InvalidGPRReg;
1865
1866     bool masqueradesAsUndefinedWatchpointValid =
1867         masqueradesAsUndefinedWatchpointIsStillValid();
1868
1869     if (!masqueradesAsUndefinedWatchpointValid) {
1870         // The masquerades as undefined case will use the structure register, so allocate it here.
1871         // Do this at the top of the function to avoid branching around a register allocation.
1872         GPRTemporary realStructure(this);
1873         GPRTemporary realScratch(this);
1874         structure.adopt(realStructure);
1875         scratch.adopt(realScratch);
1876         structureGPR = structure.gpr();
1877         scratchGPR = scratch.gpr();
1878     }
1879
1880     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1881     if (masqueradesAsUndefinedWatchpointValid) {
1882         DFG_TYPE_CHECK(
1883             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1884     } else {
1885         DFG_TYPE_CHECK(
1886             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1887
1888         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1889             m_jit.branchTest8(
1890                 MacroAssembler::Zero, 
1891                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1892                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1893
1894         m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
1895         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1896             m_jit.branchPtr(
1897                 MacroAssembler::Equal, 
1898                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1899                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1900
1901         isNotMasqueradesAsUndefined.link(&m_jit);
1902     }
1903     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1904     MacroAssembler::Jump done = m_jit.jump();
1905     
1906     notCell.link(&m_jit);
1907
1908     if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
1909         m_jit.move(valueGPR, resultGPR);
1910         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1911         typeCheck(
1912             JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
1913                 MacroAssembler::NotEqual, 
1914                 resultGPR, 
1915                 MacroAssembler::TrustedImm64(ValueNull)));
1916     }
1917     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1918     
1919     done.link(&m_jit);
1920     
1921     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1922 }
1923
1924 void SpeculativeJIT::compileLogicalNot(Node* node)
1925 {
1926     switch (node->child1().useKind()) {
1927     case ObjectOrOtherUse: {
1928         compileObjectOrOtherLogicalNot(node->child1());
1929         return;
1930     }
1931         
1932     case Int32Use: {
1933         SpeculateInt32Operand value(this, node->child1());
1934         GPRTemporary result(this, Reuse, value);
1935         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1936         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1937         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1938         return;
1939     }
1940         
1941     case DoubleRepUse: {
1942         SpeculateDoubleOperand value(this, node->child1());
1943         FPRTemporary scratch(this);
1944         GPRTemporary result(this);
1945         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1946         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1947         m_jit.xor32(TrustedImm32(true), result.gpr());
1948         nonZero.link(&m_jit);
1949         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1950         return;
1951     }
1952     
1953     case BooleanUse:
1954     case KnownBooleanUse: {
1955         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1956             SpeculateBooleanOperand value(this, node->child1());
1957             GPRTemporary result(this, Reuse, value);
1958             
1959             m_jit.move(value.gpr(), result.gpr());
1960             m_jit.xor64(TrustedImm32(true), result.gpr());
1961             
1962             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1963             return;
1964         }
1965         
1966         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1967         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1968         
1969         m_jit.move(value.gpr(), result.gpr());
1970         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1971         typeCheck(
1972             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1973                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1974         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1975         
1976         // If we add a DataFormatBool, we should use it here.
1977         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1978         return;
1979     }
1980         
1981     case UntypedUse: {
1982         JSValueOperand arg1(this, node->child1());
1983         GPRTemporary result(this);
1984     
1985         GPRReg arg1GPR = arg1.gpr();
1986         GPRReg resultGPR = result.gpr();
1987
1988         FPRTemporary valueFPR(this);
1989         FPRTemporary tempFPR(this);
1990
1991         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1992         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1993         std::optional<GPRTemporary> scratch;
1994         GPRReg scratchGPR = InvalidGPRReg;
1995         if (shouldCheckMasqueradesAsUndefined) {
1996             scratch.emplace(this);
1997             scratchGPR = scratch->gpr();
1998         }
1999         bool negateResult = true;
2000         m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
2001         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
2002         jsValueResult(resultGPR, node, DataFormatJSBoolean);
2003         return;
2004     }
2005     case StringUse:
2006         return compileStringZeroLength(node);
2007
2008     case StringOrOtherUse:
2009         return compileLogicalNotStringOrOther(node);
2010
2011     default:
2012         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2013         break;
2014     }
2015 }
2016
2017 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
2018 {
2019     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
2020     GPRTemporary scratch(this);
2021     GPRTemporary structure;
2022     GPRReg valueGPR = value.gpr();
2023     GPRReg scratchGPR = scratch.gpr();
2024     GPRReg structureGPR = InvalidGPRReg;
2025
2026     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
2027         GPRTemporary realStructure(this);
2028         structure.adopt(realStructure);
2029         structureGPR = structure.gpr();
2030     }
2031
2032     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
2033     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
2034         DFG_TYPE_CHECK(
2035             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
2036     } else {
2037         DFG_TYPE_CHECK(
2038             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
2039
2040         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
2041             JITCompiler::Zero, 
2042             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
2043             TrustedImm32(MasqueradesAsUndefined));
2044
2045         m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
2046         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
2047             m_jit.branchPtr(
2048                 MacroAssembler::Equal, 
2049                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
2050                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
2051
2052         isNotMasqueradesAsUndefined.link(&m_jit);
2053     }
2054     jump(taken, ForceJump);
2055     
2056     notCell.link(&m_jit);
2057     
2058     if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
2059         m_jit.move(valueGPR, scratchGPR);
2060         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2061         typeCheck(
2062             JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
2063                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2064     }
2065     jump(notTaken);
2066     
2067     noResult(m_currentNode);
2068 }
2069
2070 void SpeculativeJIT::emitBranch(Node* node)
2071 {
2072     BasicBlock* taken = node->branchData()->taken.block;
2073     BasicBlock* notTaken = node->branchData()->notTaken.block;
2074     
2075     switch (node->child1().useKind()) {
2076     case ObjectOrOtherUse: {
2077         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
2078         return;
2079     }
2080         
2081     case Int32Use:
2082     case DoubleRepUse: {
2083         if (node->child1().useKind() == Int32Use) {
2084             bool invert = false;
2085             
2086             if (taken == nextBlock()) {
2087                 invert = true;
2088                 BasicBlock* tmp = taken;
2089                 taken = notTaken;
2090                 notTaken = tmp;
2091             }
2092
2093             SpeculateInt32Operand value(this, node->child1());
2094             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2095         } else {
2096             SpeculateDoubleOperand value(this, node->child1());
2097             FPRTemporary scratch(this);
2098             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2099         }
2100         
2101         jump(notTaken);
2102         
2103         noResult(node);
2104         return;
2105     }
2106
2107     case StringUse: {
2108         emitStringBranch(node->child1(), taken, notTaken);
2109         return;
2110     }
2111
2112     case StringOrOtherUse: {
2113         emitStringOrOtherBranch(node->child1(), taken, notTaken);
2114         return;
2115     }
2116
2117     case UntypedUse:
2118     case BooleanUse:
2119     case KnownBooleanUse: {
2120         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2121         GPRReg valueGPR = value.gpr();
2122         
2123         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
2124             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
2125                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2126                 
2127                 if (taken == nextBlock()) {
2128                     condition = MacroAssembler::Zero;
2129                     BasicBlock* tmp = taken;
2130                     taken = notTaken;
2131                     notTaken = tmp;
2132                 }
2133                 
2134                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2135                 jump(notTaken);
2136             } else {
2137                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2138                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2139                 
2140                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
2141             }
2142             value.use();
2143         } else {
2144             GPRTemporary result(this);
2145             FPRTemporary fprValue(this);
2146             FPRTemporary fprTemp(this);
2147             std::optional<GPRTemporary> scratch;
2148
2149             GPRReg scratchGPR = InvalidGPRReg;
2150             bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
2151             if (shouldCheckMasqueradesAsUndefined) {
2152                 scratch.emplace(this);
2153                 scratchGPR = scratch->gpr();
2154             }
2155
2156             GPRReg resultGPR = result.gpr();
2157             FPRReg valueFPR = fprValue.fpr();
2158             FPRReg tempFPR = fprTemp.fpr();
2159             
2160             if (node->child1()->prediction() & SpecInt32Only) {
2161                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2162                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2163             }
2164     
2165             if (node->child1()->prediction() & SpecBoolean) {
2166                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2167                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2168             }
2169     
2170             value.use();
2171
2172             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
2173             m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
2174     
2175             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2176             jump(notTaken);
2177         }
2178         
2179         noResult(node, UseChildrenCalledExplicitly);
2180         return;
2181     }
2182         
2183     default:
2184         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
2185     }
2186 }
2187
2188 void SpeculativeJIT::compile(Node* node)
2189 {
2190     NodeType op = node->op();
2191     
2192 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
2193     m_jit.clearRegisterAllocationOffsets();
2194 #endif
2195
2196     switch (op) {
2197     case JSConstant:
2198     case DoubleConstant:
2199     case Int52Constant:
2200     case PhantomDirectArguments:
2201     case PhantomClonedArguments:
2202         initConstantInfo(node);
2203         break;
2204
2205     case LazyJSConstant:
2206         compileLazyJSConstant(node);
2207         break;
2208
2209     case Identity: {
2210         compileIdentity(node);
2211         break;
2212     }
2213
2214     case GetLocal: {
2215         AbstractValue& value = m_state.variables().operand(node->local());
2216
2217         // If the CFA is tracking this variable and it found that the variable
2218         // cannot have been assigned, then don't attempt to proceed.
2219         if (value.isClear()) {
2220             m_compileOkay = false;
2221             break;
2222         }
2223         
2224         switch (node->variableAccessData()->flushFormat()) {
2225         case FlushedDouble: {
2226             FPRTemporary result(this);
2227             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2228             VirtualRegister virtualRegister = node->virtualRegister();
2229             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2230             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2231             break;
2232         }
2233         
2234         case FlushedInt32: {
2235             GPRTemporary result(this);
2236             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2237             
2238             // Like int32Result, but don't useChildren - our children are phi nodes,
2239             // and don't represent values within this dataflow with virtual registers.
2240             VirtualRegister virtualRegister = node->virtualRegister();
2241             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2242             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2243             break;
2244         }
2245             
2246         case FlushedInt52: {
2247             GPRTemporary result(this);
2248             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2249             
2250             VirtualRegister virtualRegister = node->virtualRegister();
2251             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2252             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2253             break;
2254         }
2255             
2256         default:
2257             GPRTemporary result(this);
2258             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2259             
2260             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2261             // and don't represent values within this dataflow with virtual registers.
2262             VirtualRegister virtualRegister = node->virtualRegister();
2263             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2264             
2265             DataFormat format;
2266             if (isCellSpeculation(value.m_type))
2267                 format = DataFormatJSCell;
2268             else if (isBooleanSpeculation(value.m_type))
2269                 format = DataFormatJSBoolean;
2270             else
2271                 format = DataFormatJS;
2272             
2273             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2274             break;
2275         }
2276         break;
2277     }
2278
2279     case MovHint: {
2280         compileMovHint(m_currentNode);
2281         noResult(node);
2282         break;
2283     }
2284         
2285     case ZombieHint: {
2286         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2287         noResult(node);
2288         break;
2289     }
2290         
2291     case ExitOK: {
2292         noResult(node);
2293         break;
2294     }
2295         
2296     case SetLocal: {
2297         switch (node->variableAccessData()->flushFormat()) {
2298         case FlushedDouble: {
2299             SpeculateDoubleOperand value(this, node->child1());
2300             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2301             noResult(node);
2302             // Indicate that it's no longer necessary to retrieve the value of
2303             // this bytecode variable from registers or other locations in the stack,
2304             // but that it is stored as a double.
2305             recordSetLocal(DataFormatDouble);
2306             break;
2307         }
2308             
2309         case FlushedInt32: {
2310             SpeculateInt32Operand value(this, node->child1());
2311             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2312             noResult(node);
2313             recordSetLocal(DataFormatInt32);
2314             break;
2315         }
2316             
2317         case FlushedInt52: {
2318             SpeculateInt52Operand value(this, node->child1());
2319             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2320             noResult(node);
2321             recordSetLocal(DataFormatInt52);
2322             break;
2323         }
2324             
2325         case FlushedCell: {
2326             SpeculateCellOperand cell(this, node->child1());
2327             GPRReg cellGPR = cell.gpr();
2328             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2329             noResult(node);
2330             recordSetLocal(DataFormatCell);
2331             break;
2332         }
2333             
2334         case FlushedBoolean: {
2335             SpeculateBooleanOperand boolean(this, node->child1());
2336             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2337             noResult(node);
2338             recordSetLocal(DataFormatBoolean);
2339             break;
2340         }
2341             
2342         case FlushedJSValue: {
2343             JSValueOperand value(this, node->child1());
2344             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2345             noResult(node);
2346             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2347             break;
2348         }
2349             
2350         default:
2351             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2352             break;
2353         }
2354
2355         break;
2356     }
2357
2358     case SetArgument:
2359         // This is a no-op; it just marks the fact that the argument is being used.
2360         // But it may be profitable to use this as a hook to run speculation checks
2361         // on arguments, thereby allowing us to trivially eliminate such checks if
2362         // the argument is not used.
2363         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2364         break;
2365
2366     case BitAnd:
2367     case BitOr:
2368     case BitXor:
2369         compileBitwiseOp(node);
2370         break;
2371
2372     case BitRShift:
2373     case BitLShift:
2374     case BitURShift:
2375         compileShiftOp(node);
2376         break;
2377
2378     case UInt32ToNumber: {
2379         compileUInt32ToNumber(node);
2380         break;
2381     }
2382
2383     case DoubleAsInt32: {
2384         compileDoubleAsInt32(node);
2385         break;
2386     }
2387
2388     case ValueToInt32: {
2389         compileValueToInt32(node);
2390         break;
2391     }
2392         
2393     case DoubleRep: {
2394         compileDoubleRep(node);
2395         break;
2396     }
2397         
2398     case ValueRep: {
2399         compileValueRep(node);
2400         break;
2401     }
2402         
2403     case Int52Rep: {
2404         switch (node->child1().useKind()) {
2405         case Int32Use: {
2406             SpeculateInt32Operand operand(this, node->child1());
2407             GPRTemporary result(this, Reuse, operand);
2408             
2409             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2410             
2411             strictInt52Result(result.gpr(), node);
2412             break;
2413         }
2414             
2415         case AnyIntUse: {
2416             GPRTemporary result(this);
2417             GPRReg resultGPR = result.gpr();
2418             
2419             convertAnyInt(node->child1(), resultGPR);
2420             
2421             strictInt52Result(resultGPR, node);
2422             break;
2423         }
2424             
2425         case DoubleRepAnyIntUse: {
2426             SpeculateDoubleOperand value(this, node->child1());
2427             FPRReg valueFPR = value.fpr();
2428             
2429             flushRegisters();
2430             GPRFlushedCallResult result(this);
2431             GPRReg resultGPR = result.gpr();
2432             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2433             
2434             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2435                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2436                 m_jit.branch64(
2437                     JITCompiler::Equal, resultGPR,
2438                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2439             
2440             strictInt52Result(resultGPR, node);
2441             break;
2442         }
2443             
2444         default:
2445             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2446         }
2447         break;
2448     }
2449
2450     case ValueAdd:
2451         compileValueAdd(node);
2452         break;
2453
2454     case StrCat: {
2455         compileStrCat(node);
2456         break;
2457     }
2458
2459     case ArithAdd:
2460         compileArithAdd(node);
2461         break;
2462
2463     case ArithClz32:
2464         compileArithClz32(node);
2465         break;
2466         
2467     case MakeRope:
2468         compileMakeRope(node);
2469         break;
2470
2471     case ArithSub:
2472         compileArithSub(node);
2473         break;
2474
2475     case ArithNegate:
2476         compileArithNegate(node);
2477         break;
2478
2479     case ArithMul:
2480         compileArithMul(node);
2481         break;
2482
2483     case ArithDiv: {
2484         compileArithDiv(node);
2485         break;
2486     }
2487
2488     case ArithMod: {
2489         compileArithMod(node);
2490         break;
2491     }
2492
2493     case ArithAbs:
2494         compileArithAbs(node);
2495         break;
2496         
2497     case ArithMin:
2498     case ArithMax: {
2499         compileArithMinMax(node);
2500         break;
2501     }
2502
2503     case ArithPow:
2504         compileArithPow(node);
2505         break;
2506
2507     case ArithSqrt:
2508         compileArithSqrt(node);
2509         break;
2510
2511     case ArithFRound:
2512         compileArithFRound(node);
2513         break;
2514
2515     case ArithRandom:
2516         compileArithRandom(node);
2517         break;
2518
2519     case ArithRound:
2520     case ArithFloor:
2521     case ArithCeil:
2522     case ArithTrunc:
2523         compileArithRounding(node);
2524         break;
2525
2526     case ArithUnary:
2527         compileArithUnary(node);
2528         break;
2529
2530     case LogicalNot:
2531         compileLogicalNot(node);
2532         break;
2533
2534     case CompareLess:
2535         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2536             return;
2537         break;
2538
2539     case CompareLessEq:
2540         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2541             return;
2542         break;
2543
2544     case CompareGreater:
2545         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2546             return;
2547         break;
2548
2549     case CompareGreaterEq:
2550         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2551             return;
2552         break;
2553
2554     case CompareBelow:
2555         compileCompareUnsigned(node, JITCompiler::Below);
2556         break;
2557
2558     case CompareBelowEq:
2559         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2560         break;
2561
2562     case CompareEq:
2563         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2564             return;
2565         break;
2566
2567     case CompareStrictEq:
2568         if (compileStrictEq(node))
2569             return;
2570         break;
2571         
2572     case CompareEqPtr:
2573         compileCompareEqPtr(node);
2574         break;
2575
2576     case StringCharCodeAt: {
2577         compileGetCharCodeAt(node);
2578         break;
2579     }
2580
2581     case StringCharAt: {
2582         // Relies on StringCharAt node having same basic layout as GetByVal
2583         compileGetByValOnString(node);
2584         break;
2585     }
2586
2587     case StringFromCharCode: {
2588         compileFromCharCode(node);
2589         break;
2590     }
2591         
2592     case CheckArray: {
2593         checkArray(node);
2594         break;
2595     }
2596         
2597     case Arrayify:
2598     case ArrayifyToStructure: {
2599         arrayify(node);
2600         break;
2601     }
2602
2603     case GetByVal: {
2604         switch (node->arrayMode().type()) {
2605         case Array::SelectUsingPredictions:
2606         case Array::ForceExit:
2607             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2608             break;
2609         case Array::Undecided: {
2610             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2611             GPRTemporary result(this, Reuse, index);
2612             GPRReg indexGPR = index.gpr();
2613             GPRReg resultGPR = result.gpr();
2614
2615             speculationCheck(OutOfBounds, JSValueRegs(), node,
2616                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2617
2618             use(m_graph.varArgChild(node, 0));
2619             index.use();
2620
2621             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2622             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2623             break;
2624         }
2625         case Array::Generic: {
2626             if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2627                 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2628                     compileGetByValForObjectWithString(node);
2629                     break;
2630                 }
2631
2632                 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2633                     compileGetByValForObjectWithSymbol(node);
2634                     break;
2635                 }
2636             }
2637             JSValueOperand base(this, m_graph.varArgChild(node, 0));
2638             JSValueOperand property(this, m_graph.varArgChild(node, 1));
2639             GPRReg baseGPR = base.gpr();
2640             GPRReg propertyGPR = property.gpr();
2641             
2642             flushRegisters();
2643             GPRFlushedCallResult result(this);
2644             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2645             m_jit.exceptionCheck();
2646             
2647             jsValueResult(result.gpr(), node);
2648             break;
2649         }
2650         case Array::Int32:
2651         case Array::Contiguous: {
2652             if (node->arrayMode().isInBounds()) {
2653                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2654                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2655
2656                 GPRReg propertyReg = property.gpr();
2657                 GPRReg storageReg = storage.gpr();
2658
2659                 if (!m_compileOkay)
2660                     return;
2661                 
2662                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2663                 
2664                 GPRTemporary result(this);
2665
2666                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2667                 if (node->arrayMode().isSaneChain()) {
2668                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2669                     JITCompiler::Jump notHole = m_jit.branchTest64(
2670                         MacroAssembler::NonZero, result.gpr());
2671                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2672                     notHole.link(&m_jit);
2673                 } else {
2674                     speculationCheck(
2675                         LoadFromHole, JSValueRegs(), 0,
2676                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2677                 }
2678                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2679                 break;
2680             }
2681             
2682             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2683             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2684             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2685             
2686             GPRReg baseReg = base.gpr();
2687             GPRReg propertyReg = property.gpr();
2688             GPRReg storageReg = storage.gpr();
2689             
2690             if (!m_compileOkay)
2691                 return;
2692             
2693             GPRTemporary result(this);
2694             GPRReg resultReg = result.gpr();
2695             
2696             MacroAssembler::JumpList slowCases;
2697             
2698             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2699
2700             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2701             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2702             
2703             addSlowPathGenerator(
2704                 slowPathCall(
2705                     slowCases, this, operationGetByValObjectInt, GetPropertyPtrTag,
2706                     result.gpr(), baseReg, propertyReg));
2707             
2708             jsValueResult(resultReg, node);
2709             break;
2710         }
2711
2712         case Array::Double: {
2713             if (node->arrayMode().isInBounds()) {
2714                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2715                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2716
2717                 GPRReg propertyReg = property.gpr();
2718                 GPRReg storageReg = storage.gpr();
2719
2720                 if (!m_compileOkay)
2721                     return;
2722
2723                 FPRTemporary result(this);
2724                 FPRReg resultReg = result.fpr();
2725
2726                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2727
2728                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2729                 if (!node->arrayMode().isSaneChain())
2730                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, resultReg, resultReg));
2731                 doubleResult(resultReg, node);
2732                 break;
2733             }
2734
2735             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2736             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2737             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2738             
2739             GPRReg baseReg = base.gpr();
2740             GPRReg propertyReg = property.gpr();
2741             GPRReg storageReg = storage.gpr();
2742             
2743             if (!m_compileOkay)
2744                 return;
2745             
2746             GPRTemporary result(this);
2747             FPRTemporary temp(this);
2748             GPRReg resultReg = result.gpr();
2749             FPRReg tempReg = temp.fpr();
2750             
2751             MacroAssembler::JumpList slowCases;
2752             
2753             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2754
2755             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2756             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2757             boxDouble(tempReg, resultReg);
2758             
2759             addSlowPathGenerator(
2760                 slowPathCall(
2761                     slowCases, this, operationGetByValObjectInt, GetPropertyPtrTag,
2762                     result.gpr(), baseReg, propertyReg));
2763             
2764             jsValueResult(resultReg, node);
2765             break;
2766         }
2767
2768         case Array::ArrayStorage:
2769         case Array::SlowPutArrayStorage: {
2770             if (node->arrayMode().isInBounds()) {
2771                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2772                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2773             
2774                 GPRReg propertyReg = property.gpr();
2775                 GPRReg storageReg = storage.gpr();
2776             
2777                 if (!m_compileOkay)
2778                     return;
2779             
2780                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2781             
2782                 GPRTemporary result(this);
2783                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2784                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2785             
2786                 jsValueResult(result.gpr(), node);
2787                 break;
2788             }
2789
2790             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2791             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2792             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2793             
2794             GPRReg baseReg = base.gpr();
2795             GPRReg propertyReg = property.gpr();
2796             GPRReg storageReg = storage.gpr();
2797             
2798             if (!m_compileOkay)
2799                 return;
2800             
2801             GPRTemporary result(this);
2802             GPRReg resultReg = result.gpr();
2803             
2804             MacroAssembler::JumpList slowCases;
2805             
2806             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2807     
2808             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2809             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2810     
2811             addSlowPathGenerator(
2812                 slowPathCall(
2813                     slowCases, this, operationGetByValObjectInt, GetPropertyPtrTag,
2814                     result.gpr(), baseReg, propertyReg));
2815             
2816             jsValueResult(resultReg, node);
2817             break;
2818         }
2819         case Array::String:
2820             compileGetByValOnString(node);
2821             break;
2822         case Array::DirectArguments:
2823             compileGetByValOnDirectArguments(node);
2824             break;
2825         case Array::ScopedArguments:
2826             compileGetByValOnScopedArguments(node);
2827             break;
2828         default: {
2829             TypedArrayType type = node->arrayMode().typedArrayType();
2830             if (isInt(type))
2831                 compileGetByValOnIntTypedArray(node, type);
2832             else
2833                 compileGetByValOnFloatTypedArray(node, type);
2834         } }
2835         break;
2836     }
2837
2838     case GetByValWithThis: {
2839         compileGetByValWithThis(node);
2840         break;
2841     }
2842
2843     case PutByValDirect:
2844     case PutByVal:
2845     case PutByValAlias: {
2846         Edge child1 = m_jit.graph().varArgChild(node, 0);
2847         Edge child2 = m_jit.graph().varArgChild(node, 1);
2848         Edge child3 = m_jit.graph().varArgChild(node, 2);
2849         Edge child4 = m_jit.graph().varArgChild(node, 3);
2850         
2851         ArrayMode arrayMode = node->arrayMode().modeForPut();
2852         bool alreadyHandled = false;
2853         
2854         switch (arrayMode.type()) {
2855         case Array::SelectUsingPredictions:
2856         case Array::ForceExit:
2857             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2858             break;
2859         case Array::Generic: {
2860             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
2861
2862             if (child1.useKind() == CellUse) {
2863                 if (child2.useKind() == StringUse) {
2864                     compilePutByValForCellWithString(node, child1, child2, child3);
2865                     alreadyHandled = true;
2866                     break;
2867                 }
2868
2869                 if (child2.useKind() == SymbolUse) {
2870                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2871                     alreadyHandled = true;
2872                     break;
2873                 }
2874             }
2875             
2876             JSValueOperand arg1(this, child1);
2877             JSValueOperand arg2(this, child2);
2878             JSValueOperand arg3(this, child3);
2879             GPRReg arg1GPR = arg1.gpr();
2880             GPRReg arg2GPR = arg2.gpr();
2881             GPRReg arg3GPR = arg3.gpr();
2882             flushRegisters();
2883             if (node->op() == PutByValDirect)
2884                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2885             else
2886                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2887             m_jit.exceptionCheck();
2888             
2889             noResult(node);
2890             alreadyHandled = true;
2891             break;
2892         }
2893         default:
2894             break;
2895         }
2896         
2897         if (alreadyHandled)
2898             break;
2899
2900         SpeculateCellOperand base(this, child1);
2901         SpeculateStrictInt32Operand property(this, child2);
2902         
2903         GPRReg baseReg = base.gpr();
2904         GPRReg propertyReg = property.gpr();
2905
2906         switch (arrayMode.type()) {
2907         case Array::Int32:
2908         case Array::Contiguous: {
2909             JSValueOperand value(this, child3, ManualOperandSpeculation);
2910
2911             GPRReg valueReg = value.gpr();
2912         
2913             if (!m_compileOkay)
2914                 return;
2915             
2916             if (arrayMode.type() == Array::Int32) {
2917                 DFG_TYPE_CHECK(
2918                     JSValueRegs(valueReg), child3, SpecInt32Only,
2919                     m_jit.branch64(
2920                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2921             }
2922
2923             StorageOperand storage(this, child4);
2924             GPRReg storageReg = storage.gpr();
2925
2926             if (node->op() == PutByValAlias) {
2927                 // Store the value to the array.
2928                 GPRReg propertyReg = property.gpr();
2929                 GPRReg valueReg = value.gpr();
2930                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2931                 
2932                 noResult(node);
2933                 break;
2934             }
2935             
2936             GPRTemporary temporary;
2937             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2938
2939             MacroAssembler::Jump slowCase;
2940             
2941             if (arrayMode.isInBounds()) {
2942                 speculationCheck(
2943                     OutOfBounds, JSValueRegs(), 0,
2944                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2945             } else {
2946                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2947                 
2948                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2949                 
2950                 if (!arrayMode.isOutOfBounds())
2951                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2952                 
2953                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2954                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2955
2956                 inBounds.link(&m_jit);
2957             }
2958
2959             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2960
2961             base.use();
2962             property.use();
2963             value.use();
2964             storage.use();
2965             
2966             if (arrayMode.isOutOfBounds()) {
2967                 addSlowPathGenerator(slowPathCall(
2968                     slowCase, this,
2969                     m_jit.codeBlock()->isStrictMode()
2970                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2971                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2972                     PutPropertyPtrTag, NoResult, baseReg, propertyReg, valueReg));
2973             }
2974
2975             noResult(node, UseChildrenCalledExplicitly);
2976             break;
2977         }
2978             
2979         case Array::Double: {
2980             compileDoublePutByVal(node, base, property);
2981             break;
2982         }
2983             
2984         case Array::ArrayStorage:
2985         case Array::SlowPutArrayStorage: {
2986             JSValueOperand value(this, child3);
2987
2988             GPRReg valueReg = value.gpr();
2989         
2990             if (!m_compileOkay)
2991                 return;
2992
2993             StorageOperand storage(this, child4);
2994             GPRReg storageReg = storage.gpr();
2995
2996             if (node->op() == PutByValAlias) {
2997                 // Store the value to the array.
2998                 GPRReg propertyReg = property.gpr();
2999                 GPRReg valueReg = value.gpr();
3000                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3001                 
3002                 noResult(node);
3003                 break;
3004             }
3005             
3006             GPRTemporary temporary;
3007             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3008
3009             MacroAssembler::JumpList slowCases;
3010
3011             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3012             if (!arrayMode.isOutOfBounds())
3013                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3014             else
3015                 slowCases.append(beyondArrayBounds);
3016
3017             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3018             if (arrayMode.isInBounds()) {
3019                 speculationCheck(
3020                     StoreToHole, JSValueRegs(), 0,
3021                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
3022             } else {
3023                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3024                 if (arrayMode.isSlowPut()) {
3025                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3026                     // the above branch. But it's simply not worth it since this only happens if we're
3027                     // already having a bad time.
3028                     slowCases.append(m_jit.jump());
3029                 } else {
3030                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3031                 
3032                     // If we're writing to a hole we might be growing the array; 
3033                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3034                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3035                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3036                 
3037                     lengthDoesNotNeedUpdate.link(&m_jit);
3038                 }
3039                 notHoleValue.link(&m_jit);
3040             }
3041     
3042             // Store the value to the array.
3043             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3044
3045             base.use();
3046             property.use();
3047             value.use();
3048             storage.use();
3049             
3050             if (!slowCases.empty()) {
3051                 addSlowPathGenerator(slowPathCall(
3052                     slowCases, this,
3053                     m_jit.codeBlock()->isStrictMode()
3054                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
3055                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
3056                     PutPropertyPtrTag, NoResult, baseReg, propertyReg, valueReg));
3057             }
3058
3059             noResult(node, UseChildrenCalledExplicitly);
3060             break;
3061         }
3062             
3063         default: {
3064             TypedArrayType type = arrayMode.typedArrayType();
3065             if (isInt(type))
3066                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3067             else
3068                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3069         } }
3070
3071         break;
3072     }
3073         
3074     case AtomicsAdd:
3075     case AtomicsAnd:
3076     case AtomicsCompareExchange:
3077     case AtomicsExchange:
3078     case AtomicsLoad:
3079     case AtomicsOr:
3080     case AtomicsStore:
3081     case AtomicsSub:
3082     case AtomicsXor: {
3083         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
3084         Edge baseEdge = m_jit.graph().child(node, 0);
3085         Edge indexEdge = m_jit.graph().child(node, 1);
3086         Edge argEdges[maxNumExtraAtomicsArgs];
3087         for (unsigned i = numExtraArgs; i--;)
3088             argEdges[i] = m_jit.graph().child(node, 2 + i);
3089         Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
3090
3091         GPRReg baseGPR;
3092         GPRReg indexGPR;
3093         GPRReg argGPRs[2];
3094         GPRReg resultGPR;
3095
3096         auto callSlowPath = [&] () {
3097             switch (node->op()) {
3098             case AtomicsAdd:
3099                 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3100                 break;
3101             case AtomicsAnd:
3102                 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3103                 break;
3104             case AtomicsCompareExchange:
3105                 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
3106                 break;
3107             case AtomicsExchange:
3108                 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3109                 break;
3110             case AtomicsLoad:
3111                 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
3112                 break;
3113             case AtomicsOr:
3114                 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3115                 break;
3116             case AtomicsStore:
3117                 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3118                 break;
3119             case AtomicsSub:
3120                 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3121                 break;
3122             case AtomicsXor:
3123                 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3124                 break;
3125             default:
3126                 RELEASE_ASSERT_NOT_REACHED();
3127                 break;
3128             }
3129         };
3130         
3131         if (!storageEdge) {
3132             // We are in generic mode!
3133             JSValueOperand base(this, baseEdge);
3134             JSValueOperand index(this, indexEdge);
3135             std::optional<JSValueOperand> args[2];
3136             baseGPR = base.gpr();
3137             indexGPR = index.gpr();
3138             for (unsigned i = numExtraArgs; i--;) {
3139                 args[i].emplace(this, argEdges[i]);
3140                 argGPRs[i] = args[i]->gpr();
3141             }
3142             
3143             flushRegisters();
3144             GPRFlushedCallResult result(this);
3145             resultGPR = result.gpr();
3146             callSlowPath();
3147             m_jit.exceptionCheck();
3148             
3149             jsValueResult(resultGPR, node);
3150             break;
3151         }
3152         
3153         TypedArrayType type = node->arrayMode().typedArrayType();
3154         
3155         SpeculateCellOperand base(this, baseEdge);
3156         SpeculateStrictInt32Operand index(this, indexEdge);
3157
3158         baseGPR = base.gpr();
3159         indexGPR = index.gpr();
3160         
3161         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
3162         
3163         GPRTemporary args[2];
3164         
3165         JITCompiler::JumpList slowPathCases;
3166         
3167         bool ok = true;
3168         for (unsigned i = numExtraArgs; i--;) {
3169             if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
3170                 noResult(node);
3171                 ok = false;
3172             }
3173             argGPRs[i] = args[i].gpr();
3174         }
3175         if (!ok)
3176             break;
3177         
3178         StorageOperand storage(this, storageEdge);
3179         GPRTemporary oldValue(this);
3180         GPRTemporary result(this);
3181         GPRTemporary newValue(this);
3182         GPRReg storageGPR = storage.gpr();
3183         GPRReg oldValueGPR = oldValue.gpr();
3184         resultGPR = result.gpr();
3185         GPRReg newValueGPR = newValue.gpr();
3186         
3187         // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
3188         // https://bugs.webkit.org/show_bug.cgi?id=170974
3189         m_jit.nop();
3190         
3191         JITCompiler::Label loop = m_jit.label();
3192         
3193         loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
3194         m_jit.move(oldValueGPR, newValueGPR);
3195         m_jit.move(oldValueGPR, resultGPR);
3196         
3197         switch (node->op()) {
3198         case AtomicsAdd:
3199             m_jit.add32(argGPRs[0], newValueGPR);
3200             break;
3201         case AtomicsAnd:
3202             m_jit.and32(argGPRs[0], newValueGPR);
3203             break;
3204         case AtomicsCompareExchange: {
3205             switch (elementSize(type)) {
3206             case 1:
3207                 if (isSigned(type))
3208                     m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
3209                 else
3210                     m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
3211                 break;
3212             case 2:
3213                 if (isSigned(type))
3214                     m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3215                 else
3216                     m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3217                 break;
3218             case 4:
3219                 break;
3220             default:
3221                 RELEASE_ASSERT_NOT_REACHED();
3222                 break;
3223             }
3224             JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3225             m_jit.move(argGPRs[1], newValueGPR);
3226             fail.link(&m_jit);
3227             break;
3228         }
3229         case AtomicsExchange:
3230             m_jit.move(argGPRs[0], newValueGPR);
3231             break;
3232         case AtomicsLoad:
3233             break;
3234         case AtomicsOr:
3235             m_jit.or32(argGPRs[0], newValueGPR);
3236             break;
3237         case AtomicsStore:
3238             m_jit.move(argGPRs[0], newValueGPR);
3239             m_jit.move(argGPRs[0], resultGPR);
3240             break;
3241         case AtomicsSub:
3242             m_jit.sub32(argGPRs[0], newValueGPR);
3243             break;
3244         case AtomicsXor:
3245             m_jit.xor32(argGPRs[0], newValueGPR);
3246             break;
3247         default:
3248             RELEASE_ASSERT_NOT_REACHED();
3249             break;
3250         }
3251         
3252         JITCompiler::JumpList success;
3253         switch (elementSize(type)) {
3254         case 1:
3255             success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3256             break;
3257         case 2:
3258             success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3259             break;
3260         case 4:
3261             success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3262             break;
3263         default:
3264             RELEASE_ASSERT_NOT_REACHED();
3265             break;
3266         }
3267         m_jit.jump().linkTo(loop, &m_jit);
3268         
3269         if (!slowPathCases.empty()) {
3270             slowPathCases.link(&m_jit);
3271             silentSpillAllRegisters(resultGPR);
3272             // Since we spilled, we can do things to registers.
3273             m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3274             m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3275             for (unsigned i = numExtraArgs; i--;)
3276                 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3277             callSlowPath();
3278             silentFillAllRegisters();
3279             m_jit.exceptionCheck();
3280         }
3281         
3282         success.link(&m_jit);
3283         setIntTypedArrayLoadResult(node, resultGPR, type);
3284         break;
3285     }
3286         
3287     case AtomicsIsLockFree: {
3288         if (node->child1().useKind() != Int32Use) {
3289             JSValueOperand operand(this, node->child1());
3290             GPRReg operandGPR = operand.gpr();
3291             flushRegisters();
3292             GPRFlushedCallResult result(this);
3293             GPRReg resultGPR = result.gpr();
3294             callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3295             m_jit.exceptionCheck();
3296             jsValueResult(resultGPR, node);
3297             break;
3298         }
3299
3300         SpeculateInt32Operand operand(this, node->child1());
3301         GPRTemporary result(this);
3302         GPRReg operandGPR = operand.gpr();
3303         GPRReg resultGPR = result.gpr();
3304         m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3305         JITCompiler::JumpList done;
3306         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3307         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3308         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3309         m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3310         done.link(&m_jit);
3311         jsValueResult(resultGPR, node);
3312         break;
3313     }
3314
3315     case RegExpExec: {
3316         compileRegExpExec(node);
3317         break;
3318     }
3319
3320     case RegExpExecNonGlobalOrSticky: {
3321         compileRegExpExecNonGlobalOrSticky(node);
3322         break;
3323     }
3324
3325     case RegExpMatchFastGlobal: {
3326         compileRegExpMatchFastGlobal(node);
3327         break;
3328     }
3329
3330     case RegExpTest: {
3331         compileRegExpTest(node);
3332         break;
3333     }
3334
3335     case RegExpMatchFast: {
3336         compileRegExpMatchFast(node);
3337         break;
3338     }
3339
3340     case StringReplace:
3341     case StringReplaceRegExp: {
3342         compileStringReplace(node);
3343         break;
3344     }
3345         
3346     case GetRegExpObjectLastIndex: {
3347         compileGetRegExpObjectLastIndex(node);
3348         break;
3349     }
3350         
3351     case SetRegExpObjectLastIndex: {
3352         compileSetRegExpObjectLastIndex(node);
3353         break;
3354     }
3355
3356     case RecordRegExpCachedResult: {
3357         compileRecordRegExpCachedResult(node);
3358         break;
3359     }
3360         
3361     case ArrayPush: {
3362         compileArrayPush(node);
3363         break;
3364     }
3365
3366     case ArraySlice: {
3367         compileArraySlice(node);
3368         break;
3369     }
3370
3371     case ArrayIndexOf: {
3372         compileArrayIndexOf(node);
3373         break;
3374     }
3375         
3376     case ArrayPop: {
3377         ASSERT(node->arrayMode().isJSArray());
3378
3379         SpeculateCellOperand base(this, node->child1());
3380         StorageOperand storage(this, node->child2());
3381         GPRTemporary value(this);
3382         GPRTemporary storageLength(this);
3383         FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop().
3384         
3385         GPRReg baseGPR = base.gpr();
3386         GPRReg storageGPR = storage.gpr();
3387         GPRReg valueGPR = value.gpr();
3388         GPRReg storageLengthGPR = storageLength.gpr();
3389         FPRReg tempFPR = temp.fpr();
3390         
3391         switch (node->arrayMode().type()) {
3392         case Array::Int32:
3393         case Array::Double:
3394         case Array::Contiguous: {
3395             m_jit.load32(
3396                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3397             MacroAssembler::Jump undefinedCase =
3398                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3399             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3400             m_jit.store32(
3401                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3402             MacroAssembler::Jump slowCase;
3403             if (node->arrayMode().type() == Array::Double) {
3404                 m_jit.loadDouble(
3405                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3406                     tempFPR);
3407                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3408                 // length and the new length.
3409                 m_jit.store64(
3410                     MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3411                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3412                 boxDouble(tempFPR, valueGPR);
3413             } else {
3414                 m_jit.load64(
3415                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3416                     valueGPR);
3417                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3418                 // length and the new length.
3419                 m_jit.store64(
3420                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3421                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3422             }
3423
3424             addSlowPathGenerator(
3425                 slowPathMove(
3426                     undefinedCase, this,
3427                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3428             addSlowPathGenerator(
3429                 slowPathCall(
3430                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3431             
3432             // We can't know for sure that the result is an int because of the slow paths. :-/
3433             jsValueResult(valueGPR, node);
3434             break;
3435         }
3436             
3437         case Array::ArrayStorage: {
3438             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3439         
3440             JITCompiler::Jump undefinedCase =
3441                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3442         
3443             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3444         
3445             JITCompiler::JumpList slowCases;
3446             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3447         
3448             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3449             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3450         
3451             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3452         
3453             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight,  ArrayStorage::vectorOffset()));
3454             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3455         
3456             addSlowPathGenerator(
3457                 slowPathMove(
3458                     undefinedCase, this,
3459                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3460         
3461             addSlowPathGenerator(
3462                 slowPathCall(
3463                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3464
3465             jsValueResult(valueGPR, node);
3466             break;
3467         }
3468             
3469         default:
3470             CRASH();
3471             break;
3472         }
3473         break;
3474     }
3475
3476     case DFG::Jump: {
3477         jump(node->targetBlock());
3478         noResult(node);
3479         break;
3480     }
3481
3482     case Branch:
3483         emitBranch(node);
3484         break;
3485         
3486     case Switch:
3487         emitSwitch(node);
3488         break;
3489
3490     case Return: {
3491         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3492         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3493         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3494
3495         // Return the result in returnValueGPR.
3496         JSValueOperand op1(this, node->child1());
3497         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3498
3499         m_jit.emitRestoreCalleeSaves();
3500         m_jit.emitFunctionEpilogue();
3501         m_jit.ret();
3502         
3503         noResult(node);
3504         break;
3505     }
3506         
3507     case Throw: {
3508         compileThrow(node);
3509         break;
3510     }
3511
3512     case ThrowStaticError: {
3513         compileThrowStaticError(node);
3514         break;
3515     }
3516         
3517     case BooleanToNumber: {
3518         switch (node->child1().useKind()) {
3519         case BooleanUse: {
3520             JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3521             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3522             
3523             m_jit.move(value.gpr(), result.gpr());
3524             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3525             DFG_TYPE_CHECK(
3526                 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3527                     JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3528
3529             int32Result(result.gpr(), node);
3530             break;
3531         }
3532             
3533         case UntypedUse: {
3534             JSValueOperand value(this, node->child1());
3535             GPRTemporary result(this);
3536             
3537             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3538                 m_jit.move(value.gpr(), result.gpr());
3539                 m_jit.and32(TrustedImm32(1), result.gpr());
3540                 int32Result(result.gpr(), node);
3541                 break;
3542             }
3543             
3544             m_jit.move(value.gpr(), result.gpr());
3545             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3546             JITCompiler::Jump isBoolean = m_jit.branchTest64(
3547                 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3548             m_jit.move(value.gpr(), result.gpr());
3549             JITCompiler::Jump done = m_jit.jump();
3550             isBoolean.link(&m_jit);
3551             m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3552             done.link(&m_jit);
3553             
3554             jsValueResult(result.gpr(), node);
3555             break;
3556         }
3557             
3558         default:
3559             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3560             break;
3561         }
3562         break;
3563     }
3564         
3565     case ToPrimitive: {
3566         compileToPrimitive(node);
3567         break;
3568     }
3569
3570     case ToNumber: {
3571         JSValueOperand argument(this, node->child1());
3572         GPRTemporary result(this, Reuse, argument);
3573
3574         GPRReg argumentGPR = argument.gpr();
3575         GPRReg resultGPR = result.gpr();
3576
3577         argument.use();
3578
3579         // We have several attempts to remove ToNumber. But ToNumber still exists.
3580         // It means that converting non-numbers to numbers by this ToNumber is not rare.
3581         // Instead of the slow path generator, we emit callOperation here.
3582         if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3583             flushRegisters();
3584             callOperation(operationToNumber, resultGPR, argumentGPR);
3585             m_jit.exceptionCheck();
3586         } else {
3587             MacroAssembler::Jump notNumber = m_jit.branchIfNotNumber(argumentGPR);
3588             m_jit.move(argumentGPR, resultGPR);
3589             MacroAssembler::Jump done = m_jit.jump();
3590
3591             notNumber.link(&m_jit);
3592             silentSpillAllRegisters(resultGPR);
3593             callOperation(operationToNumber, resultGPR, argumentGPR);
3594             silentFillAllRegisters();
3595             m_jit.exceptionCheck();
3596
3597             done.link(&m_jit);
3598         }
3599
3600         jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3601         break;
3602     }
3603         
3604     case ToString:
3605     case CallStringConstructor: {
3606         compileToStringOrCallStringConstructor(node);
3607         break;
3608     }
3609         
3610     case NewStringObject: {
3611         compileNewStringObject(node);
3612         break;
3613     }
3614         
3615     case NewArray: {
3616         compileNewArray(node);
3617         break;
3618     }
3619
3620     case NewArrayWithSpread: {
3621         compileNewArrayWithSpread(node);
3622         break;
3623     }
3624
3625     case Spread: {
3626         compileSpread(node);
3627         break;
3628     }
3629         
3630     case NewArrayWithSize: {
3631         compileNewArrayWithSize(node);
3632         break;
3633     }
3634         
3635     case NewArrayBuffer: {
3636         compileNewArrayBuffer(node);
3637         break;
3638     }
3639         
3640     case NewTypedArray: {
3641         compileNewTypedArray(node);
3642         break;
3643     }
3644         
3645     case NewRegexp: {
3646         compileNewRegexp(node);
3647         break;
3648     }
3649
3650     case ToObject:
3651     case CallObjectConstructor: {
3652         compileToObjectOrCallObjectConstructor(node);
3653         break;
3654     }
3655
3656     case ToThis: {
3657         compileToThis(node);
3658         break;
3659     }
3660
3661     case CreateThis: {
3662         compileCreateThis(node);
3663         break;
3664     }
3665         
3666     case NewObject: {
3667         compileNewObject(node);
3668         break;
3669     }
3670
3671     case GetCallee: {
3672         compileGetCallee(node);
3673         break;
3674     }
3675         
3676     case GetArgumentCountIncludingThis: {
3677         compileGetArgumentCountIncludingThis(node);
3678         break;
3