Unreviewed, rolling out r226434.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT64.cpp
1 /*
2  * Copyright (C) 2011-2017 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);
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         unsigned 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.setupArgumentsWithExecState(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(0));
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);
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);
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);
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);
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);
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);
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         speculate(node, node->child1());
2206         switch (node->child1().useKind()) {
2207         case DoubleRepUse:
2208         case DoubleRepRealUse:
2209         case DoubleRepAnyIntUse: {
2210             SpeculateDoubleOperand op(this, node->child1());
2211             FPRTemporary scratch(this, op);
2212             m_jit.moveDouble(op.fpr(), scratch.fpr());
2213             doubleResult(scratch.fpr(), node);
2214             break;
2215         }
2216         case Int52RepUse: {
2217             SpeculateInt52Operand op(this, node->child1());
2218             GPRTemporary result(this, Reuse, op);
2219             m_jit.move(op.gpr(), result.gpr());
2220             int52Result(result.gpr(), node);
2221             break;
2222         }
2223         default: {
2224             JSValueOperand op(this, node->child1(), ManualOperandSpeculation);
2225             GPRTemporary result(this, Reuse, op);
2226             m_jit.move(op.gpr(), result.gpr());
2227             jsValueResult(result.gpr(), node);
2228             break;
2229         }
2230         } // switch
2231         break;
2232     }
2233
2234     case GetLocal: {
2235         AbstractValue& value = m_state.variables().operand(node->local());
2236
2237         // If the CFA is tracking this variable and it found that the variable
2238         // cannot have been assigned, then don't attempt to proceed.
2239         if (value.isClear()) {
2240             m_compileOkay = false;
2241             break;
2242         }
2243         
2244         switch (node->variableAccessData()->flushFormat()) {
2245         case FlushedDouble: {
2246             FPRTemporary result(this);
2247             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2248             VirtualRegister virtualRegister = node->virtualRegister();
2249             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2250             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2251             break;
2252         }
2253         
2254         case FlushedInt32: {
2255             GPRTemporary result(this);
2256             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2257             
2258             // Like int32Result, but don't useChildren - our children are phi nodes,
2259             // and don't represent values within this dataflow with virtual registers.
2260             VirtualRegister virtualRegister = node->virtualRegister();
2261             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2262             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2263             break;
2264         }
2265             
2266         case FlushedInt52: {
2267             GPRTemporary result(this);
2268             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2269             
2270             VirtualRegister virtualRegister = node->virtualRegister();
2271             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2272             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2273             break;
2274         }
2275             
2276         default:
2277             GPRTemporary result(this);
2278             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2279             
2280             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2281             // and don't represent values within this dataflow with virtual registers.
2282             VirtualRegister virtualRegister = node->virtualRegister();
2283             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2284             
2285             DataFormat format;
2286             if (isCellSpeculation(value.m_type))
2287                 format = DataFormatJSCell;
2288             else if (isBooleanSpeculation(value.m_type))
2289                 format = DataFormatJSBoolean;
2290             else
2291                 format = DataFormatJS;
2292             
2293             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2294             break;
2295         }
2296         break;
2297     }
2298
2299     case MovHint: {
2300         compileMovHint(m_currentNode);
2301         noResult(node);
2302         break;
2303     }
2304         
2305     case ZombieHint: {
2306         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2307         noResult(node);
2308         break;
2309     }
2310         
2311     case ExitOK: {
2312         noResult(node);
2313         break;
2314     }
2315         
2316     case SetLocal: {
2317         switch (node->variableAccessData()->flushFormat()) {
2318         case FlushedDouble: {
2319             SpeculateDoubleOperand value(this, node->child1());
2320             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2321             noResult(node);
2322             // Indicate that it's no longer necessary to retrieve the value of
2323             // this bytecode variable from registers or other locations in the stack,
2324             // but that it is stored as a double.
2325             recordSetLocal(DataFormatDouble);
2326             break;
2327         }
2328             
2329         case FlushedInt32: {
2330             SpeculateInt32Operand value(this, node->child1());
2331             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2332             noResult(node);
2333             recordSetLocal(DataFormatInt32);
2334             break;
2335         }
2336             
2337         case FlushedInt52: {
2338             SpeculateInt52Operand value(this, node->child1());
2339             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2340             noResult(node);
2341             recordSetLocal(DataFormatInt52);
2342             break;
2343         }
2344             
2345         case FlushedCell: {
2346             SpeculateCellOperand cell(this, node->child1());
2347             GPRReg cellGPR = cell.gpr();
2348             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2349             noResult(node);
2350             recordSetLocal(DataFormatCell);
2351             break;
2352         }
2353             
2354         case FlushedBoolean: {
2355             SpeculateBooleanOperand boolean(this, node->child1());
2356             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2357             noResult(node);
2358             recordSetLocal(DataFormatBoolean);
2359             break;
2360         }
2361             
2362         case FlushedJSValue: {
2363             JSValueOperand value(this, node->child1());
2364             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2365             noResult(node);
2366             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2367             break;
2368         }
2369             
2370         default:
2371             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2372             break;
2373         }
2374
2375         break;
2376     }
2377
2378     case SetArgument:
2379         // This is a no-op; it just marks the fact that the argument is being used.
2380         // But it may be profitable to use this as a hook to run speculation checks
2381         // on arguments, thereby allowing us to trivially eliminate such checks if
2382         // the argument is not used.
2383         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2384         break;
2385
2386     case BitAnd:
2387     case BitOr:
2388     case BitXor:
2389         compileBitwiseOp(node);
2390         break;
2391
2392     case BitRShift:
2393     case BitLShift:
2394     case BitURShift:
2395         compileShiftOp(node);
2396         break;
2397
2398     case UInt32ToNumber: {
2399         compileUInt32ToNumber(node);
2400         break;
2401     }
2402
2403     case DoubleAsInt32: {
2404         compileDoubleAsInt32(node);
2405         break;
2406     }
2407
2408     case ValueToInt32: {
2409         compileValueToInt32(node);
2410         break;
2411     }
2412         
2413     case DoubleRep: {
2414         compileDoubleRep(node);
2415         break;
2416     }
2417         
2418     case ValueRep: {
2419         compileValueRep(node);
2420         break;
2421     }
2422         
2423     case Int52Rep: {
2424         switch (node->child1().useKind()) {
2425         case Int32Use: {
2426             SpeculateInt32Operand operand(this, node->child1());
2427             GPRTemporary result(this, Reuse, operand);
2428             
2429             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2430             
2431             strictInt52Result(result.gpr(), node);
2432             break;
2433         }
2434             
2435         case AnyIntUse: {
2436             GPRTemporary result(this);
2437             GPRReg resultGPR = result.gpr();
2438             
2439             convertAnyInt(node->child1(), resultGPR);
2440             
2441             strictInt52Result(resultGPR, node);
2442             break;
2443         }
2444             
2445         case DoubleRepAnyIntUse: {
2446             SpeculateDoubleOperand value(this, node->child1());
2447             FPRReg valueFPR = value.fpr();
2448             
2449             flushRegisters();
2450             GPRFlushedCallResult result(this);
2451             GPRReg resultGPR = result.gpr();
2452             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2453             
2454             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2455                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2456                 m_jit.branch64(
2457                     JITCompiler::Equal, resultGPR,
2458                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2459             
2460             strictInt52Result(resultGPR, node);
2461             break;
2462         }
2463             
2464         default:
2465             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2466         }
2467         break;
2468     }
2469
2470     case ValueAdd:
2471         compileValueAdd(node);
2472         break;
2473
2474     case StrCat: {
2475         compileStrCat(node);
2476         break;
2477     }
2478
2479     case ArithAdd:
2480         compileArithAdd(node);
2481         break;
2482
2483     case ArithClz32:
2484         compileArithClz32(node);
2485         break;
2486         
2487     case MakeRope:
2488         compileMakeRope(node);
2489         break;
2490
2491     case ArithSub:
2492         compileArithSub(node);
2493         break;
2494
2495     case ArithNegate:
2496         compileArithNegate(node);
2497         break;
2498
2499     case ArithMul:
2500         compileArithMul(node);
2501         break;
2502
2503     case ArithDiv: {
2504         compileArithDiv(node);
2505         break;
2506     }
2507
2508     case ArithMod: {
2509         compileArithMod(node);
2510         break;
2511     }
2512
2513     case ArithAbs:
2514         compileArithAbs(node);
2515         break;
2516         
2517     case ArithMin:
2518     case ArithMax: {
2519         switch (node->binaryUseKind()) {
2520         case Int32Use: {
2521             SpeculateStrictInt32Operand op1(this, node->child1());
2522             SpeculateStrictInt32Operand op2(this, node->child2());
2523             GPRTemporary result(this, Reuse, op1);
2524             
2525             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2526             m_jit.move(op2.gpr(), result.gpr());
2527             if (op1.gpr() != result.gpr()) {
2528                 MacroAssembler::Jump done = m_jit.jump();
2529                 op1Less.link(&m_jit);
2530                 m_jit.move(op1.gpr(), result.gpr());
2531                 done.link(&m_jit);
2532             } else
2533                 op1Less.link(&m_jit);
2534             
2535             int32Result(result.gpr(), node);
2536             break;
2537         }
2538         
2539         case DoubleRepUse: {
2540             SpeculateDoubleOperand op1(this, node->child1());
2541             SpeculateDoubleOperand op2(this, node->child2());
2542             FPRTemporary result(this, op1);
2543             
2544             FPRReg op1FPR = op1.fpr();
2545             FPRReg op2FPR = op2.fpr();
2546             FPRReg resultFPR = result.fpr();
2547         
2548             MacroAssembler::JumpList done;
2549         
2550             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2551         
2552             // op2 is eather the lesser one or one of then is NaN
2553             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2554         
2555             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2556             // op1 + op2 and putting it into result.
2557             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2558             done.append(m_jit.jump());
2559         
2560             op2Less.link(&m_jit);
2561             m_jit.moveDouble(op2FPR, resultFPR);
2562         
2563             if (op1FPR != resultFPR) {
2564                 done.append(m_jit.jump());
2565             
2566                 op1Less.link(&m_jit);
2567                 m_jit.moveDouble(op1FPR, resultFPR);
2568             } else
2569                 op1Less.link(&m_jit);
2570         
2571             done.link(&m_jit);
2572         
2573             doubleResult(resultFPR, node);
2574             break;
2575         }
2576             
2577         default:
2578             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2579             break;
2580         }
2581         break;
2582     }
2583
2584     case ArithPow:
2585         compileArithPow(node);
2586         break;
2587
2588     case ArithSqrt:
2589         compileArithSqrt(node);
2590         break;
2591
2592     case ArithFRound:
2593         compileArithFRound(node);
2594         break;
2595
2596     case ArithRandom:
2597         compileArithRandom(node);
2598         break;
2599
2600     case ArithRound:
2601     case ArithFloor:
2602     case ArithCeil:
2603     case ArithTrunc:
2604         compileArithRounding(node);
2605         break;
2606
2607     case ArithUnary:
2608         compileArithUnary(node);
2609         break;
2610
2611     case LogicalNot:
2612         compileLogicalNot(node);
2613         break;
2614
2615     case CompareLess:
2616         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2617             return;
2618         break;
2619
2620     case CompareLessEq:
2621         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2622             return;
2623         break;
2624
2625     case CompareGreater:
2626         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2627             return;
2628         break;
2629
2630     case CompareGreaterEq:
2631         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2632             return;
2633         break;
2634
2635     case CompareBelow:
2636         compileCompareUnsigned(node, JITCompiler::Below);
2637         break;
2638
2639     case CompareBelowEq:
2640         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2641         break;
2642
2643     case CompareEq:
2644         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2645             return;
2646         break;
2647
2648     case CompareStrictEq:
2649         if (compileStrictEq(node))
2650             return;
2651         break;
2652         
2653     case CompareEqPtr:
2654         compileCompareEqPtr(node);
2655         break;
2656
2657     case StringCharCodeAt: {
2658         compileGetCharCodeAt(node);
2659         break;
2660     }
2661
2662     case StringCharAt: {
2663         // Relies on StringCharAt node having same basic layout as GetByVal
2664         compileGetByValOnString(node);
2665         break;
2666     }
2667
2668     case StringFromCharCode: {
2669         compileFromCharCode(node);
2670         break;
2671     }
2672         
2673     case CheckArray: {
2674         checkArray(node);
2675         break;
2676     }
2677         
2678     case Arrayify:
2679     case ArrayifyToStructure: {
2680         arrayify(node);
2681         break;
2682     }
2683
2684     case GetByVal: {
2685         switch (node->arrayMode().type()) {
2686         case Array::SelectUsingPredictions:
2687         case Array::ForceExit:
2688             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2689             break;
2690         case Array::Undecided: {
2691             SpeculateStrictInt32Operand index(this, node->child2());
2692             GPRTemporary result(this, Reuse, index);
2693             GPRReg indexGPR = index.gpr();
2694             GPRReg resultGPR = result.gpr();
2695
2696             speculationCheck(OutOfBounds, JSValueRegs(), node,
2697                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2698
2699             use(node->child1());
2700             index.use();
2701
2702             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2703             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2704             break;
2705         }
2706         case Array::Generic: {
2707             if (node->child1().useKind() == ObjectUse) {
2708                 if (node->child2().useKind() == StringUse) {
2709                     compileGetByValForObjectWithString(node);
2710                     break;
2711                 }
2712
2713                 if (node->child2().useKind() == SymbolUse) {
2714                     compileGetByValForObjectWithSymbol(node);
2715                     break;
2716                 }
2717             }
2718             JSValueOperand base(this, node->child1());
2719             JSValueOperand property(this, node->child2());
2720             GPRReg baseGPR = base.gpr();
2721             GPRReg propertyGPR = property.gpr();
2722             
2723             flushRegisters();
2724             GPRFlushedCallResult result(this);
2725             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2726             m_jit.exceptionCheck();
2727             
2728             jsValueResult(result.gpr(), node);
2729             break;
2730         }
2731         case Array::Int32:
2732         case Array::Contiguous: {
2733             if (node->arrayMode().isInBounds()) {
2734                 SpeculateCellOperand base(this, node->child1());
2735                 SpeculateStrictInt32Operand property(this, node->child2());
2736                 StorageOperand storage(this, node->child3());
2737
2738                 GPRReg baseReg = base.gpr();
2739                 GPRReg propertyReg = property.gpr();
2740                 GPRReg storageReg = storage.gpr();
2741
2742                 if (!m_compileOkay)
2743                     return;
2744                 
2745                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2746                 
2747                 GPRTemporary result(this);
2748
2749                 m_jit.and32(MacroAssembler::Address(baseReg, JSObject::butterflyIndexingMaskOffset()), propertyReg);
2750                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2751                 if (node->arrayMode().isSaneChain()) {
2752                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2753                     JITCompiler::Jump notHole = m_jit.branchTest64(
2754                         MacroAssembler::NonZero, result.gpr());
2755                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2756                     notHole.link(&m_jit);
2757                 } else {
2758                     speculationCheck(
2759                         LoadFromHole, JSValueRegs(), 0,
2760                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2761                 }
2762                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2763                 break;
2764             }
2765             
2766             SpeculateCellOperand base(this, node->child1());
2767             SpeculateStrictInt32Operand property(this, node->child2());
2768             StorageOperand storage(this, node->child3());
2769             
2770             GPRReg baseReg = base.gpr();
2771             GPRReg propertyReg = property.gpr();
2772             GPRReg storageReg = storage.gpr();
2773             
2774             if (!m_compileOkay)
2775                 return;
2776             
2777             GPRTemporary result(this);
2778             GPRReg resultReg = result.gpr();
2779             
2780             MacroAssembler::JumpList slowCases;
2781             
2782             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2783
2784             m_jit.and32(MacroAssembler::Address(baseReg, JSObject::butterflyIndexingMaskOffset()), propertyReg);
2785             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2786             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2787             
2788             addSlowPathGenerator(
2789                 slowPathCall(
2790                     slowCases, this, operationGetByValObjectInt,
2791                     result.gpr(), baseReg, propertyReg));
2792             
2793             jsValueResult(resultReg, node);
2794             break;
2795         }
2796
2797         case Array::Double: {
2798             if (node->arrayMode().isInBounds()) {
2799                 SpeculateCellOperand base(this, node->child1());
2800                 SpeculateStrictInt32Operand property(this, node->child2());
2801                 StorageOperand storage(this, node->child3());
2802
2803                 GPRReg baseReg = base.gpr();
2804                 GPRReg propertyReg = property.gpr();
2805                 GPRReg storageReg = storage.gpr();
2806
2807                 if (!m_compileOkay)
2808                     return;
2809
2810                 FPRTemporary result(this);
2811                 FPRReg resultReg = result.fpr();
2812
2813                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2814
2815                 m_jit.and32(MacroAssembler::Address(baseReg, JSObject::butterflyIndexingMaskOffset()), propertyReg);
2816                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2817                 if (!node->arrayMode().isSaneChain())
2818                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, resultReg, resultReg));
2819                 doubleResult(resultReg, node);
2820                 break;
2821             }
2822
2823             SpeculateCellOperand base(this, node->child1());
2824             SpeculateStrictInt32Operand property(this, node->child2());
2825             StorageOperand storage(this, node->child3());
2826             
2827             GPRReg baseReg = base.gpr();
2828             GPRReg propertyReg = property.gpr();
2829             GPRReg storageReg = storage.gpr();
2830             
2831             if (!m_compileOkay)
2832                 return;
2833             
2834             GPRTemporary result(this);
2835             FPRTemporary temp(this);
2836             GPRReg resultReg = result.gpr();
2837             FPRReg tempReg = temp.fpr();
2838             
2839             MacroAssembler::JumpList slowCases;
2840             
2841             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2842
2843             m_jit.and32(MacroAssembler::Address(baseReg, JSObject::butterflyIndexingMaskOffset()), propertyReg);
2844             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2845             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2846             boxDouble(tempReg, resultReg);
2847             
2848             addSlowPathGenerator(
2849                 slowPathCall(
2850                     slowCases, this, operationGetByValObjectInt,
2851                     result.gpr(), baseReg, propertyReg));
2852             
2853             jsValueResult(resultReg, node);
2854             break;
2855         }
2856
2857         case Array::ArrayStorage:
2858         case Array::SlowPutArrayStorage: {
2859             if (node->arrayMode().isInBounds()) {
2860                 SpeculateStrictInt32Operand property(this, node->child2());
2861                 StorageOperand storage(this, node->child3());
2862             
2863                 GPRReg propertyReg = property.gpr();
2864                 GPRReg storageReg = storage.gpr();
2865             
2866                 if (!m_compileOkay)
2867                     return;
2868             
2869                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2870             
2871                 GPRTemporary result(this);
2872                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2873                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2874             
2875                 jsValueResult(result.gpr(), node);
2876                 break;
2877             }
2878
2879             SpeculateCellOperand base(this, node->child1());
2880             SpeculateStrictInt32Operand property(this, node->child2());
2881             StorageOperand storage(this, node->child3());
2882             
2883             GPRReg baseReg = base.gpr();
2884             GPRReg propertyReg = property.gpr();
2885             GPRReg storageReg = storage.gpr();
2886             
2887             if (!m_compileOkay)
2888                 return;
2889             
2890             GPRTemporary result(this);
2891             GPRReg resultReg = result.gpr();
2892             
2893             MacroAssembler::JumpList slowCases;
2894             
2895             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2896     
2897             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2898             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2899     
2900             addSlowPathGenerator(
2901                 slowPathCall(
2902                     slowCases, this, operationGetByValObjectInt,
2903                     result.gpr(), baseReg, propertyReg));
2904             
2905             jsValueResult(resultReg, node);
2906             break;
2907         }
2908         case Array::String:
2909             compileGetByValOnString(node);
2910             break;
2911         case Array::DirectArguments:
2912             compileGetByValOnDirectArguments(node);
2913             break;
2914         case Array::ScopedArguments:
2915             compileGetByValOnScopedArguments(node);
2916             break;
2917         default: {
2918             TypedArrayType type = node->arrayMode().typedArrayType();
2919             if (isInt(type))
2920                 compileGetByValOnIntTypedArray(node, type);
2921             else
2922                 compileGetByValOnFloatTypedArray(node, type);
2923         } }
2924         break;
2925     }
2926
2927     case GetByValWithThis: {
2928         JSValueOperand base(this, node->child1());
2929         GPRReg baseGPR = base.gpr();
2930         JSValueOperand thisValue(this, node->child2());
2931         GPRReg thisValueGPR = thisValue.gpr();
2932         JSValueOperand subscript(this, node->child3());
2933         GPRReg subscriptGPR = subscript.gpr();
2934
2935         flushRegisters();
2936         GPRFlushedCallResult result(this);
2937         GPRReg resultGPR = result.gpr();
2938         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2939         m_jit.exceptionCheck();
2940
2941         jsValueResult(resultGPR, node);
2942         break;
2943     }
2944
2945     case PutByValDirect:
2946     case PutByVal:
2947     case PutByValAlias: {
2948         Edge child1 = m_jit.graph().varArgChild(node, 0);
2949         Edge child2 = m_jit.graph().varArgChild(node, 1);
2950         Edge child3 = m_jit.graph().varArgChild(node, 2);
2951         Edge child4 = m_jit.graph().varArgChild(node, 3);
2952         
2953         ArrayMode arrayMode = node->arrayMode().modeForPut();
2954         bool alreadyHandled = false;
2955         
2956         switch (arrayMode.type()) {
2957         case Array::SelectUsingPredictions:
2958         case Array::ForceExit:
2959             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2960             break;
2961         case Array::Generic: {
2962             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2963
2964             if (child1.useKind() == CellUse) {
2965                 if (child2.useKind() == StringUse) {
2966                     compilePutByValForCellWithString(node, child1, child2, child3);
2967                     alreadyHandled = true;
2968                     break;
2969                 }
2970
2971                 if (child2.useKind() == SymbolUse) {
2972                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2973                     alreadyHandled = true;
2974                     break;
2975                 }
2976             }
2977             
2978             JSValueOperand arg1(this, child1);
2979             JSValueOperand arg2(this, child2);
2980             JSValueOperand arg3(this, child3);
2981             GPRReg arg1GPR = arg1.gpr();
2982             GPRReg arg2GPR = arg2.gpr();
2983             GPRReg arg3GPR = arg3.gpr();
2984             flushRegisters();
2985             if (node->op() == PutByValDirect)
2986                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2987             else
2988                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2989             m_jit.exceptionCheck();
2990             
2991             noResult(node);
2992             alreadyHandled = true;
2993             break;
2994         }
2995         default:
2996             break;
2997         }
2998         
2999         if (alreadyHandled)
3000             break;
3001
3002         SpeculateCellOperand base(this, child1);
3003         SpeculateStrictInt32Operand property(this, child2);
3004         
3005         GPRReg baseReg = base.gpr();
3006         GPRReg propertyReg = property.gpr();
3007
3008         switch (arrayMode.type()) {
3009         case Array::Int32:
3010         case Array::Contiguous: {
3011             JSValueOperand value(this, child3, ManualOperandSpeculation);
3012
3013             GPRReg valueReg = value.gpr();
3014         
3015             if (!m_compileOkay)
3016                 return;
3017             
3018             if (arrayMode.type() == Array::Int32) {
3019                 DFG_TYPE_CHECK(
3020                     JSValueRegs(valueReg), child3, SpecInt32Only,
3021                     m_jit.branch64(
3022                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
3023             }
3024
3025             StorageOperand storage(this, child4);
3026             GPRReg storageReg = storage.gpr();
3027
3028             if (node->op() == PutByValAlias) {
3029                 // Store the value to the array.
3030                 GPRReg propertyReg = property.gpr();
3031                 GPRReg valueReg = value.gpr();
3032                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3033                 
3034                 noResult(node);
3035                 break;
3036             }
3037             
3038             GPRTemporary temporary;
3039             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3040
3041             MacroAssembler::Jump slowCase;
3042             
3043             if (arrayMode.isInBounds()) {
3044                 speculationCheck(
3045                     OutOfBounds, JSValueRegs(), 0,
3046                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3047             } else {
3048                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3049                 
3050                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3051                 
3052                 if (!arrayMode.isOutOfBounds())
3053                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3054                 
3055                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3056                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3057
3058                 inBounds.link(&m_jit);
3059             }
3060
3061             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3062
3063             base.use();
3064             property.use();
3065             value.use();
3066             storage.use();
3067             
3068             if (arrayMode.isOutOfBounds()) {
3069                 if (node->op() == PutByValDirect) {
3070                     addSlowPathGenerator(slowPathCall(
3071                         slowCase, this,
3072                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3073                         NoResult, baseReg, propertyReg, valueReg));
3074                 } else {
3075                     addSlowPathGenerator(slowPathCall(
3076                         slowCase, this,
3077                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3078                         NoResult, baseReg, propertyReg, valueReg));
3079                 }
3080             }
3081
3082             noResult(node, UseChildrenCalledExplicitly);
3083             break;
3084         }
3085             
3086         case Array::Double: {
3087             compileDoublePutByVal(node, base, property);
3088             break;
3089         }
3090             
3091         case Array::ArrayStorage:
3092         case Array::SlowPutArrayStorage: {
3093             JSValueOperand value(this, child3);
3094
3095             GPRReg valueReg = value.gpr();
3096         
3097             if (!m_compileOkay)
3098                 return;
3099
3100             StorageOperand storage(this, child4);
3101             GPRReg storageReg = storage.gpr();
3102
3103             if (node->op() == PutByValAlias) {
3104                 // Store the value to the array.
3105                 GPRReg propertyReg = property.gpr();
3106                 GPRReg valueReg = value.gpr();
3107                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3108                 
3109                 noResult(node);
3110                 break;
3111             }
3112             
3113             GPRTemporary temporary;
3114             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3115
3116             MacroAssembler::JumpList slowCases;
3117
3118             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3119             if (!arrayMode.isOutOfBounds())
3120                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3121             else
3122                 slowCases.append(beyondArrayBounds);
3123
3124             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3125             if (arrayMode.isInBounds()) {
3126                 speculationCheck(
3127                     StoreToHole, JSValueRegs(), 0,
3128                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
3129             } else {
3130                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3131                 if (arrayMode.isSlowPut()) {
3132                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3133                     // the above branch. But it's simply not worth it since this only happens if we're
3134                     // already having a bad time.
3135                     slowCases.append(m_jit.jump());
3136                 } else {
3137                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3138                 
3139                     // If we're writing to a hole we might be growing the array; 
3140                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3141                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3142                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3143                 
3144                     lengthDoesNotNeedUpdate.link(&m_jit);
3145                 }
3146                 notHoleValue.link(&m_jit);
3147             }
3148     
3149             // Store the value to the array.
3150             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3151
3152             base.use();
3153             property.use();
3154             value.use();
3155             storage.use();
3156             
3157             if (!slowCases.empty()) {
3158                 if (node->op() == PutByValDirect) {
3159                     addSlowPathGenerator(slowPathCall(
3160                         slowCases, this,
3161                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3162                         NoResult, baseReg, propertyReg, valueReg));
3163                 } else {
3164                     addSlowPathGenerator(slowPathCall(
3165                         slowCases, this,
3166                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3167                         NoResult, baseReg, propertyReg, valueReg));
3168                 }
3169             }
3170
3171             noResult(node, UseChildrenCalledExplicitly);
3172             break;
3173         }
3174             
3175         default: {
3176             TypedArrayType type = arrayMode.typedArrayType();
3177             if (isInt(type))
3178                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3179             else
3180                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3181         } }
3182
3183         break;
3184     }
3185         
3186     case AtomicsAdd:
3187     case AtomicsAnd:
3188     case AtomicsCompareExchange:
3189     case AtomicsExchange:
3190     case AtomicsLoad:
3191     case AtomicsOr:
3192     case AtomicsStore:
3193     case AtomicsSub:
3194     case AtomicsXor: {
3195         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
3196         Edge baseEdge = m_jit.graph().child(node, 0);
3197         Edge indexEdge = m_jit.graph().child(node, 1);
3198         Edge argEdges[maxNumExtraAtomicsArgs];
3199         for (unsigned i = numExtraArgs; i--;)
3200             argEdges[i] = m_jit.graph().child(node, 2 + i);
3201         Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
3202
3203         GPRReg baseGPR;
3204         GPRReg indexGPR;
3205         GPRReg argGPRs[2];
3206         GPRReg resultGPR;
3207
3208         auto callSlowPath = [&] () {
3209             switch (node->op()) {
3210             case AtomicsAdd:
3211                 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3212                 break;
3213             case AtomicsAnd:
3214                 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3215                 break;
3216             case AtomicsCompareExchange:
3217                 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
3218                 break;
3219             case AtomicsExchange:
3220                 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3221                 break;
3222             case AtomicsLoad:
3223                 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
3224                 break;
3225             case AtomicsOr:
3226                 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3227                 break;
3228             case AtomicsStore:
3229                 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3230                 break;
3231             case AtomicsSub:
3232                 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3233                 break;
3234             case AtomicsXor:
3235                 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3236                 break;
3237             default:
3238                 RELEASE_ASSERT_NOT_REACHED();
3239                 break;
3240             }
3241         };
3242         
3243         if (!storageEdge) {
3244             // We are in generic mode!
3245             JSValueOperand base(this, baseEdge);
3246             JSValueOperand index(this, indexEdge);
3247             std::optional<JSValueOperand> args[2];
3248             baseGPR = base.gpr();
3249             indexGPR = index.gpr();
3250             for (unsigned i = numExtraArgs; i--;) {
3251                 args[i].emplace(this, argEdges[i]);
3252                 argGPRs[i] = args[i]->gpr();
3253             }
3254             
3255             flushRegisters();
3256             GPRFlushedCallResult result(this);
3257             resultGPR = result.gpr();
3258             callSlowPath();
3259             m_jit.exceptionCheck();
3260             
3261             jsValueResult(resultGPR, node);
3262             break;
3263         }
3264         
3265         TypedArrayType type = node->arrayMode().typedArrayType();
3266         
3267         SpeculateCellOperand base(this, baseEdge);
3268         SpeculateStrictInt32Operand index(this, indexEdge);
3269
3270         baseGPR = base.gpr();
3271         indexGPR = index.gpr();
3272         
3273         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
3274         
3275         GPRTemporary args[2];
3276         
3277         JITCompiler::JumpList slowPathCases;
3278         
3279         bool ok = true;
3280         for (unsigned i = numExtraArgs; i--;) {
3281             if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
3282                 noResult(node);
3283                 ok = false;
3284             }
3285             argGPRs[i] = args[i].gpr();
3286         }
3287         if (!ok)
3288             break;
3289         
3290         StorageOperand storage(this, storageEdge);
3291         GPRTemporary oldValue(this);
3292         GPRTemporary result(this);
3293         GPRTemporary newValue(this);
3294         GPRReg storageGPR = storage.gpr();
3295         GPRReg oldValueGPR = oldValue.gpr();
3296         resultGPR = result.gpr();
3297         GPRReg newValueGPR = newValue.gpr();
3298         
3299         // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
3300         // https://bugs.webkit.org/show_bug.cgi?id=170974
3301         m_jit.nop();
3302         
3303         JITCompiler::Label loop = m_jit.label();
3304         
3305         loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
3306         m_jit.move(oldValueGPR, newValueGPR);
3307         m_jit.move(oldValueGPR, resultGPR);
3308         
3309         switch (node->op()) {
3310         case AtomicsAdd:
3311             m_jit.add32(argGPRs[0], newValueGPR);
3312             break;
3313         case AtomicsAnd:
3314             m_jit.and32(argGPRs[0], newValueGPR);
3315             break;
3316         case AtomicsCompareExchange: {
3317             switch (elementSize(type)) {
3318             case 1:
3319                 if (isSigned(type))
3320                     m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
3321                 else
3322                     m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
3323                 break;
3324             case 2:
3325                 if (isSigned(type))
3326                     m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3327                 else
3328                     m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3329                 break;
3330             case 4:
3331                 break;
3332             default:
3333                 RELEASE_ASSERT_NOT_REACHED();
3334                 break;
3335             }
3336             JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3337             m_jit.move(argGPRs[1], newValueGPR);
3338             fail.link(&m_jit);
3339             break;
3340         }
3341         case AtomicsExchange:
3342             m_jit.move(argGPRs[0], newValueGPR);
3343             break;
3344         case AtomicsLoad:
3345             break;
3346         case AtomicsOr:
3347             m_jit.or32(argGPRs[0], newValueGPR);
3348             break;
3349         case AtomicsStore:
3350             m_jit.move(argGPRs[0], newValueGPR);
3351             m_jit.move(argGPRs[0], resultGPR);
3352             break;
3353         case AtomicsSub:
3354             m_jit.sub32(argGPRs[0], newValueGPR);
3355             break;
3356         case AtomicsXor:
3357             m_jit.xor32(argGPRs[0], newValueGPR);
3358             break;
3359         default:
3360             RELEASE_ASSERT_NOT_REACHED();
3361             break;
3362         }
3363         
3364         JITCompiler::JumpList success;
3365         switch (elementSize(type)) {
3366         case 1:
3367             success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3368             break;
3369         case 2:
3370             success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3371             break;
3372         case 4:
3373             success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3374             break;
3375         default:
3376             RELEASE_ASSERT_NOT_REACHED();
3377             break;
3378         }
3379         m_jit.jump().linkTo(loop, &m_jit);
3380         
3381         if (!slowPathCases.empty()) {
3382             slowPathCases.link(&m_jit);
3383             silentSpillAllRegisters(resultGPR);
3384             // Since we spilled, we can do things to registers.
3385             m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3386             m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3387             for (unsigned i = numExtraArgs; i--;)
3388                 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3389             callSlowPath();
3390             silentFillAllRegisters();
3391             m_jit.exceptionCheck();
3392         }
3393         
3394         success.link(&m_jit);
3395         setIntTypedArrayLoadResult(node, resultGPR, type);
3396         break;
3397     }
3398         
3399     case AtomicsIsLockFree: {
3400         if (node->child1().useKind() != Int32Use) {
3401             JSValueOperand operand(this, node->child1());
3402             GPRReg operandGPR = operand.gpr();
3403             flushRegisters();
3404             GPRFlushedCallResult result(this);
3405             GPRReg resultGPR = result.gpr();
3406             callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3407             m_jit.exceptionCheck();
3408             jsValueResult(resultGPR, node);
3409             break;
3410         }
3411
3412         SpeculateInt32Operand operand(this, node->child1());
3413         GPRTemporary result(this);
3414         GPRReg operandGPR = operand.gpr();
3415         GPRReg resultGPR = result.gpr();
3416         m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3417         JITCompiler::JumpList done;
3418         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3419         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3420         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3421         m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3422         done.link(&m_jit);
3423         jsValueResult(resultGPR, node);
3424         break;
3425     }
3426
3427     case RegExpExec: {
3428         compileRegExpExec(node);
3429         break;
3430     }
3431
3432     case RegExpTest: {
3433         compileRegExpTest(node);
3434         break;
3435     }
3436
3437     case StringReplace:
3438     case StringReplaceRegExp: {
3439         compileStringReplace(node);
3440         break;
3441     }
3442         
3443     case GetRegExpObjectLastIndex: {
3444         compileGetRegExpObjectLastIndex(node);
3445         break;
3446     }
3447         
3448     case SetRegExpObjectLastIndex: {
3449         compileSetRegExpObjectLastIndex(node);
3450         break;
3451     }
3452
3453     case RecordRegExpCachedResult: {
3454         compileRecordRegExpCachedResult(node);
3455         break;
3456     }
3457         
3458     case ArrayPush: {
3459         compileArrayPush(node);
3460         break;
3461     }
3462
3463     case ArraySlice: {
3464         compileArraySlice(node);
3465         break;
3466     }
3467
3468     case ArrayIndexOf: {
3469         compileArrayIndexOf(node);
3470         break;
3471     }
3472         
3473     case ArrayPop: {
3474         ASSERT(node->arrayMode().isJSArray());
3475
3476         SpeculateCellOperand base(this, node->child1());
3477         StorageOperand storage(this, node->child2());
3478         GPRTemporary value(this);
3479         GPRTemporary storageLength(this);
3480         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().
3481         
3482         GPRReg baseGPR = base.gpr();
3483         GPRReg storageGPR = storage.gpr();
3484         GPRReg valueGPR = value.gpr();
3485         GPRReg storageLengthGPR = storageLength.gpr();
3486         FPRReg tempFPR = temp.fpr();
3487         
3488         switch (node->arrayMode().type()) {
3489         case Array::Int32:
3490         case Array::Double:
3491         case Array::Contiguous: {
3492             m_jit.load32(
3493                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3494             MacroAssembler::Jump undefinedCase =
3495                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3496             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3497             m_jit.store32(
3498                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3499             MacroAssembler::Jump slowCase;
3500             if (node->arrayMode().type() == Array::Double) {
3501                 m_jit.loadDouble(
3502                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3503                     tempFPR);
3504                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3505                 // length and the new length.
3506                 m_jit.store64(
3507                     MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3508                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3509                 boxDouble(tempFPR, valueGPR);
3510             } else {
3511                 m_jit.load64(
3512                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3513                     valueGPR);
3514                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3515                 // length and the new length.
3516                 m_jit.store64(
3517                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3518                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3519             }
3520
3521             addSlowPathGenerator(
3522                 slowPathMove(
3523                     undefinedCase, this,
3524                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3525             addSlowPathGenerator(
3526                 slowPathCall(
3527                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3528             
3529             // We can't know for sure that the result is an int because of the slow paths. :-/
3530             jsValueResult(valueGPR, node);
3531             break;
3532         }
3533             
3534         case Array::ArrayStorage: {
3535             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3536         
3537             JITCompiler::Jump undefinedCase =
3538                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3539         
3540             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3541         
3542             JITCompiler::JumpList slowCases;
3543             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3544         
3545             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3546             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3547         
3548             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3549         
3550             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight,  ArrayStorage::vectorOffset()));
3551             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3552         
3553             addSlowPathGenerator(
3554                 slowPathMove(
3555                     undefinedCase, this,
3556                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3557         
3558             addSlowPathGenerator(
3559                 slowPathCall(
3560                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3561
3562             jsValueResult(valueGPR, node);
3563             break;
3564         }
3565             
3566         default:
3567             CRASH();
3568             break;
3569         }
3570         break;
3571     }
3572
3573     case DFG::Jump: {
3574         jump(node->targetBlock());
3575         noResult(node);
3576         break;
3577     }
3578
3579     case Branch:
3580         emitBranch(node);
3581         break;
3582         
3583     case Switch:
3584         emitSwitch(node);
3585         break;
3586
3587     case Return: {
3588         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3589         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3590         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3591
3592         // Return the result in returnValueGPR.
3593         JSValueOperand op1(this, node->child1());
3594         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3595
3596         m_jit.emitRestoreCalleeSaves();
3597         m_jit.emitFunctionEpilogue();
3598         m_jit.ret();
3599         
3600         noResult(node);
3601         break;
3602     }
3603         
3604     case Throw: {
3605         compileThrow(node);
3606         break;
3607     }
3608
3609     case ThrowStaticError: {
3610         compileThrowStaticError(node);
3611         break;
3612     }
3613         
3614     case BooleanToNumber: {
3615         switch (node->child1().useKind()) {
3616         case BooleanUse: {
3617             JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3618             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3619             
3620             m_jit.move(value.gpr(), result.gpr());
3621             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3622             DFG_TYPE_CHECK(
3623                 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3624                     JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3625
3626             int32Result(result.gpr(), node);
3627             break;
3628         }
3629             
3630         case UntypedUse: {
3631             JSValueOperand value(this, node->child1());
3632             GPRTemporary result(this);
3633             
3634             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3635                 m_jit.move(value.gpr(), result.gpr());
3636                 m_jit.and32(TrustedImm32(1), result.gpr());
3637                 int32Result(result.gpr(), node);
3638                 break;
3639             }
3640             
3641             m_jit.move(value.gpr(), result.gpr());
3642             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3643             JITCompiler::Jump isBoolean = m_jit.branchTest64(
3644                 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3645             m_jit.move(value.gpr(), result.gpr());
3646             JITCompiler::Jump done = m_jit.jump();
3647             isBoolean.link(&m_jit);
3648             m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3649             done.link(&m_jit);
3650             
3651             jsValueResult(result.gpr(), node);
3652             break;
3653         }
3654             
3655         default:
3656             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3657             break;
3658