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