[DFG] More aggressive removal of duplicate 32bit DFG code
[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, type == AccessType::Get ? operationGetByIdOptimize : operationTryGetByIdOptimize,
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,
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(), 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         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1092         returnFormat = DataFormatInt32;
1093         return allocate();
1094     }
1095
1096     VirtualRegister virtualRegister = edge->virtualRegister();
1097     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1098
1099     switch (info.registerFormat()) {
1100     case DataFormatNone: {
1101         GPRReg gpr = allocate();
1102
1103         if (edge->hasConstant()) {
1104             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1105             ASSERT(edge->isInt32Constant());
1106             m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
1107             info.fillInt32(*m_stream, gpr);
1108             returnFormat = DataFormatInt32;
1109             return gpr;
1110         }
1111         
1112         DataFormat spillFormat = info.spillFormat();
1113         
1114         DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32, spillFormat);
1115         
1116         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1117         
1118         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
1119             // If we know this was spilled as an integer we can fill without checking.
1120             if (strict) {
1121                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1122                 info.fillInt32(*m_stream, gpr);
1123                 returnFormat = DataFormatInt32;
1124                 return gpr;
1125             }
1126             if (spillFormat == DataFormatInt32) {
1127                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1128                 info.fillInt32(*m_stream, gpr);
1129                 returnFormat = DataFormatInt32;
1130             } else {
1131                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1132                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1133                 returnFormat = DataFormatJSInt32;
1134             }
1135             return gpr;
1136         }
1137         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1138
1139         // Fill as JSValue, and fall through.
1140         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1141         m_gprs.unlock(gpr);
1142         FALLTHROUGH;
1143     }
1144
1145     case DataFormatJS: {
1146         DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
1147         // Check the value is an integer.
1148         GPRReg gpr = info.gpr();
1149         m_gprs.lock(gpr);
1150         if (type & ~SpecInt32Only)
1151             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1152         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1153         // If !strict we're done, return.
1154         if (!strict) {
1155             returnFormat = DataFormatJSInt32;
1156             return gpr;
1157         }
1158         // else fall through & handle as DataFormatJSInt32.
1159         m_gprs.unlock(gpr);
1160         FALLTHROUGH;
1161     }
1162
1163     case DataFormatJSInt32: {
1164         // In a strict fill we need to strip off the value tag.
1165         if (strict) {
1166             GPRReg gpr = info.gpr();
1167             GPRReg result;
1168             // If the register has already been locked we need to take a copy.
1169             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
1170             if (m_gprs.isLocked(gpr))
1171                 result = allocate();
1172             else {
1173                 m_gprs.lock(gpr);
1174                 info.fillInt32(*m_stream, gpr);
1175                 result = gpr;
1176             }
1177             m_jit.zeroExtend32ToPtr(gpr, result);
1178             returnFormat = DataFormatInt32;
1179             return result;
1180         }
1181
1182         GPRReg gpr = info.gpr();
1183         m_gprs.lock(gpr);
1184         returnFormat = DataFormatJSInt32;
1185         return gpr;
1186     }
1187
1188     case DataFormatInt32: {
1189         GPRReg gpr = info.gpr();
1190         m_gprs.lock(gpr);
1191         returnFormat = DataFormatInt32;
1192         return gpr;
1193     }
1194         
1195     case DataFormatJSDouble:
1196     case DataFormatCell:
1197     case DataFormatBoolean:
1198     case DataFormatJSCell:
1199     case DataFormatJSBoolean:
1200     case DataFormatDouble:
1201     case DataFormatStorage:
1202     case DataFormatInt52:
1203     case DataFormatStrictInt52:
1204         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1205         
1206     default:
1207         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1208         return InvalidGPRReg;
1209     }
1210 }
1211 #if COMPILER(CLANG) && defined(__has_warning)
1212 #pragma clang diagnostic pop
1213 #endif
1214
1215 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1216 {
1217     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1218 }
1219
1220 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1221 {
1222     DataFormat mustBeDataFormatInt32;
1223     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1224     DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32, mustBeDataFormatInt32);
1225     return result;
1226 }
1227
1228 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1229 {
1230     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1231     AbstractValue& value = m_state.forNode(edge);
1232
1233     m_interpreter.filter(value, SpecAnyInt);
1234     if (value.isClear()) {
1235         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1236         return allocate();
1237     }
1238
1239     VirtualRegister virtualRegister = edge->virtualRegister();
1240     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1241
1242     switch (info.registerFormat()) {
1243     case DataFormatNone: {
1244         GPRReg gpr = allocate();
1245
1246         if (edge->hasConstant()) {
1247             JSValue jsValue = edge->asJSValue();
1248             ASSERT(jsValue.isAnyInt());
1249             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1250             int64_t value = jsValue.asAnyInt();
1251             if (desiredFormat == DataFormatInt52)
1252                 value = value << JSValue::int52ShiftAmount;
1253             m_jit.move(MacroAssembler::Imm64(value), gpr);
1254             info.fillGPR(*m_stream, gpr, desiredFormat);
1255             return gpr;
1256         }
1257         
1258         DataFormat spillFormat = info.spillFormat();
1259         
1260         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52, spillFormat);
1261         
1262         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1263         
1264         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1265         if (desiredFormat == DataFormatStrictInt52) {
1266             if (spillFormat == DataFormatInt52)
1267                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1268             info.fillStrictInt52(*m_stream, gpr);
1269             return gpr;
1270         }
1271         if (spillFormat == DataFormatStrictInt52)
1272             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1273         info.fillInt52(*m_stream, gpr);
1274         return gpr;
1275     }
1276
1277     case DataFormatStrictInt52: {
1278         GPRReg gpr = info.gpr();
1279         bool wasLocked = m_gprs.isLocked(gpr);
1280         lock(gpr);
1281         if (desiredFormat == DataFormatStrictInt52)
1282             return gpr;
1283         if (wasLocked) {
1284             GPRReg result = allocate();
1285             m_jit.move(gpr, result);
1286             unlock(gpr);
1287             gpr = result;
1288         } else
1289             info.fillInt52(*m_stream, gpr);
1290         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1291         return gpr;
1292     }
1293         
1294     case DataFormatInt52: {
1295         GPRReg gpr = info.gpr();
1296         bool wasLocked = m_gprs.isLocked(gpr);
1297         lock(gpr);
1298         if (desiredFormat == DataFormatInt52)
1299             return gpr;
1300         if (wasLocked) {
1301             GPRReg result = allocate();
1302             m_jit.move(gpr, result);
1303             unlock(gpr);
1304             gpr = result;
1305         } else
1306             info.fillStrictInt52(*m_stream, gpr);
1307         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1308         return gpr;
1309     }
1310
1311     default:
1312         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1313         return InvalidGPRReg;
1314     }
1315 }
1316
1317 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1318 {
1319     ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1320     ASSERT(edge->hasDoubleResult());
1321     VirtualRegister virtualRegister = edge->virtualRegister();
1322     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1323
1324     if (info.registerFormat() == DataFormatNone) {
1325         if (edge->hasConstant()) {
1326             if (edge->isNumberConstant()) {
1327                 FPRReg fpr = fprAllocate();
1328                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1329                 if (!doubleAsInt)
1330                     m_jit.moveZeroToDouble(fpr);
1331                 else {
1332                     GPRReg gpr = allocate();
1333                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1334                     m_jit.move64ToDouble(gpr, fpr);
1335                     unlock(gpr);
1336                 }
1337
1338                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1339                 info.fillDouble(*m_stream, fpr);
1340                 return fpr;
1341             }
1342             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1343             return fprAllocate();
1344         }
1345         
1346         DataFormat spillFormat = info.spillFormat();
1347         if (spillFormat != DataFormatDouble) {
1348             DFG_CRASH(
1349                 m_jit.graph(), m_currentNode, toCString(
1350                     "Expected ", edge, " to have double format but instead it is spilled as ",
1351                     dataFormatToString(spillFormat)).data());
1352         }
1353         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble, spillFormat);
1354         FPRReg fpr = fprAllocate();
1355         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1356         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1357         info.fillDouble(*m_stream, fpr);
1358         return fpr;
1359     }
1360
1361     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble, info.registerFormat());
1362     FPRReg fpr = info.fpr();
1363     m_fprs.lock(fpr);
1364     return fpr;
1365 }
1366
1367 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1368 {
1369     AbstractValue& value = m_state.forNode(edge);
1370     SpeculatedType type = value.m_type;
1371     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCellCheck));
1372
1373     m_interpreter.filter(value, SpecCellCheck);
1374     if (value.isClear()) {
1375         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1376         return allocate();
1377     }
1378
1379     VirtualRegister virtualRegister = edge->virtualRegister();
1380     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1381
1382     switch (info.registerFormat()) {
1383     case DataFormatNone: {
1384         GPRReg gpr = allocate();
1385
1386         if (edge->hasConstant()) {
1387             JSValue jsValue = edge->asJSValue();
1388             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1389             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1390             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1391             return gpr;
1392         }
1393
1394         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1395         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1396
1397         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1398         if (type & ~SpecCellCheck)
1399             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1400         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1401         return gpr;
1402     }
1403
1404     case DataFormatCell:
1405     case DataFormatJSCell: {
1406         GPRReg gpr = info.gpr();
1407         m_gprs.lock(gpr);
1408         if (!ASSERT_DISABLED) {
1409             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1410             m_jit.abortWithReason(DFGIsNotCell);
1411             checkCell.link(&m_jit);
1412         }
1413         return gpr;
1414     }
1415
1416     case DataFormatJS: {
1417         GPRReg gpr = info.gpr();
1418         m_gprs.lock(gpr);
1419         if (type & ~SpecCellCheck)
1420             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1421         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1422         return gpr;
1423     }
1424
1425     case DataFormatJSInt32:
1426     case DataFormatInt32:
1427     case DataFormatJSDouble:
1428     case DataFormatJSBoolean:
1429     case DataFormatBoolean:
1430     case DataFormatDouble:
1431     case DataFormatStorage:
1432     case DataFormatInt52:
1433     case DataFormatStrictInt52:
1434         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1435         
1436     default:
1437         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1438         return InvalidGPRReg;
1439     }
1440 }
1441
1442 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1443 {
1444     AbstractValue& value = m_state.forNode(edge);
1445     SpeculatedType type = value.m_type;
1446     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1447
1448     m_interpreter.filter(value, SpecBoolean);
1449     if (value.isClear()) {
1450         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1451         return allocate();
1452     }
1453
1454     VirtualRegister virtualRegister = edge->virtualRegister();
1455     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1456
1457     switch (info.registerFormat()) {
1458     case DataFormatNone: {
1459         GPRReg gpr = allocate();
1460
1461         if (edge->hasConstant()) {
1462             JSValue jsValue = edge->asJSValue();
1463             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1464             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1465             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1466             return gpr;
1467         }
1468         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS, info.spillFormat());
1469         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1470         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1471
1472         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1473         if (type & ~SpecBoolean) {
1474             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1475             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1476             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1477         }
1478         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1479         return gpr;
1480     }
1481
1482     case DataFormatBoolean:
1483     case DataFormatJSBoolean: {
1484         GPRReg gpr = info.gpr();
1485         m_gprs.lock(gpr);
1486         return gpr;
1487     }
1488
1489     case DataFormatJS: {
1490         GPRReg gpr = info.gpr();
1491         m_gprs.lock(gpr);
1492         if (type & ~SpecBoolean) {
1493             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1494             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1495             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1496         }
1497         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1498         return gpr;
1499     }
1500
1501     case DataFormatJSInt32:
1502     case DataFormatInt32:
1503     case DataFormatJSDouble:
1504     case DataFormatJSCell:
1505     case DataFormatCell:
1506     case DataFormatDouble:
1507     case DataFormatStorage:
1508     case DataFormatInt52:
1509     case DataFormatStrictInt52:
1510         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1511         
1512     default:
1513         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1514         return InvalidGPRReg;
1515     }
1516 }
1517
1518 void SpeculativeJIT::compileObjectEquality(Node* node)
1519 {
1520     SpeculateCellOperand op1(this, node->child1());
1521     SpeculateCellOperand op2(this, node->child2());
1522     GPRTemporary result(this, Reuse, op1);
1523     
1524     GPRReg op1GPR = op1.gpr();
1525     GPRReg op2GPR = op2.gpr();
1526     GPRReg resultGPR = result.gpr();
1527    
1528     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1529         DFG_TYPE_CHECK(
1530             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1531         DFG_TYPE_CHECK(
1532             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1533     } else {
1534         DFG_TYPE_CHECK(
1535             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1536         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1537             m_jit.branchTest8(
1538                 MacroAssembler::NonZero, 
1539                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1540                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1541
1542         DFG_TYPE_CHECK(
1543             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1544         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1545             m_jit.branchTest8(
1546                 MacroAssembler::NonZero, 
1547                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1548                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1549     }
1550
1551     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1552     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1553     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1554 }
1555
1556 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1557 {
1558     SpeculateCellOperand op1(this, objectChild);
1559     JSValueOperand op2(this, otherChild);
1560     GPRTemporary result(this);
1561
1562     GPRReg op1GPR = op1.gpr();
1563     GPRReg op2GPR = op2.gpr();
1564     GPRReg resultGPR = result.gpr();
1565
1566     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1567
1568     // At this point we know that we can perform a straight-forward equality comparison on pointer
1569     // values because we are doing strict equality.
1570     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1571     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1572     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1573 }
1574     
1575 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1576 {
1577     BasicBlock* taken = branchNode->branchData()->taken.block;
1578     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1579     
1580     SpeculateCellOperand op1(this, objectChild);
1581     JSValueOperand op2(this, otherChild);
1582     
1583     GPRReg op1GPR = op1.gpr();
1584     GPRReg op2GPR = op2.gpr();
1585     
1586     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1587
1588     if (taken == nextBlock()) {
1589         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1590         jump(taken);
1591     } else {
1592         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1593         jump(notTaken);
1594     }
1595 }
1596
1597 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1598 {
1599     SpeculateCellOperand op1(this, leftChild);
1600     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1601     GPRTemporary result(this);
1602     
1603     GPRReg op1GPR = op1.gpr();
1604     GPRReg op2GPR = op2.gpr();
1605     GPRReg resultGPR = result.gpr();
1606
1607     bool masqueradesAsUndefinedWatchpointValid =
1608         masqueradesAsUndefinedWatchpointIsStillValid();
1609
1610     if (masqueradesAsUndefinedWatchpointValid) {
1611         DFG_TYPE_CHECK(
1612             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1613     } else {
1614         DFG_TYPE_CHECK(
1615             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1616         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1617             m_jit.branchTest8(
1618                 MacroAssembler::NonZero, 
1619                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1620                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1621     }
1622     
1623     // It seems that most of the time when programs do a == b where b may be either null/undefined
1624     // or an object, b is usually an object. Balance the branches to make that case fast.
1625     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1626     
1627     // We know that within this branch, rightChild must be a cell. 
1628     if (masqueradesAsUndefinedWatchpointValid) {
1629         DFG_TYPE_CHECK(
1630             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1631     } else {
1632         DFG_TYPE_CHECK(
1633             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1634         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1635             m_jit.branchTest8(
1636                 MacroAssembler::NonZero, 
1637                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1638                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1639     }
1640     
1641     // At this point we know that we can perform a straight-forward equality comparison on pointer
1642     // values because both left and right are pointers to objects that have no special equality
1643     // protocols.
1644     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1645     MacroAssembler::Jump done = m_jit.jump();
1646     
1647     rightNotCell.link(&m_jit);
1648     
1649     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1650     // prove that it is either null or undefined.
1651     if (needsTypeCheck(rightChild, SpecCellCheck | SpecOther)) {
1652         m_jit.move(op2GPR, resultGPR);
1653         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1654         
1655         typeCheck(
1656             JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther,
1657             m_jit.branch64(
1658                 MacroAssembler::NotEqual, resultGPR,
1659                 MacroAssembler::TrustedImm64(ValueNull)));
1660     }
1661     m_jit.move(TrustedImm32(0), result.gpr());
1662
1663     done.link(&m_jit);
1664     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1665     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1666 }
1667
1668 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1669 {
1670     BasicBlock* taken = branchNode->branchData()->taken.block;
1671     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1672     
1673     SpeculateCellOperand op1(this, leftChild);
1674     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1675     GPRTemporary result(this);
1676     
1677     GPRReg op1GPR = op1.gpr();
1678     GPRReg op2GPR = op2.gpr();
1679     GPRReg resultGPR = result.gpr();
1680     
1681     bool masqueradesAsUndefinedWatchpointValid = 
1682         masqueradesAsUndefinedWatchpointIsStillValid();
1683
1684     if (masqueradesAsUndefinedWatchpointValid) {
1685         DFG_TYPE_CHECK(
1686             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1687     } else {
1688         DFG_TYPE_CHECK(
1689             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1690         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1691             m_jit.branchTest8(
1692                 MacroAssembler::NonZero, 
1693                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1694                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1695     }
1696
1697     // It seems that most of the time when programs do a == b where b may be either null/undefined
1698     // or an object, b is usually an object. Balance the branches to make that case fast.
1699     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1700     
1701     // We know that within this branch, rightChild must be a cell. 
1702     if (masqueradesAsUndefinedWatchpointValid) {
1703         DFG_TYPE_CHECK(
1704             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1705     } else {
1706         DFG_TYPE_CHECK(
1707             JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1708         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1709             m_jit.branchTest8(
1710                 MacroAssembler::NonZero, 
1711                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1712                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1713     }
1714     
1715     // At this point we know that we can perform a straight-forward equality comparison on pointer
1716     // values because both left and right are pointers to objects that have no special equality
1717     // protocols.
1718     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1719     
1720     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1721     // prove that it is either null or undefined.
1722     if (!needsTypeCheck(rightChild, SpecCellCheck | SpecOther))
1723         rightNotCell.link(&m_jit);
1724     else {
1725         jump(notTaken, ForceJump);
1726         
1727         rightNotCell.link(&m_jit);
1728         m_jit.move(op2GPR, resultGPR);
1729         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1730         
1731         typeCheck(
1732             JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther, m_jit.branch64(
1733                 MacroAssembler::NotEqual, resultGPR,
1734                 MacroAssembler::TrustedImm64(ValueNull)));
1735     }
1736     
1737     jump(notTaken);
1738 }
1739
1740 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1741 {
1742     SpeculateCellOperand symbol(this, symbolEdge);
1743     JSValueOperand untyped(this, untypedEdge);
1744     GPRTemporary result(this, Reuse, symbol, untyped);
1745
1746     GPRReg symbolGPR = symbol.gpr();
1747     GPRReg untypedGPR = untyped.gpr();
1748     GPRReg resultGPR = result.gpr();
1749
1750     speculateSymbol(symbolEdge, symbolGPR);
1751
1752     // At this point we know that we can perform a straight-forward equality comparison on pointer
1753     // values because we are doing strict equality.
1754     m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
1755     unblessedBooleanResult(resultGPR, node);
1756 }
1757
1758 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1759 {
1760     if (node->child1()->isInt32Constant()) {
1761         SpeculateInt32Operand op2(this, node->child2());
1762         GPRTemporary result(this, Reuse, op2);
1763         int32_t imm = node->child1()->asInt32();
1764         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1765
1766         // If we add a DataFormatBool, we should use it here.
1767         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1768         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1769     } else if (node->child2()->isInt32Constant()) {
1770         SpeculateInt32Operand op1(this, node->child1());
1771         GPRTemporary result(this, Reuse, op1);
1772         int32_t imm = node->child2()->asInt32();
1773         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1774
1775         // If we add a DataFormatBool, we should use it here.
1776         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1777         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1778     } else {
1779         SpeculateInt32Operand op1(this, node->child1());
1780         SpeculateInt32Operand op2(this, node->child2());
1781         GPRTemporary result(this, Reuse, op1, op2);
1782         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1783
1784         // If we add a DataFormatBool, we should use it here.
1785         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1786         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1787     }
1788 }
1789
1790 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1791 {
1792     SpeculateWhicheverInt52Operand op1(this, node->child1());
1793     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1794     GPRTemporary result(this, Reuse, op1, op2);
1795     
1796     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1797     
1798     // If we add a DataFormatBool, we should use it here.
1799     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1800     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1801 }
1802
1803 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1804 {
1805     BasicBlock* taken = branchNode->branchData()->taken.block;
1806     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1807
1808     // The branch instruction will branch to the taken block.
1809     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1810     if (taken == nextBlock()) {
1811         condition = JITCompiler::invert(condition);
1812         BasicBlock* tmp = taken;
1813         taken = notTaken;
1814         notTaken = tmp;
1815     }
1816     
1817     SpeculateWhicheverInt52Operand op1(this, node->child1());
1818     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1819     
1820     branch64(condition, op1.gpr(), op2.gpr(), taken);
1821     jump(notTaken);
1822 }
1823
1824 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1825 {
1826     SpeculateDoubleOperand op1(this, node->child1());
1827     SpeculateDoubleOperand op2(this, node->child2());
1828     GPRTemporary result(this);
1829     
1830     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1831     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1832     m_jit.xor64(TrustedImm32(true), result.gpr());
1833     trueCase.link(&m_jit);
1834     
1835     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1836 }
1837
1838 void SpeculativeJIT::compileCompareEqPtr(Node* node)
1839 {
1840     JSValueOperand value(this, node->child1());
1841     GPRTemporary result(this);
1842     GPRReg valueGPR = value.gpr();
1843     GPRReg resultGPR = result.gpr();
1844
1845     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), node->cellOperand()->cell()), resultGPR);
1846     m_jit.compare64(MacroAssembler::Equal, valueGPR, resultGPR, resultGPR);
1847     unblessedBooleanResult(resultGPR, node);
1848 }
1849
1850 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1851 {
1852     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1853     GPRTemporary result(this);
1854     GPRReg valueGPR = value.gpr();
1855     GPRReg resultGPR = result.gpr();
1856     GPRTemporary structure;
1857     GPRReg structureGPR = InvalidGPRReg;
1858     GPRTemporary scratch;
1859     GPRReg scratchGPR = InvalidGPRReg;
1860
1861     bool masqueradesAsUndefinedWatchpointValid =
1862         masqueradesAsUndefinedWatchpointIsStillValid();
1863
1864     if (!masqueradesAsUndefinedWatchpointValid) {
1865         // The masquerades as undefined case will use the structure register, so allocate it here.
1866         // Do this at the top of the function to avoid branching around a register allocation.
1867         GPRTemporary realStructure(this);
1868         GPRTemporary realScratch(this);
1869         structure.adopt(realStructure);
1870         scratch.adopt(realScratch);
1871         structureGPR = structure.gpr();
1872         scratchGPR = scratch.gpr();
1873     }
1874
1875     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1876     if (masqueradesAsUndefinedWatchpointValid) {
1877         DFG_TYPE_CHECK(
1878             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1879     } else {
1880         DFG_TYPE_CHECK(
1881             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1882
1883         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1884             m_jit.branchTest8(
1885                 MacroAssembler::Zero, 
1886                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1887                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1888
1889         m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
1890         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1891             m_jit.branchPtr(
1892                 MacroAssembler::Equal, 
1893                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1894                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1895
1896         isNotMasqueradesAsUndefined.link(&m_jit);
1897     }
1898     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1899     MacroAssembler::Jump done = m_jit.jump();
1900     
1901     notCell.link(&m_jit);
1902
1903     if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
1904         m_jit.move(valueGPR, resultGPR);
1905         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1906         typeCheck(
1907             JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
1908                 MacroAssembler::NotEqual, 
1909                 resultGPR, 
1910                 MacroAssembler::TrustedImm64(ValueNull)));
1911     }
1912     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1913     
1914     done.link(&m_jit);
1915     
1916     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1917 }
1918
1919 void SpeculativeJIT::compileLogicalNot(Node* node)
1920 {
1921     switch (node->child1().useKind()) {
1922     case ObjectOrOtherUse: {
1923         compileObjectOrOtherLogicalNot(node->child1());
1924         return;
1925     }
1926         
1927     case Int32Use: {
1928         SpeculateInt32Operand value(this, node->child1());
1929         GPRTemporary result(this, Reuse, value);
1930         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1931         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1932         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1933         return;
1934     }
1935         
1936     case DoubleRepUse: {
1937         SpeculateDoubleOperand value(this, node->child1());
1938         FPRTemporary scratch(this);
1939         GPRTemporary result(this);
1940         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1941         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1942         m_jit.xor32(TrustedImm32(true), result.gpr());
1943         nonZero.link(&m_jit);
1944         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1945         return;
1946     }
1947     
1948     case BooleanUse:
1949     case KnownBooleanUse: {
1950         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1951             SpeculateBooleanOperand value(this, node->child1());
1952             GPRTemporary result(this, Reuse, value);
1953             
1954             m_jit.move(value.gpr(), result.gpr());
1955             m_jit.xor64(TrustedImm32(true), result.gpr());
1956             
1957             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1958             return;
1959         }
1960         
1961         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1962         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1963         
1964         m_jit.move(value.gpr(), result.gpr());
1965         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1966         typeCheck(
1967             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1968                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1969         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1970         
1971         // If we add a DataFormatBool, we should use it here.
1972         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1973         return;
1974     }
1975         
1976     case UntypedUse: {
1977         JSValueOperand arg1(this, node->child1());
1978         GPRTemporary result(this);
1979     
1980         GPRReg arg1GPR = arg1.gpr();
1981         GPRReg resultGPR = result.gpr();
1982
1983         FPRTemporary valueFPR(this);
1984         FPRTemporary tempFPR(this);
1985
1986         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1987         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1988         std::optional<GPRTemporary> scratch;
1989         GPRReg scratchGPR = InvalidGPRReg;
1990         if (shouldCheckMasqueradesAsUndefined) {
1991             scratch.emplace(this);
1992             scratchGPR = scratch->gpr();
1993         }
1994         bool negateResult = true;
1995         m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1996         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1997         jsValueResult(resultGPR, node, DataFormatJSBoolean);
1998         return;
1999     }
2000     case StringUse:
2001         return compileStringZeroLength(node);
2002
2003     case StringOrOtherUse:
2004         return compileLogicalNotStringOrOther(node);
2005
2006     default:
2007         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2008         break;
2009     }
2010 }
2011
2012 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
2013 {
2014     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
2015     GPRTemporary scratch(this);
2016     GPRTemporary structure;
2017     GPRReg valueGPR = value.gpr();
2018     GPRReg scratchGPR = scratch.gpr();
2019     GPRReg structureGPR = InvalidGPRReg;
2020
2021     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
2022         GPRTemporary realStructure(this);
2023         structure.adopt(realStructure);
2024         structureGPR = structure.gpr();
2025     }
2026
2027     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
2028     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
2029         DFG_TYPE_CHECK(
2030             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
2031     } else {
2032         DFG_TYPE_CHECK(
2033             JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
2034
2035         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
2036             JITCompiler::Zero, 
2037             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
2038             TrustedImm32(MasqueradesAsUndefined));
2039
2040         m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
2041         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
2042             m_jit.branchPtr(
2043                 MacroAssembler::Equal, 
2044                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
2045                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
2046
2047         isNotMasqueradesAsUndefined.link(&m_jit);
2048     }
2049     jump(taken, ForceJump);
2050     
2051     notCell.link(&m_jit);
2052     
2053     if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
2054         m_jit.move(valueGPR, scratchGPR);
2055         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2056         typeCheck(
2057             JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
2058                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2059     }
2060     jump(notTaken);
2061     
2062     noResult(m_currentNode);
2063 }
2064
2065 void SpeculativeJIT::emitBranch(Node* node)
2066 {
2067     BasicBlock* taken = node->branchData()->taken.block;
2068     BasicBlock* notTaken = node->branchData()->notTaken.block;
2069     
2070     switch (node->child1().useKind()) {
2071     case ObjectOrOtherUse: {
2072         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
2073         return;
2074     }
2075         
2076     case Int32Use:
2077     case DoubleRepUse: {
2078         if (node->child1().useKind() == Int32Use) {
2079             bool invert = false;
2080             
2081             if (taken == nextBlock()) {
2082                 invert = true;
2083                 BasicBlock* tmp = taken;
2084                 taken = notTaken;
2085                 notTaken = tmp;
2086             }
2087
2088             SpeculateInt32Operand value(this, node->child1());
2089             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2090         } else {
2091             SpeculateDoubleOperand value(this, node->child1());
2092             FPRTemporary scratch(this);
2093             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2094         }
2095         
2096         jump(notTaken);
2097         
2098         noResult(node);
2099         return;
2100     }
2101
2102     case StringUse: {
2103         emitStringBranch(node->child1(), taken, notTaken);
2104         return;
2105     }
2106
2107     case StringOrOtherUse: {
2108         emitStringOrOtherBranch(node->child1(), taken, notTaken);
2109         return;
2110     }
2111
2112     case UntypedUse:
2113     case BooleanUse:
2114     case KnownBooleanUse: {
2115         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2116         GPRReg valueGPR = value.gpr();
2117         
2118         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
2119             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
2120                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2121                 
2122                 if (taken == nextBlock()) {
2123                     condition = MacroAssembler::Zero;
2124                     BasicBlock* tmp = taken;
2125                     taken = notTaken;
2126                     notTaken = tmp;
2127                 }
2128                 
2129                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2130                 jump(notTaken);
2131             } else {
2132                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2133                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2134                 
2135                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
2136             }
2137             value.use();
2138         } else {
2139             GPRTemporary result(this);
2140             FPRTemporary fprValue(this);
2141             FPRTemporary fprTemp(this);
2142             std::optional<GPRTemporary> scratch;
2143
2144             GPRReg scratchGPR = InvalidGPRReg;
2145             bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
2146             if (shouldCheckMasqueradesAsUndefined) {
2147                 scratch.emplace(this);
2148                 scratchGPR = scratch->gpr();
2149             }
2150
2151             GPRReg resultGPR = result.gpr();
2152             FPRReg valueFPR = fprValue.fpr();
2153             FPRReg tempFPR = fprTemp.fpr();
2154             
2155             if (node->child1()->prediction() & SpecInt32Only) {
2156                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2157                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2158             }
2159     
2160             if (node->child1()->prediction() & SpecBoolean) {
2161                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2162                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2163             }
2164     
2165             value.use();
2166
2167             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
2168             m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
2169     
2170             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2171             jump(notTaken);
2172         }
2173         
2174         noResult(node, UseChildrenCalledExplicitly);
2175         return;
2176     }
2177         
2178     default:
2179         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
2180     }
2181 }
2182
2183 void SpeculativeJIT::compile(Node* node)
2184 {
2185     NodeType op = node->op();
2186     
2187 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
2188     m_jit.clearRegisterAllocationOffsets();
2189 #endif
2190
2191     switch (op) {
2192     case JSConstant:
2193     case DoubleConstant:
2194     case Int52Constant:
2195     case PhantomDirectArguments:
2196     case PhantomClonedArguments:
2197         initConstantInfo(node);
2198         break;
2199
2200     case LazyJSConstant:
2201         compileLazyJSConstant(node);
2202         break;
2203
2204     case Identity: {
2205         compileIdentity(node);
2206         break;
2207     }
2208
2209     case GetLocal: {
2210         AbstractValue& value = m_state.variables().operand(node->local());
2211
2212         // If the CFA is tracking this variable and it found that the variable
2213         // cannot have been assigned, then don't attempt to proceed.
2214         if (value.isClear()) {
2215             m_compileOkay = false;
2216             break;
2217         }
2218         
2219         switch (node->variableAccessData()->flushFormat()) {
2220         case FlushedDouble: {
2221             FPRTemporary result(this);
2222             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2223             VirtualRegister virtualRegister = node->virtualRegister();
2224             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2225             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2226             break;
2227         }
2228         
2229         case FlushedInt32: {
2230             GPRTemporary result(this);
2231             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2232             
2233             // Like int32Result, but don't useChildren - our children are phi nodes,
2234             // and don't represent values within this dataflow with virtual registers.
2235             VirtualRegister virtualRegister = node->virtualRegister();
2236             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2237             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2238             break;
2239         }
2240             
2241         case FlushedInt52: {
2242             GPRTemporary result(this);
2243             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2244             
2245             VirtualRegister virtualRegister = node->virtualRegister();
2246             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2247             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2248             break;
2249         }
2250             
2251         default:
2252             GPRTemporary result(this);
2253             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2254             
2255             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2256             // and don't represent values within this dataflow with virtual registers.
2257             VirtualRegister virtualRegister = node->virtualRegister();
2258             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2259             
2260             DataFormat format;
2261             if (isCellSpeculation(value.m_type))
2262                 format = DataFormatJSCell;
2263             else if (isBooleanSpeculation(value.m_type))
2264                 format = DataFormatJSBoolean;
2265             else
2266                 format = DataFormatJS;
2267             
2268             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2269             break;
2270         }
2271         break;
2272     }
2273
2274     case MovHint: {
2275         compileMovHint(m_currentNode);
2276         noResult(node);
2277         break;
2278     }
2279         
2280     case ZombieHint: {
2281         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2282         noResult(node);
2283         break;
2284     }
2285         
2286     case ExitOK: {
2287         noResult(node);
2288         break;
2289     }
2290         
2291     case SetLocal: {
2292         switch (node->variableAccessData()->flushFormat()) {
2293         case FlushedDouble: {
2294             SpeculateDoubleOperand value(this, node->child1());
2295             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2296             noResult(node);
2297             // Indicate that it's no longer necessary to retrieve the value of
2298             // this bytecode variable from registers or other locations in the stack,
2299             // but that it is stored as a double.
2300             recordSetLocal(DataFormatDouble);
2301             break;
2302         }
2303             
2304         case FlushedInt32: {
2305             SpeculateInt32Operand value(this, node->child1());
2306             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2307             noResult(node);
2308             recordSetLocal(DataFormatInt32);
2309             break;
2310         }
2311             
2312         case FlushedInt52: {
2313             SpeculateInt52Operand value(this, node->child1());
2314             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2315             noResult(node);
2316             recordSetLocal(DataFormatInt52);
2317             break;
2318         }
2319             
2320         case FlushedCell: {
2321             SpeculateCellOperand cell(this, node->child1());
2322             GPRReg cellGPR = cell.gpr();
2323             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2324             noResult(node);
2325             recordSetLocal(DataFormatCell);
2326             break;
2327         }
2328             
2329         case FlushedBoolean: {
2330             SpeculateBooleanOperand boolean(this, node->child1());
2331             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2332             noResult(node);
2333             recordSetLocal(DataFormatBoolean);
2334             break;
2335         }
2336             
2337         case FlushedJSValue: {
2338             JSValueOperand value(this, node->child1());
2339             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2340             noResult(node);
2341             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2342             break;
2343         }
2344             
2345         default:
2346             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2347             break;
2348         }
2349
2350         break;
2351     }
2352
2353     case SetArgument:
2354         // This is a no-op; it just marks the fact that the argument is being used.
2355         // But it may be profitable to use this as a hook to run speculation checks
2356         // on arguments, thereby allowing us to trivially eliminate such checks if
2357         // the argument is not used.
2358         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2359         break;
2360
2361     case BitAnd:
2362     case BitOr:
2363     case BitXor:
2364         compileBitwiseOp(node);
2365         break;
2366
2367     case BitRShift:
2368     case BitLShift:
2369     case BitURShift:
2370         compileShiftOp(node);
2371         break;
2372
2373     case UInt32ToNumber: {
2374         compileUInt32ToNumber(node);
2375         break;
2376     }
2377
2378     case DoubleAsInt32: {
2379         compileDoubleAsInt32(node);
2380         break;
2381     }
2382
2383     case ValueToInt32: {
2384         compileValueToInt32(node);
2385         break;
2386     }
2387         
2388     case DoubleRep: {
2389         compileDoubleRep(node);
2390         break;
2391     }
2392         
2393     case ValueRep: {
2394         compileValueRep(node);
2395         break;
2396     }
2397         
2398     case Int52Rep: {
2399         switch (node->child1().useKind()) {
2400         case Int32Use: {
2401             SpeculateInt32Operand operand(this, node->child1());
2402             GPRTemporary result(this, Reuse, operand);
2403             
2404             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2405             
2406             strictInt52Result(result.gpr(), node);
2407             break;
2408         }
2409             
2410         case AnyIntUse: {
2411             GPRTemporary result(this);
2412             GPRReg resultGPR = result.gpr();
2413             
2414             convertAnyInt(node->child1(), resultGPR);
2415             
2416             strictInt52Result(resultGPR, node);
2417             break;
2418         }
2419             
2420         case DoubleRepAnyIntUse: {
2421             SpeculateDoubleOperand value(this, node->child1());
2422             FPRReg valueFPR = value.fpr();
2423             
2424             flushRegisters();
2425             GPRFlushedCallResult result(this);
2426             GPRReg resultGPR = result.gpr();
2427             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2428             
2429             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2430                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2431                 m_jit.branch64(
2432                     JITCompiler::Equal, resultGPR,
2433                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2434             
2435             strictInt52Result(resultGPR, node);
2436             break;
2437         }
2438             
2439         default:
2440             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2441         }
2442         break;
2443     }
2444
2445     case ValueAdd:
2446         compileValueAdd(node);
2447         break;
2448
2449     case StrCat: {
2450         compileStrCat(node);
2451         break;
2452     }
2453
2454     case ArithAdd:
2455         compileArithAdd(node);
2456         break;
2457
2458     case ArithClz32:
2459         compileArithClz32(node);
2460         break;
2461         
2462     case MakeRope:
2463         compileMakeRope(node);
2464         break;
2465
2466     case ArithSub:
2467         compileArithSub(node);
2468         break;
2469
2470     case ArithNegate:
2471         compileArithNegate(node);
2472         break;
2473
2474     case ArithMul:
2475         compileArithMul(node);
2476         break;
2477
2478     case ArithDiv: {
2479         compileArithDiv(node);
2480         break;
2481     }
2482
2483     case ArithMod: {
2484         compileArithMod(node);
2485         break;
2486     }
2487
2488     case ArithAbs:
2489         compileArithAbs(node);
2490         break;
2491         
2492     case ArithMin:
2493     case ArithMax: {
2494         compileArithMinMax(node);
2495         break;
2496     }
2497
2498     case ArithPow:
2499         compileArithPow(node);
2500         break;
2501
2502     case ArithSqrt:
2503         compileArithSqrt(node);
2504         break;
2505
2506     case ArithFRound:
2507         compileArithFRound(node);
2508         break;
2509
2510     case ArithRandom:
2511         compileArithRandom(node);
2512         break;
2513
2514     case ArithRound:
2515     case ArithFloor:
2516     case ArithCeil:
2517     case ArithTrunc:
2518         compileArithRounding(node);
2519         break;
2520
2521     case ArithUnary:
2522         compileArithUnary(node);
2523         break;
2524
2525     case LogicalNot:
2526         compileLogicalNot(node);
2527         break;
2528
2529     case CompareLess:
2530         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2531             return;
2532         break;
2533
2534     case CompareLessEq:
2535         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2536             return;
2537         break;
2538
2539     case CompareGreater:
2540         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2541             return;
2542         break;
2543
2544     case CompareGreaterEq:
2545         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2546             return;
2547         break;
2548
2549     case CompareBelow:
2550         compileCompareUnsigned(node, JITCompiler::Below);
2551         break;
2552
2553     case CompareBelowEq:
2554         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2555         break;
2556
2557     case CompareEq:
2558         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2559             return;
2560         break;
2561
2562     case CompareStrictEq:
2563         if (compileStrictEq(node))
2564             return;
2565         break;
2566         
2567     case CompareEqPtr:
2568         compileCompareEqPtr(node);
2569         break;
2570
2571     case StringCharCodeAt: {
2572         compileGetCharCodeAt(node);
2573         break;
2574     }
2575
2576     case StringCharAt: {
2577         // Relies on StringCharAt node having same basic layout as GetByVal
2578         compileGetByValOnString(node);
2579         break;
2580     }
2581
2582     case StringFromCharCode: {
2583         compileFromCharCode(node);
2584         break;
2585     }
2586         
2587     case CheckArray: {
2588         checkArray(node);
2589         break;
2590     }
2591         
2592     case Arrayify:
2593     case ArrayifyToStructure: {
2594         arrayify(node);
2595         break;
2596     }
2597
2598     case GetByVal: {
2599         switch (node->arrayMode().type()) {
2600         case Array::SelectUsingPredictions:
2601         case Array::ForceExit:
2602             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2603             break;
2604         case Array::Undecided: {
2605             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2606             GPRTemporary result(this, Reuse, index);
2607             GPRReg indexGPR = index.gpr();
2608             GPRReg resultGPR = result.gpr();
2609
2610             speculationCheck(OutOfBounds, JSValueRegs(), node,
2611                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2612
2613             use(m_graph.varArgChild(node, 0));
2614             index.use();
2615
2616             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2617             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2618             break;
2619         }
2620         case Array::Generic: {
2621             if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2622                 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2623                     compileGetByValForObjectWithString(node);
2624                     break;
2625                 }
2626
2627                 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2628                     compileGetByValForObjectWithSymbol(node);
2629                     break;
2630                 }
2631             }
2632             JSValueOperand base(this, m_graph.varArgChild(node, 0));
2633             JSValueOperand property(this, m_graph.varArgChild(node, 1));
2634             GPRReg baseGPR = base.gpr();
2635             GPRReg propertyGPR = property.gpr();
2636             
2637             flushRegisters();
2638             GPRFlushedCallResult result(this);
2639             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2640             m_jit.exceptionCheck();
2641             
2642             jsValueResult(result.gpr(), node);
2643             break;
2644         }
2645         case Array::Int32:
2646         case Array::Contiguous: {
2647             if (node->arrayMode().isInBounds()) {
2648                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2649                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2650
2651                 GPRReg propertyReg = property.gpr();
2652                 GPRReg storageReg = storage.gpr();
2653
2654                 if (!m_compileOkay)
2655                     return;
2656                 
2657                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2658                 
2659                 GPRTemporary result(this);
2660
2661                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2662                 if (node->arrayMode().isSaneChain()) {
2663                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2664                     JITCompiler::Jump notHole = m_jit.branchTest64(
2665                         MacroAssembler::NonZero, result.gpr());
2666                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2667                     notHole.link(&m_jit);
2668                 } else {
2669                     speculationCheck(
2670                         LoadFromHole, JSValueRegs(), 0,
2671                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2672                 }
2673                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2674                 break;
2675             }
2676             
2677             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2678             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2679             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2680             
2681             GPRReg baseReg = base.gpr();
2682             GPRReg propertyReg = property.gpr();
2683             GPRReg storageReg = storage.gpr();
2684             
2685             if (!m_compileOkay)
2686                 return;
2687             
2688             GPRTemporary result(this);
2689             GPRReg resultReg = result.gpr();
2690             
2691             MacroAssembler::JumpList slowCases;
2692             
2693             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2694
2695             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2696             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2697             
2698             addSlowPathGenerator(
2699                 slowPathCall(
2700                     slowCases, this, operationGetByValObjectInt,
2701                     result.gpr(), baseReg, propertyReg));
2702             
2703             jsValueResult(resultReg, node);
2704             break;
2705         }
2706
2707         case Array::Double: {
2708             if (node->arrayMode().isInBounds()) {
2709                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2710                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2711
2712                 GPRReg propertyReg = property.gpr();
2713                 GPRReg storageReg = storage.gpr();
2714
2715                 if (!m_compileOkay)
2716                     return;
2717
2718                 FPRTemporary result(this);
2719                 FPRReg resultReg = result.fpr();
2720
2721                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2722
2723                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2724                 if (!node->arrayMode().isSaneChain())
2725                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, resultReg, resultReg));
2726                 doubleResult(resultReg, node);
2727                 break;
2728             }
2729
2730             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2731             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2732             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2733             
2734             GPRReg baseReg = base.gpr();
2735             GPRReg propertyReg = property.gpr();
2736             GPRReg storageReg = storage.gpr();
2737             
2738             if (!m_compileOkay)
2739                 return;
2740             
2741             GPRTemporary result(this);
2742             FPRTemporary temp(this);
2743             GPRReg resultReg = result.gpr();
2744             FPRReg tempReg = temp.fpr();
2745             
2746             MacroAssembler::JumpList slowCases;
2747             
2748             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2749
2750             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2751             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2752             boxDouble(tempReg, resultReg);
2753             
2754             addSlowPathGenerator(
2755                 slowPathCall(
2756                     slowCases, this, operationGetByValObjectInt,
2757                     result.gpr(), baseReg, propertyReg));
2758             
2759             jsValueResult(resultReg, node);
2760             break;
2761         }
2762
2763         case Array::ArrayStorage:
2764         case Array::SlowPutArrayStorage: {
2765             if (node->arrayMode().isInBounds()) {
2766                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2767                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2768             
2769                 GPRReg propertyReg = property.gpr();
2770                 GPRReg storageReg = storage.gpr();
2771             
2772                 if (!m_compileOkay)
2773                     return;
2774             
2775                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2776             
2777                 GPRTemporary result(this);
2778                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2779                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2780             
2781                 jsValueResult(result.gpr(), node);
2782                 break;
2783             }
2784
2785             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2786             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2787             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2788             
2789             GPRReg baseReg = base.gpr();
2790             GPRReg propertyReg = property.gpr();
2791             GPRReg storageReg = storage.gpr();
2792             
2793             if (!m_compileOkay)
2794                 return;
2795             
2796             GPRTemporary result(this);
2797             GPRReg resultReg = result.gpr();
2798             
2799             MacroAssembler::JumpList slowCases;
2800             
2801             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2802     
2803             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2804             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2805     
2806             addSlowPathGenerator(
2807                 slowPathCall(
2808                     slowCases, this, operationGetByValObjectInt,
2809                     result.gpr(), baseReg, propertyReg));
2810             
2811             jsValueResult(resultReg, node);
2812             break;
2813         }
2814         case Array::String:
2815             compileGetByValOnString(node);
2816             break;
2817         case Array::DirectArguments:
2818             compileGetByValOnDirectArguments(node);
2819             break;
2820         case Array::ScopedArguments:
2821             compileGetByValOnScopedArguments(node);
2822             break;
2823         default: {
2824             TypedArrayType type = node->arrayMode().typedArrayType();
2825             if (isInt(type))
2826                 compileGetByValOnIntTypedArray(node, type);
2827             else
2828                 compileGetByValOnFloatTypedArray(node, type);
2829         } }
2830         break;
2831     }
2832
2833     case GetByValWithThis: {
2834         compileGetByValWithThis(node);
2835         break;
2836     }
2837
2838     case PutByValDirect:
2839     case PutByVal:
2840     case PutByValAlias: {
2841         Edge child1 = m_jit.graph().varArgChild(node, 0);
2842         Edge child2 = m_jit.graph().varArgChild(node, 1);
2843         Edge child3 = m_jit.graph().varArgChild(node, 2);
2844         Edge child4 = m_jit.graph().varArgChild(node, 3);
2845         
2846         ArrayMode arrayMode = node->arrayMode().modeForPut();
2847         bool alreadyHandled = false;
2848         
2849         switch (arrayMode.type()) {
2850         case Array::SelectUsingPredictions:
2851         case Array::ForceExit:
2852             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2853             break;
2854         case Array::Generic: {
2855             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
2856
2857             if (child1.useKind() == CellUse) {
2858                 if (child2.useKind() == StringUse) {
2859                     compilePutByValForCellWithString(node, child1, child2, child3);
2860                     alreadyHandled = true;
2861                     break;
2862                 }
2863
2864                 if (child2.useKind() == SymbolUse) {
2865                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2866                     alreadyHandled = true;
2867                     break;
2868                 }
2869             }
2870             
2871             JSValueOperand arg1(this, child1);
2872             JSValueOperand arg2(this, child2);
2873             JSValueOperand arg3(this, child3);
2874             GPRReg arg1GPR = arg1.gpr();
2875             GPRReg arg2GPR = arg2.gpr();
2876             GPRReg arg3GPR = arg3.gpr();
2877             flushRegisters();
2878             if (node->op() == PutByValDirect)
2879                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2880             else
2881                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2882             m_jit.exceptionCheck();
2883             
2884             noResult(node);
2885             alreadyHandled = true;
2886             break;
2887         }
2888         default:
2889             break;
2890         }
2891         
2892         if (alreadyHandled)
2893             break;
2894
2895         SpeculateCellOperand base(this, child1);
2896         SpeculateStrictInt32Operand property(this, child2);
2897         
2898         GPRReg baseReg = base.gpr();
2899         GPRReg propertyReg = property.gpr();
2900
2901         switch (arrayMode.type()) {
2902         case Array::Int32:
2903         case Array::Contiguous: {
2904             JSValueOperand value(this, child3, ManualOperandSpeculation);
2905
2906             GPRReg valueReg = value.gpr();
2907         
2908             if (!m_compileOkay)
2909                 return;
2910             
2911             if (arrayMode.type() == Array::Int32) {
2912                 DFG_TYPE_CHECK(
2913                     JSValueRegs(valueReg), child3, SpecInt32Only,
2914                     m_jit.branch64(
2915                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2916             }
2917
2918             StorageOperand storage(this, child4);
2919             GPRReg storageReg = storage.gpr();
2920
2921             if (node->op() == PutByValAlias) {
2922                 // Store the value to the array.
2923                 GPRReg propertyReg = property.gpr();
2924                 GPRReg valueReg = value.gpr();
2925                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2926                 
2927                 noResult(node);
2928                 break;
2929             }
2930             
2931             GPRTemporary temporary;
2932             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2933
2934             MacroAssembler::Jump slowCase;
2935             
2936             if (arrayMode.isInBounds()) {
2937                 speculationCheck(
2938                     OutOfBounds, JSValueRegs(), 0,
2939                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2940             } else {
2941                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2942                 
2943                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2944                 
2945                 if (!arrayMode.isOutOfBounds())
2946                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2947                 
2948                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2949                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2950
2951                 inBounds.link(&m_jit);
2952             }
2953
2954             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2955
2956             base.use();
2957             property.use();
2958             value.use();
2959             storage.use();
2960             
2961             if (arrayMode.isOutOfBounds()) {
2962                 addSlowPathGenerator(slowPathCall(
2963                     slowCase, this,
2964                     m_jit.codeBlock()->isStrictMode()
2965                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2966                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2967                     NoResult, baseReg, propertyReg, valueReg));
2968             }
2969
2970             noResult(node, UseChildrenCalledExplicitly);
2971             break;
2972         }
2973             
2974         case Array::Double: {
2975             compileDoublePutByVal(node, base, property);
2976             break;
2977         }
2978             
2979         case Array::ArrayStorage:
2980         case Array::SlowPutArrayStorage: {
2981             JSValueOperand value(this, child3);
2982
2983             GPRReg valueReg = value.gpr();
2984         
2985             if (!m_compileOkay)
2986                 return;
2987
2988             StorageOperand storage(this, child4);
2989             GPRReg storageReg = storage.gpr();
2990
2991             if (node->op() == PutByValAlias) {
2992                 // Store the value to the array.
2993                 GPRReg propertyReg = property.gpr();
2994                 GPRReg valueReg = value.gpr();
2995                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2996                 
2997                 noResult(node);
2998                 break;
2999             }
3000             
3001             GPRTemporary temporary;
3002             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3003
3004             MacroAssembler::JumpList slowCases;
3005
3006             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3007             if (!arrayMode.isOutOfBounds())
3008                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3009             else
3010                 slowCases.append(beyondArrayBounds);
3011
3012             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3013             if (arrayMode.isInBounds()) {
3014                 speculationCheck(
3015                     StoreToHole, JSValueRegs(), 0,
3016                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
3017             } else {
3018                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3019                 if (arrayMode.isSlowPut()) {
3020                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3021                     // the above branch. But it's simply not worth it since this only happens if we're
3022                     // already having a bad time.
3023                     slowCases.append(m_jit.jump());
3024                 } else {
3025                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3026                 
3027                     // If we're writing to a hole we might be growing the array; 
3028                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3029                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3030                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3031                 
3032                     lengthDoesNotNeedUpdate.link(&m_jit);
3033                 }
3034                 notHoleValue.link(&m_jit);
3035             }
3036     
3037             // Store the value to the array.
3038             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3039
3040             base.use();
3041             property.use();
3042             value.use();
3043             storage.use();
3044             
3045             if (!slowCases.empty()) {
3046                 addSlowPathGenerator(slowPathCall(
3047                     slowCases, this,
3048                     m_jit.codeBlock()->isStrictMode()
3049                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
3050                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
3051                     NoResult, baseReg, propertyReg, valueReg));
3052             }
3053
3054             noResult(node, UseChildrenCalledExplicitly);
3055             break;
3056         }
3057             
3058         default: {
3059             TypedArrayType type = arrayMode.typedArrayType();
3060             if (isInt(type))
3061                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3062             else
3063                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3064         } }
3065
3066         break;
3067     }
3068         
3069     case AtomicsAdd:
3070     case AtomicsAnd:
3071     case AtomicsCompareExchange:
3072     case AtomicsExchange:
3073     case AtomicsLoad:
3074     case AtomicsOr:
3075     case AtomicsStore:
3076     case AtomicsSub:
3077     case AtomicsXor: {
3078         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
3079         Edge baseEdge = m_jit.graph().child(node, 0);
3080         Edge indexEdge = m_jit.graph().child(node, 1);
3081         Edge argEdges[maxNumExtraAtomicsArgs];
3082         for (unsigned i = numExtraArgs; i--;)
3083             argEdges[i] = m_jit.graph().child(node, 2 + i);
3084         Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
3085
3086         GPRReg baseGPR;
3087         GPRReg indexGPR;
3088         GPRReg argGPRs[2];
3089         GPRReg resultGPR;
3090
3091         auto callSlowPath = [&] () {
3092             switch (node->op()) {
3093             case AtomicsAdd:
3094                 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3095                 break;
3096             case AtomicsAnd:
3097                 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3098                 break;
3099             case AtomicsCompareExchange:
3100                 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
3101                 break;
3102             case AtomicsExchange:
3103                 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3104                 break;
3105             case AtomicsLoad:
3106                 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
3107                 break;
3108             case AtomicsOr:
3109                 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3110                 break;
3111             case AtomicsStore:
3112                 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3113                 break;
3114             case AtomicsSub:
3115                 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3116                 break;
3117             case AtomicsXor:
3118                 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3119                 break;
3120             default:
3121                 RELEASE_ASSERT_NOT_REACHED();
3122                 break;
3123             }
3124         };
3125         
3126         if (!storageEdge) {
3127             // We are in generic mode!
3128             JSValueOperand base(this, baseEdge);
3129             JSValueOperand index(this, indexEdge);
3130             std::optional<JSValueOperand> args[2];
3131             baseGPR = base.gpr();
3132             indexGPR = index.gpr();
3133             for (unsigned i = numExtraArgs; i--;) {
3134                 args[i].emplace(this, argEdges[i]);
3135                 argGPRs[i] = args[i]->gpr();
3136             }
3137             
3138             flushRegisters();
3139             GPRFlushedCallResult result(this);
3140             resultGPR = result.gpr();
3141             callSlowPath();
3142             m_jit.exceptionCheck();
3143             
3144             jsValueResult(resultGPR, node);
3145             break;
3146         }
3147         
3148         TypedArrayType type = node->arrayMode().typedArrayType();
3149         
3150         SpeculateCellOperand base(this, baseEdge);
3151         SpeculateStrictInt32Operand index(this, indexEdge);
3152
3153         baseGPR = base.gpr();
3154         indexGPR = index.gpr();
3155         
3156         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
3157         
3158         GPRTemporary args[2];
3159         
3160         JITCompiler::JumpList slowPathCases;
3161         
3162         bool ok = true;
3163         for (unsigned i = numExtraArgs; i--;) {
3164             if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
3165                 noResult(node);
3166                 ok = false;
3167             }
3168             argGPRs[i] = args[i].gpr();
3169         }
3170         if (!ok)
3171             break;
3172         
3173         StorageOperand storage(this, storageEdge);
3174         GPRTemporary oldValue(this);
3175         GPRTemporary result(this);
3176         GPRTemporary newValue(this);
3177         GPRReg storageGPR = storage.gpr();
3178         GPRReg oldValueGPR = oldValue.gpr();
3179         resultGPR = result.gpr();
3180         GPRReg newValueGPR = newValue.gpr();
3181         
3182         // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
3183         // https://bugs.webkit.org/show_bug.cgi?id=170974
3184         m_jit.nop();
3185         
3186         JITCompiler::Label loop = m_jit.label();
3187         
3188         loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
3189         m_jit.move(oldValueGPR, newValueGPR);
3190         m_jit.move(oldValueGPR, resultGPR);
3191         
3192         switch (node->op()) {
3193         case AtomicsAdd:
3194             m_jit.add32(argGPRs[0], newValueGPR);
3195             break;
3196         case AtomicsAnd:
3197             m_jit.and32(argGPRs[0], newValueGPR);
3198             break;
3199         case AtomicsCompareExchange: {
3200             switch (elementSize(type)) {
3201             case 1:
3202                 if (isSigned(type))
3203                     m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
3204                 else
3205                     m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
3206                 break;
3207             case 2:
3208                 if (isSigned(type))
3209                     m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3210                 else
3211                     m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3212                 break;
3213             case 4:
3214                 break;
3215             default:
3216                 RELEASE_ASSERT_NOT_REACHED();
3217                 break;
3218             }
3219             JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3220             m_jit.move(argGPRs[1], newValueGPR);
3221             fail.link(&m_jit);
3222             break;
3223         }
3224         case AtomicsExchange:
3225             m_jit.move(argGPRs[0], newValueGPR);
3226             break;
3227         case AtomicsLoad:
3228             break;
3229         case AtomicsOr:
3230             m_jit.or32(argGPRs[0], newValueGPR);
3231             break;
3232         case AtomicsStore:
3233             m_jit.move(argGPRs[0], newValueGPR);
3234             m_jit.move(argGPRs[0], resultGPR);
3235             break;
3236         case AtomicsSub:
3237             m_jit.sub32(argGPRs[0], newValueGPR);
3238             break;
3239         case AtomicsXor:
3240             m_jit.xor32(argGPRs[0], newValueGPR);
3241             break;
3242         default:
3243             RELEASE_ASSERT_NOT_REACHED();
3244             break;
3245         }
3246         
3247         JITCompiler::JumpList success;
3248         switch (elementSize(type)) {
3249         case 1:
3250             success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3251             break;
3252         case 2:
3253             success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3254             break;
3255         case 4:
3256             success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3257             break;
3258         default:
3259             RELEASE_ASSERT_NOT_REACHED();
3260             break;
3261         }
3262         m_jit.jump().linkTo(loop, &m_jit);
3263         
3264         if (!slowPathCases.empty()) {
3265             slowPathCases.link(&m_jit);
3266             silentSpillAllRegisters(resultGPR);
3267             // Since we spilled, we can do things to registers.
3268             m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3269             m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3270             for (unsigned i = numExtraArgs; i--;)
3271                 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3272             callSlowPath();
3273             silentFillAllRegisters();
3274             m_jit.exceptionCheck();
3275         }
3276         
3277         success.link(&m_jit);
3278         setIntTypedArrayLoadResult(node, resultGPR, type);
3279         break;
3280     }
3281         
3282     case AtomicsIsLockFree: {
3283         if (node->child1().useKind() != Int32Use) {
3284             JSValueOperand operand(this, node->child1());
3285             GPRReg operandGPR = operand.gpr();
3286             flushRegisters();
3287             GPRFlushedCallResult result(this);
3288             GPRReg resultGPR = result.gpr();
3289             callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3290             m_jit.exceptionCheck();
3291             jsValueResult(resultGPR, node);
3292             break;
3293         }
3294
3295         SpeculateInt32Operand operand(this, node->child1());
3296         GPRTemporary result(this);
3297         GPRReg operandGPR = operand.gpr();
3298         GPRReg resultGPR = result.gpr();
3299         m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3300         JITCompiler::JumpList done;
3301         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3302         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3303         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3304         m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3305         done.link(&m_jit);
3306         jsValueResult(resultGPR, node);
3307         break;
3308     }
3309
3310     case RegExpExec: {
3311         compileRegExpExec(node);
3312         break;
3313     }
3314
3315     case RegExpExecNonGlobalOrSticky: {
3316         compileRegExpExecNonGlobalOrSticky(node);
3317         break;
3318     }
3319
3320     case RegExpMatchFastGlobal: {
3321         compileRegExpMatchFastGlobal(node);
3322         break;
3323     }
3324
3325     case RegExpTest: {
3326         compileRegExpTest(node);
3327         break;
3328     }
3329
3330     case RegExpMatchFast: {
3331         compileRegExpMatchFast(node);
3332         break;
3333     }
3334
3335     case StringReplace:
3336     case StringReplaceRegExp: {
3337         compileStringReplace(node);
3338         break;
3339     }
3340         
3341     case GetRegExpObjectLastIndex: {
3342         compileGetRegExpObjectLastIndex(node);
3343         break;
3344     }
3345         
3346     case SetRegExpObjectLastIndex: {
3347         compileSetRegExpObjectLastIndex(node);
3348         break;
3349     }
3350
3351     case RecordRegExpCachedResult: {
3352         compileRecordRegExpCachedResult(node);
3353         break;
3354     }
3355         
3356     case ArrayPush: {
3357         compileArrayPush(node);
3358         break;
3359     }
3360
3361     case ArraySlice: {
3362         compileArraySlice(node);
3363         break;
3364     }
3365
3366     case ArrayIndexOf: {
3367         compileArrayIndexOf(node);
3368         break;
3369     }
3370         
3371     case ArrayPop: {
3372         ASSERT(node->arrayMode().isJSArray());
3373
3374         SpeculateCellOperand base(this, node->child1());
3375         StorageOperand storage(this, node->child2());
3376         GPRTemporary value(this);
3377         GPRTemporary storageLength(this);
3378         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().
3379         
3380         GPRReg baseGPR = base.gpr();
3381         GPRReg storageGPR = storage.gpr();
3382         GPRReg valueGPR = value.gpr();
3383         GPRReg storageLengthGPR = storageLength.gpr();
3384         FPRReg tempFPR = temp.fpr();
3385         
3386         switch (node->arrayMode().type()) {
3387         case Array::Int32:
3388         case Array::Double:
3389         case Array::Contiguous: {
3390             m_jit.load32(
3391                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3392             MacroAssembler::Jump undefinedCase =
3393                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3394             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3395             m_jit.store32(
3396                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3397             MacroAssembler::Jump slowCase;
3398             if (node->arrayMode().type() == Array::Double) {
3399                 m_jit.loadDouble(
3400                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3401                     tempFPR);
3402                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3403                 // length and the new length.
3404                 m_jit.store64(
3405                     MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3406                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3407                 boxDouble(tempFPR, valueGPR);
3408             } else {
3409                 m_jit.load64(
3410                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3411                     valueGPR);
3412                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3413                 // length and the new length.
3414                 m_jit.store64(
3415                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3416                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3417             }
3418
3419             addSlowPathGenerator(
3420                 slowPathMove(
3421                     undefinedCase, this,
3422                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3423             addSlowPathGenerator(
3424                 slowPathCall(
3425                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3426             
3427             // We can't know for sure that the result is an int because of the slow paths. :-/
3428             jsValueResult(valueGPR, node);
3429             break;
3430         }
3431             
3432         case Array::ArrayStorage: {
3433             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3434         
3435             JITCompiler::Jump undefinedCase =
3436                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3437         
3438             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3439         
3440             JITCompiler::JumpList slowCases;
3441             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3442         
3443             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3444             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3445         
3446             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3447         
3448             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight,  ArrayStorage::vectorOffset()));
3449             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3450         
3451             addSlowPathGenerator(
3452                 slowPathMove(
3453                     undefinedCase, this,
3454                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3455         
3456             addSlowPathGenerator(
3457                 slowPathCall(
3458                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3459
3460             jsValueResult(valueGPR, node);
3461             break;
3462         }
3463             
3464         default:
3465             CRASH();
3466             break;
3467         }
3468         break;
3469     }
3470
3471     case DFG::Jump: {
3472         jump(node->targetBlock());
3473         noResult(node);
3474         break;
3475     }
3476
3477     case Branch:
3478         emitBranch(node);
3479         break;
3480         
3481     case Switch:
3482         emitSwitch(node);
3483         break;
3484
3485     case Return: {
3486         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3487         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3488         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3489
3490         // Return the result in returnValueGPR.
3491         JSValueOperand op1(this, node->child1());
3492         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3493
3494         m_jit.emitRestoreCalleeSaves();
3495         m_jit.emitFunctionEpilogue();
3496         m_jit.ret();
3497         
3498         noResult(node);
3499         break;
3500     }
3501         
3502     case Throw: {
3503         compileThrow(node);
3504         break;
3505     }
3506
3507     case ThrowStaticError: {
3508         compileThrowStaticError(node);
3509         break;
3510     }
3511         
3512     case BooleanToNumber: {
3513         switch (node->child1().useKind()) {
3514         case BooleanUse: {
3515             JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3516             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3517             
3518             m_jit.move(value.gpr(), result.gpr());
3519             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3520             DFG_TYPE_CHECK(
3521                 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3522                     JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3523
3524             int32Result(result.gpr(), node);
3525             break;
3526         }
3527             
3528         case UntypedUse: {
3529             JSValueOperand value(this, node->child1());
3530             GPRTemporary result(this);
3531             
3532             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3533                 m_jit.move(value.gpr(), result.gpr());
3534                 m_jit.and32(TrustedImm32(1), result.gpr());
3535                 int32Result(result.gpr(), node);
3536                 break;
3537             }
3538             
3539             m_jit.move(value.gpr(), result.gpr());
3540             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3541             JITCompiler::Jump isBoolean = m_jit.branchTest64(
3542                 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3543             m_jit.move(value.gpr(), result.gpr());
3544             JITCompiler::Jump done = m_jit.jump();
3545             isBoolean.link(&m_jit);
3546             m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3547             done.link(&m_jit);
3548             
3549             jsValueResult(result.gpr(), node);
3550             break;
3551         }
3552             
3553         default:
3554             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3555             break;
3556         }
3557         break;
3558     }
3559         
3560     case ToPrimitive: {
3561         compileToPrimitive(node);
3562         break;
3563     }
3564
3565     case ToNumber: {
3566         JSValueOperand argument(this, node->child1());
3567         GPRTemporary result(this, Reuse, argument);
3568
3569         GPRReg argumentGPR = argument.gpr();
3570         GPRReg resultGPR = result.gpr();
3571
3572         argument.use();
3573
3574         // We have several attempts to remove ToNumber. But ToNumber still exists.
3575         // It means that converting non-numbers to numbers by this ToNumber is not rare.
3576         // Instead of the slow path generator, we emit callOperation here.
3577         if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3578             flushRegisters();
3579             callOperation(operationToNumber, resultGPR, argumentGPR);
3580             m_jit.exceptionCheck();
3581         } else {
3582             MacroAssembler::Jump notNumber = m_jit.branchIfNotNumber(argumentGPR);
3583             m_jit.move(argumentGPR, resultGPR);
3584             MacroAssembler::Jump done = m_jit.jump();
3585
3586             notNumber.link(&m_jit);
3587             silentSpillAllRegisters(resultGPR);
3588             callOperation(operationToNumber, resultGPR, argumentGPR);
3589             silentFillAllRegisters();
3590             m_jit.exceptionCheck();
3591
3592             done.link(&m_jit);
3593         }
3594
3595         jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3596         break;
3597     }
3598         
3599     case ToString:
3600     case CallStringConstructor: {
3601         compileToStringOrCallStringConstructor(node);
3602         break;
3603     }
3604         
3605     case NewStringObject: {
3606         compileNewStringObject(node);
3607         break;
3608     }
3609         
3610     case NewArray: {
3611         compileNewArray(node);
3612         break;
3613     }
3614
3615     case NewArrayWithSpread: {
3616         compileNewArrayWithSpread(node);
3617         break;
3618     }
3619
3620     case Spread: {
3621         compileSpread(node);
3622         break;
3623     }
3624         
3625     case NewArrayWithSize: {
3626         compileNewArrayWithSize(node);
3627         break;
3628     }
3629         
3630     case NewArrayBuffer: {
3631         compileNewArrayBuffer(node);
3632         break;
3633     }
3634         
3635     case NewTypedArray: {
3636         compileNewTypedArray(node);
3637         break;
3638     }
3639         
3640     case NewRegexp: {
3641         compileNewRegexp(node);
3642         break;
3643     }
3644
3645     case ToObject:
3646     case CallObjectConstructor: {
3647         compileToObjectOrCallObjectConstructor(node);
3648         break;
3649     }
3650
3651     case ToThis: {
3652         compileToThis(node);
3653         break;
3654     }
3655
3656     case CreateThis: {
3657         compileCreateThis(node);
3658         break;
3659     }
3660         
3661     case NewObject: {
3662         compileNewObject(node);
3663         break;
3664     }
3665
3666     case GetCallee: {
3667         compileGetCallee(node);
3668         break;
3669     }
3670         
3671     case GetArgumentCountIncludingThis: {
3672         compileGetArgumentCountIncludingThis(node);
3673         break;
3674     }
3675
3676     case SetArgumentCountIncludingThis:
3677         compileSetArgumentCountIncludingThis(node);
3678         break;
3679
3680     case GetRestLength: {
3681     &n