a5cfcea7b4e714d0d1a5f1bf1fd8f2e2d4d44550
[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             GPRFlushedCallResult result(this);
2450             GPRReg resultGPR = result.gpr();
2451             
2452             flushRegisters();
2453             
2454             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2455             
2456             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2457                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2458                 m_jit.branch64(
2459                     JITCompiler::Equal, resultGPR,
2460                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2461             
2462             strictInt52Result(resultGPR, node);
2463             break;
2464         }
2465             
2466         default:
2467             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2468         }
2469         break;
2470     }
2471
2472     case ValueAdd:
2473         compileValueAdd(node);
2474         break;
2475
2476     case StrCat: {
2477         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2478         JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
2479         JSValueOperand op3(this, node->child3(), ManualOperandSpeculation);
2480         
2481         GPRReg op1GPR = op1.gpr();
2482         GPRReg op2GPR = op2.gpr();
2483         GPRReg op3GPR;
2484         if (node->child3())
2485             op3GPR = op3.gpr();
2486         else
2487             op3GPR = InvalidGPRReg;
2488         
2489         flushRegisters();
2490
2491         GPRFlushedCallResult result(this);
2492         if (node->child3())
2493             callOperation(operationStrCat3, result.gpr(), op1GPR, op2GPR, op3GPR);
2494         else
2495             callOperation(operationStrCat2, result.gpr(), op1GPR, op2GPR);
2496         m_jit.exceptionCheck();
2497         
2498         cellResult(result.gpr(), node);
2499         break;
2500     }
2501
2502     case ArithAdd:
2503         compileArithAdd(node);
2504         break;
2505
2506     case ArithClz32:
2507         compileArithClz32(node);
2508         break;
2509         
2510     case MakeRope:
2511         compileMakeRope(node);
2512         break;
2513
2514     case ArithSub:
2515         compileArithSub(node);
2516         break;
2517
2518     case ArithNegate:
2519         compileArithNegate(node);
2520         break;
2521
2522     case ArithMul:
2523         compileArithMul(node);
2524         break;
2525
2526     case ArithDiv: {
2527         compileArithDiv(node);
2528         break;
2529     }
2530
2531     case ArithMod: {
2532         compileArithMod(node);
2533         break;
2534     }
2535
2536     case ArithAbs:
2537         compileArithAbs(node);
2538         break;
2539         
2540     case ArithMin:
2541     case ArithMax: {
2542         switch (node->binaryUseKind()) {
2543         case Int32Use: {
2544             SpeculateStrictInt32Operand op1(this, node->child1());
2545             SpeculateStrictInt32Operand op2(this, node->child2());
2546             GPRTemporary result(this, Reuse, op1);
2547             
2548             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2549             m_jit.move(op2.gpr(), result.gpr());
2550             if (op1.gpr() != result.gpr()) {
2551                 MacroAssembler::Jump done = m_jit.jump();
2552                 op1Less.link(&m_jit);
2553                 m_jit.move(op1.gpr(), result.gpr());
2554                 done.link(&m_jit);
2555             } else
2556                 op1Less.link(&m_jit);
2557             
2558             int32Result(result.gpr(), node);
2559             break;
2560         }
2561         
2562         case DoubleRepUse: {
2563             SpeculateDoubleOperand op1(this, node->child1());
2564             SpeculateDoubleOperand op2(this, node->child2());
2565             FPRTemporary result(this, op1);
2566             
2567             FPRReg op1FPR = op1.fpr();
2568             FPRReg op2FPR = op2.fpr();
2569             FPRReg resultFPR = result.fpr();
2570         
2571             MacroAssembler::JumpList done;
2572         
2573             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2574         
2575             // op2 is eather the lesser one or one of then is NaN
2576             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2577         
2578             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2579             // op1 + op2 and putting it into result.
2580             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2581             done.append(m_jit.jump());
2582         
2583             op2Less.link(&m_jit);
2584             m_jit.moveDouble(op2FPR, resultFPR);
2585         
2586             if (op1FPR != resultFPR) {
2587                 done.append(m_jit.jump());
2588             
2589                 op1Less.link(&m_jit);
2590                 m_jit.moveDouble(op1FPR, resultFPR);
2591             } else
2592                 op1Less.link(&m_jit);
2593         
2594             done.link(&m_jit);
2595         
2596             doubleResult(resultFPR, node);
2597             break;
2598         }
2599             
2600         default:
2601             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2602             break;
2603         }
2604         break;
2605     }
2606
2607     case ArithPow:
2608         compileArithPow(node);
2609         break;
2610
2611     case ArithSqrt:
2612         compileArithSqrt(node);
2613         break;
2614
2615     case ArithFRound:
2616         compileArithFRound(node);
2617         break;
2618
2619     case ArithRandom:
2620         compileArithRandom(node);
2621         break;
2622
2623     case ArithRound:
2624     case ArithFloor:
2625     case ArithCeil:
2626     case ArithTrunc:
2627         compileArithRounding(node);
2628         break;
2629
2630     case ArithUnary:
2631         compileArithUnary(node);
2632         break;
2633
2634     case LogicalNot:
2635         compileLogicalNot(node);
2636         break;
2637
2638     case CompareLess:
2639         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2640             return;
2641         break;
2642
2643     case CompareLessEq:
2644         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2645             return;
2646         break;
2647
2648     case CompareGreater:
2649         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2650             return;
2651         break;
2652
2653     case CompareGreaterEq:
2654         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2655             return;
2656         break;
2657
2658     case CompareBelow:
2659         compileCompareUnsigned(node, JITCompiler::Below);
2660         break;
2661
2662     case CompareBelowEq:
2663         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2664         break;
2665
2666     case CompareEq:
2667         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2668             return;
2669         break;
2670
2671     case CompareStrictEq:
2672         if (compileStrictEq(node))
2673             return;
2674         break;
2675         
2676     case CompareEqPtr:
2677         compileCompareEqPtr(node);
2678         break;
2679
2680     case StringCharCodeAt: {
2681         compileGetCharCodeAt(node);
2682         break;
2683     }
2684
2685     case StringCharAt: {
2686         // Relies on StringCharAt node having same basic layout as GetByVal
2687         compileGetByValOnString(node);
2688         break;
2689     }
2690
2691     case StringFromCharCode: {
2692         compileFromCharCode(node);
2693         break;
2694     }
2695         
2696     case CheckArray: {
2697         checkArray(node);
2698         break;
2699     }
2700         
2701     case Arrayify:
2702     case ArrayifyToStructure: {
2703         arrayify(node);
2704         break;
2705     }
2706
2707     case GetByVal: {
2708         switch (node->arrayMode().type()) {
2709         case Array::SelectUsingPredictions:
2710         case Array::ForceExit:
2711             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2712             break;
2713         case Array::Undecided: {
2714             SpeculateStrictInt32Operand index(this, node->child2());
2715             GPRTemporary result(this, Reuse, index);
2716             GPRReg indexGPR = index.gpr();
2717             GPRReg resultGPR = result.gpr();
2718
2719             speculationCheck(OutOfBounds, JSValueRegs(), node,
2720                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2721
2722             use(node->child1());
2723             index.use();
2724
2725             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2726             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2727             break;
2728         }
2729         case Array::Generic: {
2730             if (node->child1().useKind() == ObjectUse) {
2731                 if (node->child2().useKind() == StringUse) {
2732                     compileGetByValForObjectWithString(node);
2733                     break;
2734                 }
2735
2736                 if (node->child2().useKind() == SymbolUse) {
2737                     compileGetByValForObjectWithSymbol(node);
2738                     break;
2739                 }
2740             }
2741             JSValueOperand base(this, node->child1());
2742             JSValueOperand property(this, node->child2());
2743             GPRReg baseGPR = base.gpr();
2744             GPRReg propertyGPR = property.gpr();
2745             
2746             flushRegisters();
2747             GPRFlushedCallResult result(this);
2748             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2749             m_jit.exceptionCheck();
2750             
2751             jsValueResult(result.gpr(), node);
2752             break;
2753         }
2754         case Array::Int32:
2755         case Array::Contiguous: {
2756             if (node->arrayMode().isInBounds()) {
2757                 SpeculateStrictInt32Operand property(this, node->child2());
2758                 StorageOperand storage(this, node->child3());
2759                 
2760                 GPRReg propertyReg = property.gpr();
2761                 GPRReg storageReg = storage.gpr();
2762                 
2763                 if (!m_compileOkay)
2764                     return;
2765                 
2766                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2767                 
2768                 GPRTemporary result(this);
2769                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2770                 if (node->arrayMode().isSaneChain()) {
2771                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2772                     JITCompiler::Jump notHole = m_jit.branchTest64(
2773                         MacroAssembler::NonZero, result.gpr());
2774                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2775                     notHole.link(&m_jit);
2776                 } else {
2777                     speculationCheck(
2778                         LoadFromHole, JSValueRegs(), 0,
2779                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2780                 }
2781                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2782                 break;
2783             }
2784             
2785             SpeculateCellOperand base(this, node->child1());
2786             SpeculateStrictInt32Operand property(this, node->child2());
2787             StorageOperand storage(this, node->child3());
2788             
2789             GPRReg baseReg = base.gpr();
2790             GPRReg propertyReg = property.gpr();
2791             GPRReg storageReg = storage.gpr();
2792             
2793             if (!m_compileOkay)
2794                 return;
2795             
2796             GPRTemporary result(this);
2797             GPRReg resultReg = result.gpr();
2798             
2799             MacroAssembler::JumpList slowCases;
2800             
2801             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2802             
2803             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2804             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2805             
2806             addSlowPathGenerator(
2807                 slowPathCall(
2808                     slowCases, this, operationGetByValObjectInt,
2809                     result.gpr(), baseReg, propertyReg));
2810             
2811             jsValueResult(resultReg, node);
2812             break;
2813         }
2814
2815         case Array::Double: {
2816             if (node->arrayMode().isInBounds()) {
2817                 SpeculateStrictInt32Operand property(this, node->child2());
2818                 StorageOperand storage(this, node->child3());
2819             
2820                 GPRReg propertyReg = property.gpr();
2821                 GPRReg storageReg = storage.gpr();
2822             
2823                 if (!m_compileOkay)
2824                     return;
2825             
2826                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2827             
2828                 FPRTemporary result(this);
2829                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2830                 if (!node->arrayMode().isSaneChain())
2831                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2832                 doubleResult(result.fpr(), node);
2833                 break;
2834             }
2835
2836             SpeculateCellOperand base(this, node->child1());
2837             SpeculateStrictInt32Operand property(this, node->child2());
2838             StorageOperand storage(this, node->child3());
2839             
2840             GPRReg baseReg = base.gpr();
2841             GPRReg propertyReg = property.gpr();
2842             GPRReg storageReg = storage.gpr();
2843             
2844             if (!m_compileOkay)
2845                 return;
2846             
2847             GPRTemporary result(this);
2848             FPRTemporary temp(this);
2849             GPRReg resultReg = result.gpr();
2850             FPRReg tempReg = temp.fpr();
2851             
2852             MacroAssembler::JumpList slowCases;
2853             
2854             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2855             
2856             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2857             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2858             boxDouble(tempReg, resultReg);
2859             
2860             addSlowPathGenerator(
2861                 slowPathCall(
2862                     slowCases, this, operationGetByValObjectInt,
2863                     result.gpr(), baseReg, propertyReg));
2864             
2865             jsValueResult(resultReg, node);
2866             break;
2867         }
2868
2869         case Array::ArrayStorage:
2870         case Array::SlowPutArrayStorage: {
2871             if (node->arrayMode().isInBounds()) {
2872                 SpeculateStrictInt32Operand property(this, node->child2());
2873                 StorageOperand storage(this, node->child3());
2874             
2875                 GPRReg propertyReg = property.gpr();
2876                 GPRReg storageReg = storage.gpr();
2877             
2878                 if (!m_compileOkay)
2879                     return;
2880             
2881                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2882             
2883                 GPRTemporary result(this);
2884                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2885                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2886             
2887                 jsValueResult(result.gpr(), node);
2888                 break;
2889             }
2890
2891             SpeculateCellOperand base(this, node->child1());
2892             SpeculateStrictInt32Operand property(this, node->child2());
2893             StorageOperand storage(this, node->child3());
2894             
2895             GPRReg baseReg = base.gpr();
2896             GPRReg propertyReg = property.gpr();
2897             GPRReg storageReg = storage.gpr();
2898             
2899             if (!m_compileOkay)
2900                 return;
2901             
2902             GPRTemporary result(this);
2903             GPRReg resultReg = result.gpr();
2904             
2905             MacroAssembler::JumpList slowCases;
2906             
2907             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2908     
2909             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2910             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2911     
2912             addSlowPathGenerator(
2913                 slowPathCall(
2914                     slowCases, this, operationGetByValObjectInt,
2915                     result.gpr(), baseReg, propertyReg));
2916             
2917             jsValueResult(resultReg, node);
2918             break;
2919         }
2920         case Array::String:
2921             compileGetByValOnString(node);
2922             break;
2923         case Array::DirectArguments:
2924             compileGetByValOnDirectArguments(node);
2925             break;
2926         case Array::ScopedArguments:
2927             compileGetByValOnScopedArguments(node);
2928             break;
2929         default: {
2930             TypedArrayType type = node->arrayMode().typedArrayType();
2931             if (isInt(type))
2932                 compileGetByValOnIntTypedArray(node, type);
2933             else
2934                 compileGetByValOnFloatTypedArray(node, type);
2935         } }
2936         break;
2937     }
2938
2939     case GetByValWithThis: {
2940         JSValueOperand base(this, node->child1());
2941         GPRReg baseGPR = base.gpr();
2942         JSValueOperand thisValue(this, node->child2());
2943         GPRReg thisValueGPR = thisValue.gpr();
2944         JSValueOperand subscript(this, node->child3());
2945         GPRReg subscriptGPR = subscript.gpr();
2946
2947         GPRFlushedCallResult result(this);
2948         GPRReg resultGPR = result.gpr();
2949
2950         flushRegisters();
2951         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2952         m_jit.exceptionCheck();
2953
2954         jsValueResult(resultGPR, node);
2955         break;
2956     }
2957
2958     case PutByValDirect:
2959     case PutByVal:
2960     case PutByValAlias: {
2961         Edge child1 = m_jit.graph().varArgChild(node, 0);
2962         Edge child2 = m_jit.graph().varArgChild(node, 1);
2963         Edge child3 = m_jit.graph().varArgChild(node, 2);
2964         Edge child4 = m_jit.graph().varArgChild(node, 3);
2965         
2966         ArrayMode arrayMode = node->arrayMode().modeForPut();
2967         bool alreadyHandled = false;
2968         
2969         switch (arrayMode.type()) {
2970         case Array::SelectUsingPredictions:
2971         case Array::ForceExit:
2972             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2973             break;
2974         case Array::Generic: {
2975             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2976
2977             if (child1.useKind() == CellUse) {
2978                 if (child2.useKind() == StringUse) {
2979                     compilePutByValForCellWithString(node, child1, child2, child3);
2980                     alreadyHandled = true;
2981                     break;
2982                 }
2983
2984                 if (child2.useKind() == SymbolUse) {
2985                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2986                     alreadyHandled = true;
2987                     break;
2988                 }
2989             }
2990             
2991             JSValueOperand arg1(this, child1);
2992             JSValueOperand arg2(this, child2);
2993             JSValueOperand arg3(this, child3);
2994             GPRReg arg1GPR = arg1.gpr();
2995             GPRReg arg2GPR = arg2.gpr();
2996             GPRReg arg3GPR = arg3.gpr();
2997             flushRegisters();
2998             if (node->op() == PutByValDirect)
2999                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
3000             else
3001                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
3002             m_jit.exceptionCheck();
3003             
3004             noResult(node);
3005             alreadyHandled = true;
3006             break;
3007         }
3008         default:
3009             break;
3010         }
3011         
3012         if (alreadyHandled)
3013             break;
3014         
3015         // FIXME: the base may not be necessary for some array access modes. But we have to
3016         // keep it alive to this point, so it's likely to be in a register anyway. Likely
3017         // no harm in locking it here.
3018         SpeculateCellOperand base(this, child1);
3019         SpeculateStrictInt32Operand property(this, child2);
3020         
3021         GPRReg baseReg = base.gpr();
3022         GPRReg propertyReg = property.gpr();
3023
3024         switch (arrayMode.type()) {
3025         case Array::Int32:
3026         case Array::Contiguous: {
3027             JSValueOperand value(this, child3, ManualOperandSpeculation);
3028
3029             GPRReg valueReg = value.gpr();
3030         
3031             if (!m_compileOkay)
3032                 return;
3033             
3034             if (arrayMode.type() == Array::Int32) {
3035                 DFG_TYPE_CHECK(
3036                     JSValueRegs(valueReg), child3, SpecInt32Only,
3037                     m_jit.branch64(
3038                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
3039             }
3040
3041             StorageOperand storage(this, child4);
3042             GPRReg storageReg = storage.gpr();
3043
3044             if (node->op() == PutByValAlias) {
3045                 // Store the value to the array.
3046                 GPRReg propertyReg = property.gpr();
3047                 GPRReg valueReg = value.gpr();
3048                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3049                 
3050                 noResult(node);
3051                 break;
3052             }
3053             
3054             GPRTemporary temporary;
3055             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3056
3057             MacroAssembler::Jump slowCase;
3058             
3059             if (arrayMode.isInBounds()) {
3060                 speculationCheck(
3061                     OutOfBounds, JSValueRegs(), 0,
3062                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3063             } else {
3064                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3065                 
3066                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3067                 
3068                 if (!arrayMode.isOutOfBounds())
3069                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3070                 
3071                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3072                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3073                 
3074                 inBounds.link(&m_jit);
3075             }
3076             
3077             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3078
3079             base.use();
3080             property.use();
3081             value.use();
3082             storage.use();
3083             
3084             if (arrayMode.isOutOfBounds()) {
3085                 if (node->op() == PutByValDirect) {
3086                     addSlowPathGenerator(slowPathCall(
3087                         slowCase, this,
3088                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3089                         NoResult, baseReg, propertyReg, valueReg));
3090                 } else {
3091                     addSlowPathGenerator(slowPathCall(
3092                         slowCase, this,
3093                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3094                         NoResult, baseReg, propertyReg, valueReg));
3095                 }
3096             }
3097
3098             noResult(node, UseChildrenCalledExplicitly);
3099             break;
3100         }
3101             
3102         case Array::Double: {
3103             compileDoublePutByVal(node, base, property);
3104             break;
3105         }
3106             
3107         case Array::ArrayStorage:
3108         case Array::SlowPutArrayStorage: {
3109             JSValueOperand value(this, child3);
3110
3111             GPRReg valueReg = value.gpr();
3112         
3113             if (!m_compileOkay)
3114                 return;
3115
3116             StorageOperand storage(this, child4);
3117             GPRReg storageReg = storage.gpr();
3118
3119             if (node->op() == PutByValAlias) {
3120                 // Store the value to the array.
3121                 GPRReg propertyReg = property.gpr();
3122                 GPRReg valueReg = value.gpr();
3123                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3124                 
3125                 noResult(node);
3126                 break;
3127             }
3128             
3129             GPRTemporary temporary;
3130             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3131
3132             MacroAssembler::JumpList slowCases;
3133
3134             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3135             if (!arrayMode.isOutOfBounds())
3136                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3137             else
3138                 slowCases.append(beyondArrayBounds);
3139
3140             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3141             if (arrayMode.isInBounds()) {
3142                 speculationCheck(
3143                     StoreToHole, JSValueRegs(), 0,
3144                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
3145             } else {
3146                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3147                 if (arrayMode.isSlowPut()) {
3148                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3149                     // the above branch. But it's simply not worth it since this only happens if we're
3150                     // already having a bad time.
3151                     slowCases.append(m_jit.jump());
3152                 } else {
3153                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3154                 
3155                     // If we're writing to a hole we might be growing the array; 
3156                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3157                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3158                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3159                 
3160                     lengthDoesNotNeedUpdate.link(&m_jit);
3161                 }
3162                 notHoleValue.link(&m_jit);
3163             }
3164     
3165             // Store the value to the array.
3166             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3167
3168             base.use();
3169             property.use();
3170             value.use();
3171             storage.use();
3172             
3173             if (!slowCases.empty()) {
3174                 if (node->op() == PutByValDirect) {
3175                     addSlowPathGenerator(slowPathCall(
3176                         slowCases, this,
3177                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3178                         NoResult, baseReg, propertyReg, valueReg));
3179                 } else {
3180                     addSlowPathGenerator(slowPathCall(
3181                         slowCases, this,
3182                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3183                         NoResult, baseReg, propertyReg, valueReg));
3184                 }
3185             }
3186
3187             noResult(node, UseChildrenCalledExplicitly);
3188             break;
3189         }
3190             
3191         default: {
3192             TypedArrayType type = arrayMode.typedArrayType();
3193             if (isInt(type))
3194                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3195             else
3196                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3197         } }
3198
3199         break;
3200     }
3201         
3202     case AtomicsAdd:
3203     case AtomicsAnd:
3204     case AtomicsCompareExchange:
3205     case AtomicsExchange:
3206     case AtomicsLoad:
3207     case AtomicsOr:
3208     case AtomicsStore:
3209     case AtomicsSub:
3210     case AtomicsXor: {
3211         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
3212         Edge baseEdge = m_jit.graph().child(node, 0);
3213         Edge indexEdge = m_jit.graph().child(node, 1);
3214         Edge argEdges[maxNumExtraAtomicsArgs];
3215         for (unsigned i = numExtraArgs; i--;)
3216             argEdges[i] = m_jit.graph().child(node, 2 + i);
3217         Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
3218
3219         GPRReg baseGPR;
3220         GPRReg indexGPR;
3221         GPRReg argGPRs[2];
3222         GPRReg resultGPR;
3223
3224         auto callSlowPath = [&] () {
3225             switch (node->op()) {
3226             case AtomicsAdd:
3227                 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3228                 break;
3229             case AtomicsAnd:
3230                 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3231                 break;
3232             case AtomicsCompareExchange:
3233                 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
3234                 break;
3235             case AtomicsExchange:
3236                 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3237                 break;
3238             case AtomicsLoad:
3239                 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
3240                 break;
3241             case AtomicsOr:
3242                 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3243                 break;
3244             case AtomicsStore:
3245                 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3246                 break;
3247             case AtomicsSub:
3248                 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3249                 break;
3250             case AtomicsXor:
3251                 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
3252                 break;
3253             default:
3254                 RELEASE_ASSERT_NOT_REACHED();
3255                 break;
3256             }
3257         };
3258         
3259         if (!storageEdge) {
3260             // We are in generic mode!
3261             JSValueOperand base(this, baseEdge);
3262             JSValueOperand index(this, indexEdge);
3263             std::optional<JSValueOperand> args[2];
3264             baseGPR = base.gpr();
3265             indexGPR = index.gpr();
3266             for (unsigned i = numExtraArgs; i--;) {
3267                 args[i].emplace(this, argEdges[i]);
3268                 argGPRs[i] = args[i]->gpr();
3269             }
3270             
3271             GPRFlushedCallResult result(this);
3272             resultGPR = result.gpr();
3273             
3274             flushRegisters();
3275             callSlowPath();
3276             m_jit.exceptionCheck();
3277             
3278             jsValueResult(resultGPR, node);
3279             break;
3280         }
3281         
3282         TypedArrayType type = node->arrayMode().typedArrayType();
3283         
3284         SpeculateCellOperand base(this, baseEdge);
3285         SpeculateStrictInt32Operand index(this, indexEdge);
3286
3287         baseGPR = base.gpr();
3288         indexGPR = index.gpr();
3289         
3290         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
3291         
3292         GPRTemporary args[2];
3293         
3294         JITCompiler::JumpList slowPathCases;
3295         
3296         bool ok = true;
3297         for (unsigned i = numExtraArgs; i--;) {
3298             if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
3299                 noResult(node);
3300                 ok = false;
3301             }
3302             argGPRs[i] = args[i].gpr();
3303         }
3304         if (!ok)
3305             break;
3306         
3307         StorageOperand storage(this, storageEdge);
3308         GPRTemporary oldValue(this);
3309         GPRTemporary result(this);
3310         GPRTemporary newValue(this);
3311         GPRReg storageGPR = storage.gpr();
3312         GPRReg oldValueGPR = oldValue.gpr();
3313         resultGPR = result.gpr();
3314         GPRReg newValueGPR = newValue.gpr();
3315         
3316         // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
3317         // https://bugs.webkit.org/show_bug.cgi?id=170974
3318         m_jit.nop();
3319         
3320         JITCompiler::Label loop = m_jit.label();
3321         
3322         loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
3323         m_jit.move(oldValueGPR, newValueGPR);
3324         m_jit.move(oldValueGPR, resultGPR);
3325         
3326         switch (node->op()) {
3327         case AtomicsAdd:
3328             m_jit.add32(argGPRs[0], newValueGPR);
3329             break;
3330         case AtomicsAnd:
3331             m_jit.and32(argGPRs[0], newValueGPR);
3332             break;
3333         case AtomicsCompareExchange: {
3334             switch (elementSize(type)) {
3335             case 1:
3336                 if (isSigned(type))
3337                     m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
3338                 else
3339                     m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
3340                 break;
3341             case 2:
3342                 if (isSigned(type))
3343                     m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3344                 else
3345                     m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3346                 break;
3347             case 4:
3348                 break;
3349             default:
3350                 RELEASE_ASSERT_NOT_REACHED();
3351                 break;
3352             }
3353             JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3354             m_jit.move(argGPRs[1], newValueGPR);
3355             fail.link(&m_jit);
3356             break;
3357         }
3358         case AtomicsExchange:
3359             m_jit.move(argGPRs[0], newValueGPR);
3360             break;
3361         case AtomicsLoad:
3362             break;
3363         case AtomicsOr:
3364             m_jit.or32(argGPRs[0], newValueGPR);
3365             break;
3366         case AtomicsStore:
3367             m_jit.move(argGPRs[0], newValueGPR);
3368             m_jit.move(argGPRs[0], resultGPR);
3369             break;
3370         case AtomicsSub:
3371             m_jit.sub32(argGPRs[0], newValueGPR);
3372             break;
3373         case AtomicsXor:
3374             m_jit.xor32(argGPRs[0], newValueGPR);
3375             break;
3376         default:
3377             RELEASE_ASSERT_NOT_REACHED();
3378             break;
3379         }
3380         
3381         JITCompiler::JumpList success;
3382         switch (elementSize(type)) {
3383         case 1:
3384             success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3385             break;
3386         case 2:
3387             success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3388             break;
3389         case 4:
3390             success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3391             break;
3392         default:
3393             RELEASE_ASSERT_NOT_REACHED();
3394             break;
3395         }
3396         m_jit.jump().linkTo(loop, &m_jit);
3397         
3398         if (!slowPathCases.empty()) {
3399             slowPathCases.link(&m_jit);
3400             silentSpillAllRegisters(resultGPR);
3401             // Since we spilled, we can do things to registers.
3402             m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3403             m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3404             for (unsigned i = numExtraArgs; i--;)
3405                 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3406             callSlowPath();
3407             silentFillAllRegisters();
3408             m_jit.exceptionCheck();
3409         }
3410         
3411         success.link(&m_jit);
3412         setIntTypedArrayLoadResult(node, resultGPR, type);
3413         break;
3414     }
3415         
3416     case AtomicsIsLockFree: {
3417         if (node->child1().useKind() != Int32Use) {
3418             JSValueOperand operand(this, node->child1());
3419             GPRReg operandGPR = operand.gpr();
3420             GPRFlushedCallResult result(this);
3421             GPRReg resultGPR = result.gpr();
3422             flushRegisters();
3423             callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3424             m_jit.exceptionCheck();
3425             jsValueResult(resultGPR, node);
3426             break;
3427         }
3428
3429         SpeculateInt32Operand operand(this, node->child1());
3430         GPRTemporary result(this);
3431         GPRReg operandGPR = operand.gpr();
3432         GPRReg resultGPR = result.gpr();
3433         m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3434         JITCompiler::JumpList done;
3435         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3436         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3437         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3438         m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3439         done.link(&m_jit);
3440         jsValueResult(resultGPR, node);
3441         break;
3442     }
3443
3444     case RegExpExec: {
3445         bool sample = false;
3446
3447         if (sample)
3448             m_jit.incrementSuperSamplerCount();
3449         
3450         SpeculateCellOperand globalObject(this, node->child1());
3451         GPRReg globalObjectGPR = globalObject.gpr();
3452         
3453         if (node->child2().useKind() == RegExpObjectUse) {
3454             if (node->child3().useKind() == StringUse) {
3455                 SpeculateCellOperand base(this, node->child2());
3456                 SpeculateCellOperand argument(this, node->child3());
3457                 GPRReg baseGPR = base.gpr();
3458                 GPRReg argumentGPR = argument.gpr();
3459                 speculateRegExpObject(node->child2(), baseGPR);
3460                 speculateString(node->child3(), argumentGPR);
3461                 
3462                 flushRegisters();
3463                 GPRFlushedCallResult result(this);
3464                 callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3465                 m_jit.exceptionCheck();
3466                 
3467                 jsValueResult(result.gpr(), node);
3468
3469                 if (sample)
3470                     m_jit.decrementSuperSamplerCount();
3471                 break;
3472             }
3473             
3474             SpeculateCellOperand base(this, node->child2());
3475             JSValueOperand argument(this, node->child3());
3476             GPRReg baseGPR = base.gpr();
3477             GPRReg argumentGPR = argument.gpr();
3478             speculateRegExpObject(node->child2(), baseGPR);
3479         
3480             flushRegisters();
3481             GPRFlushedCallResult result(this);
3482             callOperation(operationRegExpExec, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3483             m_jit.exceptionCheck();
3484         
3485             jsValueResult(result.gpr(), node);
3486
3487             if (sample)
3488                 m_jit.decrementSuperSamplerCount();
3489             break;
3490         }
3491         
3492         JSValueOperand base(this, node->child2());
3493         JSValueOperand argument(this, node->child3());
3494         GPRReg baseGPR = base.gpr();
3495         GPRReg argumentGPR = argument.gpr();
3496         
3497         flushRegisters();
3498         GPRFlushedCallResult result(this);
3499         callOperation(operationRegExpExecGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3500         m_jit.exceptionCheck();
3501         
3502         jsValueResult(result.gpr(), node);
3503
3504         if (sample)
3505             m_jit.decrementSuperSamplerCount();
3506         break;
3507     }
3508
3509     case RegExpTest: {
3510         SpeculateCellOperand globalObject(this, node->child1());
3511         GPRReg globalObjectGPR = globalObject.gpr();
3512         
3513         if (node->child2().useKind() == RegExpObjectUse) {
3514             if (node->child3().useKind() == StringUse) {
3515                 SpeculateCellOperand base(this, node->child2());
3516                 SpeculateCellOperand argument(this, node->child3());
3517                 GPRReg baseGPR = base.gpr();
3518                 GPRReg argumentGPR = argument.gpr();
3519                 speculateRegExpObject(node->child2(), baseGPR);
3520                 speculateString(node->child3(), argumentGPR);
3521                 
3522                 flushRegisters();
3523                 GPRFlushedCallResult result(this);
3524                 callOperation(operationRegExpTestString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3525                 m_jit.exceptionCheck();
3526                 
3527                 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3528                 jsValueResult(result.gpr(), node);
3529                 break;
3530             }
3531             
3532             SpeculateCellOperand base(this, node->child2());
3533             JSValueOperand argument(this, node->child3());
3534             GPRReg baseGPR = base.gpr();
3535             GPRReg argumentGPR = argument.gpr();
3536             speculateRegExpObject(node->child2(), baseGPR);
3537         
3538             flushRegisters();
3539             GPRFlushedCallResult result(this);
3540             callOperation(operationRegExpTest, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3541             m_jit.exceptionCheck();
3542         
3543             m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3544             jsValueResult(result.gpr(), node);
3545             break;
3546         }
3547         
3548         JSValueOperand base(this, node->child2());
3549         JSValueOperand argument(this, node->child3());
3550         GPRReg baseGPR = base.gpr();
3551         GPRReg argumentGPR = argument.gpr();
3552         
3553         flushRegisters();
3554         GPRFlushedCallResult result(this);
3555         callOperation(operationRegExpTestGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3556         m_jit.exceptionCheck();
3557         
3558         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3559         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3560         break;
3561     }
3562
3563     case StringReplace:
3564     case StringReplaceRegExp: {
3565         bool sample = false;
3566
3567         if (sample)
3568             m_jit.incrementSuperSamplerCount();
3569         
3570         if (node->child1().useKind() == StringUse
3571             && node->child2().useKind() == RegExpObjectUse
3572             && node->child3().useKind() == StringUse) {
3573             if (JSString* replace = node->child3()->dynamicCastConstant<JSString*>(*m_jit.vm())) {
3574                 if (!replace->length()) {
3575                     SpeculateCellOperand string(this, node->child1());
3576                     SpeculateCellOperand regExp(this, node->child2());
3577                     GPRReg stringGPR = string.gpr();
3578                     GPRReg regExpGPR = regExp.gpr();
3579                     speculateString(node->child1(), stringGPR);
3580                     speculateRegExpObject(node->child2(), regExpGPR);
3581
3582                     flushRegisters();
3583                     GPRFlushedCallResult result(this);
3584                     callOperation(
3585                         operationStringProtoFuncReplaceRegExpEmptyStr, result.gpr(), stringGPR,
3586                         regExpGPR);
3587                     m_jit.exceptionCheck();
3588                     cellResult(result.gpr(), node);
3589                     if (sample)
3590                         m_jit.decrementSuperSamplerCount();
3591                     break;
3592                 }
3593             }
3594             
3595             SpeculateCellOperand string(this, node->child1());
3596             SpeculateCellOperand regExp(this, node->child2());
3597             SpeculateCellOperand replace(this, node->child3());
3598             GPRReg stringGPR = string.gpr();
3599             GPRReg regExpGPR = regExp.gpr();
3600             GPRReg replaceGPR = replace.gpr();
3601             speculateString(node->child1(), stringGPR);
3602             speculateRegExpObject(node->child2(), regExpGPR);
3603             speculateString(node->child3(), replaceGPR);
3604             
3605             flushRegisters();
3606             GPRFlushedCallResult result(this);
3607             callOperation(
3608                 operationStringProtoFuncReplaceRegExpString, result.gpr(), stringGPR, regExpGPR,
3609                 replaceGPR);
3610             m_jit.exceptionCheck();
3611             cellResult(result.gpr(), node);
3612             if (sample)
3613                 m_jit.decrementSuperSamplerCount();
3614             break;
3615         }
3616
3617         // If we fixed up the edge of child2, we inserted a Check(@child2, String).
3618         OperandSpeculationMode child2SpeculationMode = AutomaticOperandSpeculation;
3619         if (node->child2().useKind() == StringUse)
3620             child2SpeculationMode = ManualOperandSpeculation;
3621
3622         JSValueOperand string(this, node->child1());
3623         JSValueOperand search(this, node->child2(), child2SpeculationMode);
3624         JSValueOperand replace(this, node->child3());
3625         GPRReg stringGPR = string.gpr();
3626         GPRReg searchGPR = search.gpr();
3627         GPRReg replaceGPR = replace.gpr();
3628         
3629         flushRegisters();
3630         GPRFlushedCallResult result(this);
3631         callOperation(
3632             operationStringProtoFuncReplaceGeneric, result.gpr(), stringGPR, searchGPR,
3633             replaceGPR);
3634         m_jit.exceptionCheck();
3635         cellResult(result.gpr(), node);
3636         if (sample)
3637             m_jit.decrementSuperSamplerCount();
3638         break;
3639     }
3640         
3641     case GetRegExpObjectLastIndex: {
3642         compileGetRegExpObjectLastIndex(node);
3643         break;
3644     }
3645         
3646     case SetRegExpObjectLastIndex: {
3647         compileSetRegExpObjectLastIndex(node);
3648         break;
3649     }
3650
3651     case RecordRegExpCachedResult: {
3652         compileRecordRegExpCachedResult(node);
3653         break;
3654     }
3655         
3656     case ArrayPush: {
3657         compileArrayPush(node);
3658         break;
3659     }
3660
3661     case ArraySlice: {
3662         compileArraySlice(node);
3663         break;
3664     }
3665
3666     case ArrayIndexOf: {
3667         compileArrayIndexOf(node);
3668         break;
3669     }
3670