[DFG][FTL] Support MapSet / SetAdd intrinsics
[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 CompareBelow:
2668         compileCompareUnsigned(node, JITCompiler::Below);
2669         break;
2670
2671     case CompareBelowEq:
2672         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2673         break;
2674
2675     case CompareEq:
2676         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2677             return;
2678         break;
2679
2680     case CompareStrictEq:
2681         if (compileStrictEq(node))
2682             return;
2683         break;
2684         
2685     case CompareEqPtr:
2686         compileCompareEqPtr(node);
2687         break;
2688
2689     case StringCharCodeAt: {
2690         compileGetCharCodeAt(node);
2691         break;
2692     }
2693
2694     case StringCharAt: {
2695         // Relies on StringCharAt node having same basic layout as GetByVal
2696         compileGetByValOnString(node);
2697         break;
2698     }
2699
2700     case StringFromCharCode: {
2701         compileFromCharCode(node);
2702         break;
2703     }
2704         
2705     case CheckArray: {
2706         checkArray(node);
2707         break;
2708     }
2709         
2710     case Arrayify:
2711     case ArrayifyToStructure: {
2712         arrayify(node);
2713         break;
2714     }
2715
2716     case GetByVal: {
2717         switch (node->arrayMode().type()) {
2718         case Array::SelectUsingPredictions:
2719         case Array::ForceExit:
2720             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2721             break;
2722         case Array::Undecided: {
2723             SpeculateStrictInt32Operand index(this, node->child2());
2724             GPRTemporary result(this, Reuse, index);
2725             GPRReg indexGPR = index.gpr();
2726             GPRReg resultGPR = result.gpr();
2727
2728             speculationCheck(OutOfBounds, JSValueRegs(), node,
2729                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2730
2731             use(node->child1());
2732             index.use();
2733
2734             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2735             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2736             break;
2737         }
2738         case Array::Generic: {
2739             if (node->child1().useKind() == ObjectUse) {
2740                 if (node->child2().useKind() == StringUse) {
2741                     compileGetByValForObjectWithString(node);
2742                     break;
2743                 }
2744
2745                 if (node->child2().useKind() == SymbolUse) {
2746                     compileGetByValForObjectWithSymbol(node);
2747                     break;
2748                 }
2749             }
2750             JSValueOperand base(this, node->child1());
2751             JSValueOperand property(this, node->child2());
2752             GPRReg baseGPR = base.gpr();
2753             GPRReg propertyGPR = property.gpr();
2754             
2755             flushRegisters();
2756             GPRFlushedCallResult result(this);
2757             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2758             m_jit.exceptionCheck();
2759             
2760             jsValueResult(result.gpr(), node);
2761             break;
2762         }
2763         case Array::Int32:
2764         case Array::Contiguous: {
2765             if (node->arrayMode().isInBounds()) {
2766                 SpeculateStrictInt32Operand property(this, node->child2());
2767                 StorageOperand storage(this, node->child3());
2768                 
2769                 GPRReg propertyReg = property.gpr();
2770                 GPRReg storageReg = storage.gpr();
2771                 
2772                 if (!m_compileOkay)
2773                     return;
2774                 
2775                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2776                 
2777                 GPRTemporary result(this);
2778                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2779                 if (node->arrayMode().isSaneChain()) {
2780                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2781                     JITCompiler::Jump notHole = m_jit.branchTest64(
2782                         MacroAssembler::NonZero, result.gpr());
2783                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2784                     notHole.link(&m_jit);
2785                 } else {
2786                     speculationCheck(
2787                         LoadFromHole, JSValueRegs(), 0,
2788                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2789                 }
2790                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2791                 break;
2792             }
2793             
2794             SpeculateCellOperand base(this, node->child1());
2795             SpeculateStrictInt32Operand property(this, node->child2());
2796             StorageOperand storage(this, node->child3());
2797             
2798             GPRReg baseReg = base.gpr();
2799             GPRReg propertyReg = property.gpr();
2800             GPRReg storageReg = storage.gpr();
2801             
2802             if (!m_compileOkay)
2803                 return;
2804             
2805             GPRTemporary result(this);
2806             GPRReg resultReg = result.gpr();
2807             
2808             MacroAssembler::JumpList slowCases;
2809             
2810             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2811             
2812             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2813             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2814             
2815             addSlowPathGenerator(
2816                 slowPathCall(
2817                     slowCases, this, operationGetByValObjectInt,
2818                     result.gpr(), baseReg, propertyReg));
2819             
2820             jsValueResult(resultReg, node);
2821             break;
2822         }
2823
2824         case Array::Double: {
2825             if (node->arrayMode().isInBounds()) {
2826                 SpeculateStrictInt32Operand property(this, node->child2());
2827                 StorageOperand storage(this, node->child3());
2828             
2829                 GPRReg propertyReg = property.gpr();
2830                 GPRReg storageReg = storage.gpr();
2831             
2832                 if (!m_compileOkay)
2833                     return;
2834             
2835                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2836             
2837                 FPRTemporary result(this);
2838                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2839                 if (!node->arrayMode().isSaneChain())
2840                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2841                 doubleResult(result.fpr(), node);
2842                 break;
2843             }
2844
2845             SpeculateCellOperand base(this, node->child1());
2846             SpeculateStrictInt32Operand property(this, node->child2());
2847             StorageOperand storage(this, node->child3());
2848             
2849             GPRReg baseReg = base.gpr();
2850             GPRReg propertyReg = property.gpr();
2851             GPRReg storageReg = storage.gpr();
2852             
2853             if (!m_compileOkay)
2854                 return;
2855             
2856             GPRTemporary result(this);
2857             FPRTemporary temp(this);
2858             GPRReg resultReg = result.gpr();
2859             FPRReg tempReg = temp.fpr();
2860             
2861             MacroAssembler::JumpList slowCases;
2862             
2863             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2864             
2865             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2866             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2867             boxDouble(tempReg, resultReg);
2868             
2869             addSlowPathGenerator(
2870                 slowPathCall(
2871                     slowCases, this, operationGetByValObjectInt,
2872                     result.gpr(), baseReg, propertyReg));
2873             
2874             jsValueResult(resultReg, node);
2875             break;
2876         }
2877
2878         case Array::ArrayStorage:
2879         case Array::SlowPutArrayStorage: {
2880             if (node->arrayMode().isInBounds()) {
2881                 SpeculateStrictInt32Operand property(this, node->child2());
2882                 StorageOperand storage(this, node->child3());
2883             
2884                 GPRReg propertyReg = property.gpr();
2885                 GPRReg storageReg = storage.gpr();
2886             
2887                 if (!m_compileOkay)
2888                     return;
2889             
2890                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2891             
2892                 GPRTemporary result(this);
2893                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2894                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2895             
2896                 jsValueResult(result.gpr(), node);
2897                 break;
2898             }
2899
2900             SpeculateCellOperand base(this, node->child1());
2901             SpeculateStrictInt32Operand property(this, node->child2());
2902             StorageOperand storage(this, node->child3());
2903             
2904             GPRReg baseReg = base.gpr();
2905             GPRReg propertyReg = property.gpr();
2906             GPRReg storageReg = storage.gpr();
2907             
2908             if (!m_compileOkay)
2909                 return;
2910             
2911             GPRTemporary result(this);
2912             GPRReg resultReg = result.gpr();
2913             
2914             MacroAssembler::JumpList slowCases;
2915             
2916             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2917     
2918             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2919             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2920     
2921             addSlowPathGenerator(
2922                 slowPathCall(
2923                     slowCases, this, operationGetByValObjectInt,
2924                     result.gpr(), baseReg, propertyReg));
2925             
2926             jsValueResult(resultReg, node);
2927             break;
2928         }
2929         case Array::String:
2930             compileGetByValOnString(node);
2931             break;
2932         case Array::DirectArguments:
2933             compileGetByValOnDirectArguments(node);
2934             break;
2935         case Array::ScopedArguments:
2936             compileGetByValOnScopedArguments(node);
2937             break;
2938         default: {
2939             TypedArrayType type = node->arrayMode().typedArrayType();
2940             if (isInt(type))
2941                 compileGetByValOnIntTypedArray(node, type);
2942             else
2943                 compileGetByValOnFloatTypedArray(node, type);
2944         } }
2945         break;
2946     }
2947
2948     case GetByValWithThis: {
2949         JSValueOperand base(this, node->child1());
2950         GPRReg baseGPR = base.gpr();
2951         JSValueOperand thisValue(this, node->child2());
2952         GPRReg thisValueGPR = thisValue.gpr();
2953         JSValueOperand subscript(this, node->child3());
2954         GPRReg subscriptGPR = subscript.gpr();
2955
2956         GPRFlushedCallResult result(this);
2957         GPRReg resultGPR = result.gpr();
2958
2959         flushRegisters();
2960         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2961         m_jit.exceptionCheck();
2962
2963         jsValueResult(resultGPR, node);
2964         break;
2965     }
2966
2967     case PutByValDirect:
2968     case PutByVal:
2969     case PutByValAlias: {
2970         Edge child1 = m_jit.graph().varArgChild(node, 0);
2971         Edge child2 = m_jit.graph().varArgChild(node, 1);
2972         Edge child3 = m_jit.graph().varArgChild(node, 2);
2973         Edge child4 = m_jit.graph().varArgChild(node, 3);
2974         
2975         ArrayMode arrayMode = node->arrayMode().modeForPut();
2976         bool alreadyHandled = false;
2977         
2978         switch (arrayMode.type()) {
2979         case Array::SelectUsingPredictions:
2980         case Array::ForceExit:
2981             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2982             break;
2983         case Array::Generic: {
2984             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2985
2986             if (child1.useKind() == CellUse) {
2987                 if (child2.useKind() == StringUse) {
2988                     compilePutByValForCellWithString(node, child1, child2, child3);
2989                     alreadyHandled = true;
2990                     break;
2991                 }
2992
2993                 if (child2.useKind() == SymbolUse) {
2994                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2995                     alreadyHandled = true;
2996                     break;
2997                 }
2998             }
2999             
3000             JSValueOperand arg1(this, child1);
3001             JSValueOperand arg2(this, child2);
3002             JSValueOperand arg3(this, child3);
3003             GPRReg arg1GPR = arg1.gpr();
3004             GPRReg arg2GPR = arg2.gpr();
3005             GPRReg arg3GPR = arg3.gpr();
3006             flushRegisters();
3007             if (node->op() == PutByValDirect)
3008                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
3009             else
3010                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
3011             m_jit.exceptionCheck();
3012             
3013             noResult(node);
3014             alreadyHandled = true;
3015             break;
3016         }
3017         default:
3018             break;
3019         }
3020         
3021         if (alreadyHandled)
3022             break;
3023         
3024         // FIXME: the base may not be necessary for some array access modes. But we have to
3025         // keep it alive to this point, so it's likely to be in a register anyway. Likely
3026         // no harm in locking it here.
3027         SpeculateCellOperand base(this, child1);
3028         SpeculateStrictInt32Operand property(this, child2);
3029         
3030         GPRReg baseReg = base.gpr();
3031         GPRReg propertyReg = property.gpr();
3032
3033         switch (arrayMode.type()) {
3034         case Array::Int32:
3035         case Array::Contiguous: {
3036             JSValueOperand value(this, child3, ManualOperandSpeculation);
3037
3038             GPRReg valueReg = value.gpr();
3039         
3040             if (!m_compileOkay)
3041                 return;
3042             
3043             if (arrayMode.type() == Array::Int32) {
3044                 DFG_TYPE_CHECK(
3045                     JSValueRegs(valueReg), child3, SpecInt32Only,
3046                     m_jit.branch64(
3047                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
3048             }
3049
3050             StorageOperand storage(this, child4);
3051             GPRReg storageReg = storage.gpr();
3052
3053             if (node->op() == PutByValAlias) {
3054                 // Store the value to the array.
3055                 GPRReg propertyReg = property.gpr();
3056                 GPRReg valueReg = value.gpr();
3057                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3058                 
3059                 noResult(node);
3060                 break;
3061             }
3062             
3063             GPRTemporary temporary;
3064             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3065
3066             MacroAssembler::Jump slowCase;
3067             
3068             if (arrayMode.isInBounds()) {
3069                 speculationCheck(
3070                     OutOfBounds, JSValueRegs(), 0,
3071                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3072             } else {
3073                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3074                 
3075                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3076                 
3077                 if (!arrayMode.isOutOfBounds())
3078                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3079                 
3080                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3081                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3082                 
3083                 inBounds.link(&m_jit);
3084             }
3085             
3086             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3087
3088             base.use();
3089             property.use();
3090             value.use();
3091             storage.use();
3092             
3093             if (arrayMode.isOutOfBounds()) {
3094                 if (node->op() == PutByValDirect) {
3095                     addSlowPathGenerator(slowPathCall(
3096                         slowCase, this,
3097                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3098                         NoResult, baseReg, propertyReg, valueReg));
3099                 } else {
3100                     addSlowPathGenerator(slowPathCall(
3101                         slowCase, this,
3102                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3103                         NoResult, baseReg, propertyReg, valueReg));
3104                 }
3105             }
3106
3107             noResult(node, UseChildrenCalledExplicitly);
3108             break;
3109         }
3110             
3111         case Array::Double: {
3112             compileDoublePutByVal(node, base, property);
3113             break;
3114         }
3115             
3116         case Array::ArrayStorage:
3117         case Array::SlowPutArrayStorage: {
3118             JSValueOperand value(this, child3);
3119
3120             GPRReg valueReg = value.gpr();
3121         
3122             if (!m_compileOkay)
3123                 return;
3124
3125             StorageOperand storage(this, child4);
3126             GPRReg storageReg = storage.gpr();
3127
3128             if (node->op() == PutByValAlias) {
3129                 // Store the value to the array.
3130                 GPRReg propertyReg = property.gpr();
3131                 GPRReg valueReg = value.gpr();
3132                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3133                 
3134                 noResult(node);
3135                 break;
3136             }
3137             
3138             GPRTemporary temporary;
3139             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3140
3141             MacroAssembler::JumpList slowCases;
3142
3143             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3144             if (!arrayMode.isOutOfBounds())
3145                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3146             else
3147                 slowCases.append(beyondArrayBounds);
3148
3149             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3150             if (arrayMode.isInBounds()) {
3151                 speculationCheck(
3152                     StoreToHole, JSValueRegs(), 0,
3153                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
3154             } else {
3155                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3156                 if (arrayMode.isSlowPut()) {
3157                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3158                     // the above branch. But it's simply not worth it since this only happens if we're
3159                     // already having a bad time.
3160                     slowCases.append(m_jit.jump());
3161                 } else {
3162                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3163                 
3164                     // If we're writing to a hole we might be growing the array; 
3165                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3166                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3167                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3168                 
3169                     lengthDoesNotNeedUpdate.link(&m_jit);
3170                 }
3171                 notHoleValue.link(&m_jit);
3172             }
3173     
3174             // Store the value to the array.
3175             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3176
3177             base.use();
3178             property.use();
3179             value.use();
3180             storage.use();
3181             
3182             if (!slowCases.empty()) {
3183                 if (node->op() == PutByValDirect) {
3184                     addSlowPathGenerator(slowPathCall(
3185                         slowCases, this,
3186                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3187                         NoResult, baseReg, propertyReg, valueReg));
3188                 } else {
3189    &nb