OSR entry: delay outer-loop compilation when at inner-loop
[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 "CallFrameShuffler.h"
33 #include "DFGAbstractInterpreterInlines.h"
34 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
35 #include "DFGOperations.h"
36 #include "DFGSlowPathGenerator.h"
37 #include "DirectArguments.h"
38 #include "GetterSetter.h"
39 #include "HasOwnPropertyCache.h"
40 #include "JSCInlines.h"
41 #include "JSEnvironmentRecord.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::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
192 {
193     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
194     RegisterSet usedRegisters = this->usedRegisters();
195     if (spillMode == DontSpill) {
196         // We've already flushed registers to the stack, we don't need to spill these.
197         usedRegisters.set(baseGPR, false);
198         usedRegisters.set(valueGPR, false);
199     }
200
201     JITPutByIdGenerator gen(
202         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, JSValueRegs(baseGPR),
203         JSValueRegs(valueGPR), scratchGPR, m_jit.ecmaModeFor(codeOrigin), putKind);
204
205     gen.generateFastPath(m_jit);
206     
207     JITCompiler::JumpList slowCases;
208     if (slowPathTarget.isSet())
209         slowCases.append(slowPathTarget);
210     slowCases.append(gen.slowPathJump());
211     
212     auto slowPath = slowPathCall(
213         slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), valueGPR, baseGPR,
214         identifierUID(identifierNumber));
215
216     m_jit.addPutById(gen, slowPath.get());
217     addSlowPathGenerator(WTFMove(slowPath));
218 }
219
220 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
221 {
222     ASSERT_WITH_MESSAGE(!masqueradesAsUndefinedWatchpointIsStillValid() || !isKnownCell(operand.node()), "The Compare should have been eliminated, it is known to be always false.");
223
224     JSValueOperand arg(this, operand, ManualOperandSpeculation);
225     GPRReg argGPR = arg.gpr();
226     
227     GPRTemporary result(this);
228     GPRReg resultGPR = result.gpr();
229
230     m_jit.move(TrustedImm32(0), resultGPR);
231
232     JITCompiler::JumpList done;
233     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
234         if (!isKnownNotCell(operand.node()))
235             done.append(m_jit.branchIfCell(JSValueRegs(argGPR)));
236     } else {
237         GPRTemporary localGlobalObject(this);
238         GPRTemporary remoteGlobalObject(this);
239         GPRTemporary scratch(this);
240
241         JITCompiler::Jump notCell;
242         if (!isKnownCell(operand.node()))
243             notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
244         
245         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
246             JITCompiler::Zero,
247             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
248             JITCompiler::TrustedImm32(MasqueradesAsUndefined));
249         done.append(isNotMasqueradesAsUndefined);
250
251         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
252         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
253         m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
254         m_jit.emitLoadStructure(argGPR, resultGPR, scratch.gpr());
255         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
256         m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
257         done.append(m_jit.jump());
258         if (!isKnownCell(operand.node()))
259             notCell.link(&m_jit);
260     }
261  
262     if (!isKnownNotOther(operand.node())) {
263         m_jit.move(argGPR, resultGPR);
264         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
265         m_jit.compare64(JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
266     }
267
268     done.link(&m_jit);
269  
270     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
271     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
272 }
273
274 void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode)
275 {
276     ASSERT_WITH_MESSAGE(!masqueradesAsUndefinedWatchpointIsStillValid() || !isKnownCell(operand.node()), "The Compare should have been eliminated, it is known to be always false.");
277
278     BasicBlock* taken = branchNode->branchData()->taken.block;
279     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
280
281     JSValueOperand arg(this, operand, ManualOperandSpeculation);
282     GPRReg argGPR = arg.gpr();
283     
284     GPRTemporary result(this, Reuse, arg);
285     GPRReg resultGPR = result.gpr();
286
287     // First, handle the case where "operand" is a cell.
288     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
289         if (!isKnownNotCell(operand.node())) {
290             JITCompiler::Jump isCell = m_jit.branchIfCell(JSValueRegs(argGPR));
291             addBranch(isCell, notTaken);
292         }
293     } else {
294         GPRTemporary localGlobalObject(this);
295         GPRTemporary remoteGlobalObject(this);
296         GPRTemporary scratch(this);
297
298         JITCompiler::Jump notCell;
299         if (!isKnownCell(operand.node()))
300             notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
301         
302         branchTest8(JITCompiler::Zero, 
303             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
304             JITCompiler::TrustedImm32(MasqueradesAsUndefined), notTaken);
305
306         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
307         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
308         m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
309         m_jit.emitLoadStructure(argGPR, resultGPR, scratch.gpr());
310         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
311         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
312
313         if (!isKnownCell(operand.node())) {
314             jump(notTaken, ForceJump);
315             notCell.link(&m_jit);
316         }
317     }
318
319     if (isKnownNotOther(operand.node()))
320         jump(notTaken);
321     else {
322         JITCompiler::RelationalCondition condition = JITCompiler::Equal;
323         if (taken == nextBlock()) {
324             condition = JITCompiler::NotEqual;
325             std::swap(taken, notTaken);
326         }
327         m_jit.move(argGPR, resultGPR);
328         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
329         branch64(condition, resultGPR, JITCompiler::TrustedImm64(ValueNull), taken);
330         jump(notTaken);
331     }
332 }
333
334 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
335 {
336     BasicBlock* taken = branchNode->branchData()->taken.block;
337     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
338
339     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
340
341     // The branch instruction will branch to the taken block.
342     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
343     if (taken == nextBlock()) {
344         cond = JITCompiler::invert(cond);
345         callResultCondition = JITCompiler::Zero;
346         BasicBlock* tmp = taken;
347         taken = notTaken;
348         notTaken = tmp;
349     }
350
351     JSValueOperand arg1(this, node->child1());
352     JSValueOperand arg2(this, node->child2());
353     GPRReg arg1GPR = arg1.gpr();
354     GPRReg arg2GPR = arg2.gpr();
355     
356     JITCompiler::JumpList slowPath;
357     
358     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
359         GPRFlushedCallResult result(this);
360         GPRReg resultGPR = result.gpr();
361     
362         arg1.use();
363         arg2.use();
364     
365         flushRegisters();
366         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
367         m_jit.exceptionCheck();
368
369         branchTest32(callResultCondition, resultGPR, taken);
370     } else {
371         GPRTemporary result(this, Reuse, arg2);
372         GPRReg resultGPR = result.gpr();
373     
374         arg1.use();
375         arg2.use();
376     
377         if (!isKnownInteger(node->child1().node()))
378             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
379         if (!isKnownInteger(node->child2().node()))
380             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
381     
382         branch32(cond, arg1GPR, arg2GPR, taken);
383     
384         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
385             jump(notTaken, ForceJump);
386     
387             slowPath.link(&m_jit);
388     
389             silentSpillAllRegisters(resultGPR);
390             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
391             silentFillAllRegisters(resultGPR);
392             m_jit.exceptionCheck();
393         
394             branchTest32(callResultCondition, resultGPR, taken);
395         }
396     }
397
398     jump(notTaken);
399
400     m_indexInBlock = m_block->size() - 1;
401     m_currentNode = branchNode;
402 }
403
404 template<typename JumpType>
405 class CompareAndBoxBooleanSlowPathGenerator
406     : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {
407 public:
408     CompareAndBoxBooleanSlowPathGenerator(
409         JumpType from, SpeculativeJIT* jit,
410         S_JITOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)
411         : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(
412             from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result)
413         , m_arg1(arg1)
414         , m_arg2(arg2)
415     {
416     }
417     
418 protected:
419     void generateInternal(SpeculativeJIT* jit) override
420     {
421         this->setUp(jit);
422         this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));
423         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
424         jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);
425         this->tearDown(jit);
426     }
427    
428 private:
429     GPRReg m_arg1;
430     GPRReg m_arg2;
431 };
432
433 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
434 {
435     ASSERT(node->isBinaryUseKind(UntypedUse));
436     JSValueOperand arg1(this, node->child1());
437     JSValueOperand arg2(this, node->child2());
438     GPRReg arg1GPR = arg1.gpr();
439     GPRReg arg2GPR = arg2.gpr();
440     
441     JITCompiler::JumpList slowPath;
442     
443     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
444         GPRFlushedCallResult result(this);
445         GPRReg resultGPR = result.gpr();
446     
447         arg1.use();
448         arg2.use();
449     
450         flushRegisters();
451         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
452         m_jit.exceptionCheck();
453         
454         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
455         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
456     } else {
457         GPRTemporary result(this, Reuse, arg2);
458         GPRReg resultGPR = result.gpr();
459
460         arg1.use();
461         arg2.use();
462     
463         if (!isKnownInteger(node->child1().node()))
464             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
465         if (!isKnownInteger(node->child2().node()))
466             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
467     
468         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
469         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
470         
471         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
472             addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>>(
473                 slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR));
474         }
475
476         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
477     }
478 }
479
480 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
481 {
482     BasicBlock* taken = branchNode->branchData()->taken.block;
483     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
484
485     // The branch instruction will branch to the taken block.
486     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
487     if (taken == nextBlock()) {
488         invert = !invert;
489         BasicBlock* tmp = taken;
490         taken = notTaken;
491         notTaken = tmp;
492     }
493     
494     JSValueOperand arg1(this, node->child1());
495     JSValueOperand arg2(this, node->child2());
496     GPRReg arg1GPR = arg1.gpr();
497     GPRReg arg2GPR = arg2.gpr();
498     
499     GPRTemporary result(this);
500     GPRReg resultGPR = result.gpr();
501     
502     arg1.use();
503     arg2.use();
504     
505     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
506         // see if we get lucky: if the arguments are cells and they reference the same
507         // cell, then they must be strictly equal.
508         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
509         
510         silentSpillAllRegisters(resultGPR);
511         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
512         silentFillAllRegisters(resultGPR);
513         m_jit.exceptionCheck();
514         
515         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
516     } else {
517         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
518         
519         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
520         
521         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
522         JITCompiler::Jump leftDouble = m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
523         leftOK.link(&m_jit);
524         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
525         JITCompiler::Jump rightDouble = m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
526         rightOK.link(&m_jit);
527         
528         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
529         jump(notTaken, ForceJump);
530         
531         twoCellsCase.link(&m_jit);
532         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
533         
534         leftDouble.link(&m_jit);
535         rightDouble.link(&m_jit);
536         
537         silentSpillAllRegisters(resultGPR);
538         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
539         silentFillAllRegisters(resultGPR);
540         m_jit.exceptionCheck();
541         
542         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
543     }
544     
545     jump(notTaken);
546 }
547
548 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
549 {
550     JSValueOperand arg1(this, node->child1());
551     JSValueOperand arg2(this, node->child2());
552     GPRReg arg1GPR = arg1.gpr();
553     GPRReg arg2GPR = arg2.gpr();
554     
555     GPRTemporary result(this);
556     GPRReg resultGPR = result.gpr();
557     
558     arg1.use();
559     arg2.use();
560     
561     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
562         // see if we get lucky: if the arguments are cells and they reference the same
563         // cell, then they must be strictly equal.
564         // FIXME: this should flush registers instead of silent spill/fill.
565         JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR);
566         
567         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
568         
569         JITCompiler::Jump done = m_jit.jump();
570
571         notEqualCase.link(&m_jit);
572         
573         silentSpillAllRegisters(resultGPR);
574         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
575         silentFillAllRegisters(resultGPR);
576         m_jit.exceptionCheck();
577         
578         m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);
579         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
580         
581         done.link(&m_jit);
582     } else {
583         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
584         
585         JITCompiler::JumpList slowPathCases;
586         
587         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
588         
589         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
590         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister));
591         leftOK.link(&m_jit);
592         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
593         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister));
594         rightOK.link(&m_jit);
595         
596         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
597         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
598         
599         JITCompiler::Jump done = m_jit.jump();
600         
601         twoCellsCase.link(&m_jit);
602         slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR));
603         
604         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
605         
606         addSlowPathGenerator(std::make_unique<CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>>(
607                     slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR,
608                     arg2GPR));
609         
610         done.link(&m_jit);
611     }
612     
613     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
614 }
615
616 void SpeculativeJIT::compileMiscStrictEq(Node* node)
617 {
618     JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
619     JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
620     GPRTemporary result(this);
621     
622     if (node->child1().useKind() == MiscUse)
623         speculateMisc(node->child1(), op1.jsValueRegs());
624     if (node->child2().useKind() == MiscUse)
625         speculateMisc(node->child2(), op2.jsValueRegs());
626     
627     m_jit.compare64(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
628     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
629     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
630 }
631
632 void SpeculativeJIT::emitCall(Node* node)
633 {
634     CallLinkInfo::CallType callType;
635     bool isVarargs = false;
636     bool isForwardVarargs = false;
637     bool isTail = false;
638     bool isEmulatedTail = false;
639     bool isDirect = false;
640     switch (node->op()) {
641     case Call:
642     case CallEval:
643         callType = CallLinkInfo::Call;
644         break;
645     case TailCall:
646         callType = CallLinkInfo::TailCall;
647         isTail = true;
648         break;
649     case TailCallInlinedCaller:
650         callType = CallLinkInfo::Call;
651         isEmulatedTail = true;
652         break;
653     case Construct:
654         callType = CallLinkInfo::Construct;
655         break;
656     case CallVarargs:
657         callType = CallLinkInfo::CallVarargs;
658         isVarargs = true;
659         break;
660     case TailCallVarargs:
661         callType = CallLinkInfo::TailCallVarargs;
662         isVarargs = true;
663         isTail = true;
664         break;
665     case TailCallVarargsInlinedCaller:
666         callType = CallLinkInfo::CallVarargs;
667         isVarargs = true;
668         isEmulatedTail = true;
669         break;
670     case ConstructVarargs:
671         callType = CallLinkInfo::ConstructVarargs;
672         isVarargs = true;
673         break;
674     case CallForwardVarargs:
675         callType = CallLinkInfo::CallVarargs;
676         isForwardVarargs = true;
677         break;
678     case ConstructForwardVarargs:
679         callType = CallLinkInfo::ConstructVarargs;
680         isForwardVarargs = true;
681         break;
682     case TailCallForwardVarargs:
683         callType = CallLinkInfo::TailCallVarargs;
684         isTail = true;
685         isForwardVarargs = true;
686         break;
687     case TailCallForwardVarargsInlinedCaller:
688         callType = CallLinkInfo::CallVarargs;
689         isEmulatedTail = true;
690         isForwardVarargs = true;
691         break;
692     case DirectCall:
693         callType = CallLinkInfo::DirectCall;
694         isDirect = true;
695         break;
696     case DirectConstruct:
697         callType = CallLinkInfo::DirectConstruct;
698         isDirect = true;
699         break;
700     case DirectTailCall:
701         callType = CallLinkInfo::DirectTailCall;
702         isTail = true;
703         isDirect = true;
704         break;
705     case DirectTailCallInlinedCaller:
706         callType = CallLinkInfo::DirectCall;
707         isEmulatedTail = true;
708         isDirect = true;
709         break;
710     default:
711         DFG_CRASH(m_jit.graph(), node, "bad node type");
712         break;
713     }
714
715     GPRReg calleeGPR = InvalidGPRReg;
716     CallFrameShuffleData shuffleData;
717     
718     ExecutableBase* executable = nullptr;
719     FunctionExecutable* functionExecutable = nullptr;
720     if (isDirect) {
721         executable = node->castOperand<ExecutableBase*>();
722         functionExecutable = jsDynamicCast<FunctionExecutable*>(executable);
723     }
724     
725     unsigned numPassedArgs = 0;
726     unsigned numAllocatedArgs = 0;
727     
728     // Gotta load the arguments somehow. Varargs is trickier.
729     if (isVarargs || isForwardVarargs) {
730         RELEASE_ASSERT(!isDirect);
731         CallVarargsData* data = node->callVarargsData();
732
733         GPRReg resultGPR;
734         unsigned numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
735         
736         if (isForwardVarargs) {
737             flushRegisters();
738             if (node->child3())
739                 use(node->child3());
740             
741             GPRReg scratchGPR1;
742             GPRReg scratchGPR2;
743             GPRReg scratchGPR3;
744             
745             scratchGPR1 = JITCompiler::selectScratchGPR();
746             scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1);
747             scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2);
748             
749             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
750             JITCompiler::JumpList slowCase;
751             InlineCallFrame* inlineCallFrame;
752             if (node->child3())
753                 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame;
754             else
755                 inlineCallFrame = node->origin.semantic.inlineCallFrame;
756             emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
757             JITCompiler::Jump done = m_jit.jump();
758             slowCase.link(&m_jit);
759             callOperation(operationThrowStackOverflowForVarargs);
760             m_jit.exceptionCheck();
761             m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
762             done.link(&m_jit);
763             resultGPR = scratchGPR2;
764         } else {
765             GPRReg argumentsGPR;
766             GPRReg scratchGPR1;
767             GPRReg scratchGPR2;
768             GPRReg scratchGPR3;
769             
770             auto loadArgumentsGPR = [&] (GPRReg reservedGPR) {
771                 if (reservedGPR != InvalidGPRReg)
772                     lock(reservedGPR);
773                 JSValueOperand arguments(this, node->child3());
774                 argumentsGPR = arguments.gpr();
775                 if (reservedGPR != InvalidGPRReg)
776                     unlock(reservedGPR);
777                 flushRegisters();
778                 
779                 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsGPR, reservedGPR);
780                 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, reservedGPR);
781                 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, scratchGPR2, reservedGPR);
782             };
783             
784             loadArgumentsGPR(InvalidGPRReg);
785             
786             DFG_ASSERT(m_jit.graph(), node, isFlushed());
787             
788             // Right now, arguments is in argumentsGPR and the register file is flushed.
789             callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsGPR, numUsedStackSlots, data->firstVarArgOffset);
790             m_jit.exceptionCheck();
791             
792             // Now we have the argument count of the callee frame, but we've lost the arguments operand.
793             // Reconstruct the arguments operand while preserving the callee frame.
794             loadArgumentsGPR(GPRInfo::returnValueGPR);
795             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);
796             emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);
797             m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);
798             
799             callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR);
800             m_jit.exceptionCheck();
801             resultGPR = GPRInfo::returnValueGPR;
802         }
803         
804         m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), resultGPR, JITCompiler::stackPointerRegister);
805         
806         DFG_ASSERT(m_jit.graph(), node, isFlushed());
807         
808         // We don't need the arguments array anymore.
809         if (isVarargs)
810             use(node->child3());
811
812         // Now set up the "this" argument.
813         JSValueOperand thisArgument(this, node->child2());
814         GPRReg thisArgumentGPR = thisArgument.gpr();
815         thisArgument.use();
816         
817         m_jit.store64(thisArgumentGPR, JITCompiler::calleeArgumentSlot(0));
818     } else {
819         // The call instruction's first child is the function; the subsequent children are the
820         // arguments.
821         numPassedArgs = node->numChildren() - 1;
822         numAllocatedArgs = numPassedArgs;
823         
824         if (functionExecutable) {
825             // Allocate more args if this would let us avoid arity checks. This is throttled by
826             // CallLinkInfo's limit. It's probably good to throttle it - if the callee wants a
827             // ginormous amount of argument space then it's better for them to do it so that when we
828             // make calls to other things, we don't waste space.
829             unsigned desiredNumAllocatedArgs = static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
830             if (desiredNumAllocatedArgs <= Options::maximumDirectCallStackSize()) {
831                 numAllocatedArgs = std::max(numAllocatedArgs, desiredNumAllocatedArgs);
832                 
833                 // Whoever converts to DirectCall should do this adjustment. It's too late for us to
834                 // do this adjustment now since we will have already emitted code that relied on the
835                 // value of m_parameterSlots.
836                 DFG_ASSERT(
837                     m_jit.graph(), node,
838                     Graph::parameterSlotsForArgCount(numAllocatedArgs)
839                     <= m_jit.graph().m_parameterSlots);
840             }
841         }
842
843         if (isTail) {
844             Edge calleeEdge = m_jit.graph().child(node, 0);
845             JSValueOperand callee(this, calleeEdge);
846             calleeGPR = callee.gpr();
847             if (!isDirect)
848                 callee.use();
849
850             shuffleData.tagTypeNumber = GPRInfo::tagTypeNumberRegister;
851             shuffleData.numLocals = m_jit.graph().frameRegisterCount();
852             shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatJS);
853             shuffleData.args.resize(numAllocatedArgs);
854             shuffleData.numPassedArgs = numPassedArgs;
855             
856             for (unsigned i = 0; i < numPassedArgs; ++i) {
857                 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
858                 GenerationInfo& info = generationInfo(argEdge.node());
859                 if (!isDirect)
860                     use(argEdge);
861                 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
862             }
863             
864             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
865                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
866
867             shuffleData.setupCalleeSaveRegisters(m_jit.codeBlock());
868         } else {
869             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCount));
870
871             for (unsigned i = 0; i < numPassedArgs; i++) {
872                 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
873                 JSValueOperand arg(this, argEdge);
874                 GPRReg argGPR = arg.gpr();
875                 use(argEdge);
876                 
877                 m_jit.store64(argGPR, JITCompiler::calleeArgumentSlot(i));
878             }
879             
880             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
881                 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
882         }
883     }
884     
885     if (!isTail || isVarargs || isForwardVarargs) {
886         Edge calleeEdge = m_jit.graph().child(node, 0);
887         JSValueOperand callee(this, calleeEdge);
888         calleeGPR = callee.gpr();
889         callee.use();
890         m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
891
892         flushRegisters();
893     }
894
895     CodeOrigin staticOrigin = node->origin.semantic;
896     ASSERT(!isTail || !staticOrigin.inlineCallFrame || !staticOrigin.inlineCallFrame->getCallerSkippingTailCalls());
897     ASSERT(!isEmulatedTail || (staticOrigin.inlineCallFrame && staticOrigin.inlineCallFrame->getCallerSkippingTailCalls()));
898     CodeOrigin dynamicOrigin =
899         isEmulatedTail ? *staticOrigin.inlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
900
901     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
902     
903     auto setResultAndResetStack = [&] () {
904         GPRFlushedCallResult result(this);
905         GPRReg resultGPR = result.gpr();
906         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
907
908         jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
909
910         // After the calls are done, we need to reestablish our stack
911         // pointer. We rely on this for varargs calls, calls with arity
912         // mismatch (the callframe is slided) and tail calls.
913         m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
914     };
915     
916     CallLinkInfo* callLinkInfo = m_jit.codeBlock()->addCallLinkInfo();
917     callLinkInfo->setUpCall(callType, m_currentNode->origin.semantic, calleeGPR);
918
919     if (node->op() == CallEval) {
920         // We want to call operationCallEval but we don't want to overwrite the parameter area in
921         // which we have created a prototypical eval call frame. This means that we have to
922         // subtract stack to make room for the call. Lucky for us, at this point we have the whole
923         // register file to ourselves.
924         
925         m_jit.emitStoreCallSiteIndex(callSite);
926         m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
927         m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
928         
929         // Now we need to make room for:
930         // - The caller frame and PC of a call to operationCallEval.
931         // - Potentially two arguments on the stack.
932         unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
933         requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
934         m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
935         m_jit.setupArgumentsWithExecState(GPRInfo::regT0);
936         prepareForExternalCall();
937         m_jit.appendCall(operationCallEval);
938         m_jit.exceptionCheck();
939         JITCompiler::Jump done = m_jit.branchTest64(JITCompiler::NonZero, GPRInfo::returnValueGPR);
940         
941         // This is the part where we meant to make a normal call. Oops.
942         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
943         m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
944         m_jit.emitDumbVirtualCall(callLinkInfo);
945         
946         done.link(&m_jit);
947         setResultAndResetStack();
948         return;
949     }
950     
951     if (isDirect) {
952         callLinkInfo->setExecutableDuringCompilation(executable);
953         callLinkInfo->setMaxNumArguments(numAllocatedArgs);
954
955         if (isTail) {
956             RELEASE_ASSERT(node->op() == DirectTailCall);
957             
958             JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
959             JITCompiler::Label mainPath = m_jit.label();
960             
961             m_jit.emitStoreCallSiteIndex(callSite);
962             
963             callLinkInfo->setFrameShuffleData(shuffleData);
964             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
965             
966             JITCompiler::Call call = m_jit.nearTailCall();
967             
968             JITCompiler::Label slowPath = m_jit.label();
969             patchableJump.m_jump.linkTo(slowPath, &m_jit);
970             
971             silentSpillAllRegisters(InvalidGPRReg);
972             callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
973             silentFillAllRegisters(InvalidGPRReg);
974             m_jit.exceptionCheck();
975             m_jit.jump().linkTo(mainPath, &m_jit);
976             
977             useChildren(node);
978             
979             m_jit.addJSDirectTailCall(patchableJump, call, slowPath, callLinkInfo);
980             return;
981         }
982         
983         JITCompiler::Label mainPath = m_jit.label();
984         
985         m_jit.emitStoreCallSiteIndex(callSite);
986         
987         JITCompiler::Call call = m_jit.nearCall();
988         JITCompiler::Jump done = m_jit.jump();
989         
990         JITCompiler::Label slowPath = m_jit.label();
991         if (isX86())
992             m_jit.pop(JITCompiler::selectScratchGPR(calleeGPR));
993
994         callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
995         m_jit.exceptionCheck();
996         m_jit.jump().linkTo(mainPath, &m_jit);
997         
998         done.link(&m_jit);
999         
1000         setResultAndResetStack();
1001         
1002         m_jit.addJSDirectCall(call, slowPath, callLinkInfo);
1003         return;
1004     }
1005     
1006     m_jit.emitStoreCallSiteIndex(callSite);
1007     
1008     JITCompiler::DataLabelPtr targetToCheck;
1009     JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
1010
1011     if (isTail) {
1012         if (node->op() == TailCall) {
1013             callLinkInfo->setFrameShuffleData(shuffleData);
1014             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
1015         } else {
1016             m_jit.emitRestoreCalleeSaves();
1017             m_jit.prepareForTailCallSlow();
1018         }
1019     }
1020
1021     JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
1022
1023     JITCompiler::Jump done = m_jit.jump();
1024
1025     slowPath.link(&m_jit);
1026
1027     if (node->op() == TailCall) {
1028         CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
1029         callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
1030         callFrameShuffler.prepareForSlowPath();
1031     } else {
1032         m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
1033
1034         if (isTail)
1035             m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
1036     }
1037
1038     m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
1039     JITCompiler::Call slowCall = m_jit.nearCall();
1040
1041     done.link(&m_jit);
1042
1043     if (isTail)
1044         m_jit.abortWithReason(JITDidReturnFromTailCall);
1045     else
1046         setResultAndResetStack();
1047
1048     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
1049 }
1050
1051 // Clang should allow unreachable [[clang::fallthrough]] in template functions if any template expansion uses it
1052 // http://llvm.org/bugs/show_bug.cgi?id=18619
1053 #if COMPILER(CLANG) && defined(__has_warning)
1054 #pragma clang diagnostic push
1055 #if __has_warning("-Wimplicit-fallthrough")
1056 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
1057 #endif
1058 #endif
1059 template<bool strict>
1060 GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
1061 {
1062     AbstractValue& value = m_state.forNode(edge);
1063     SpeculatedType type = value.m_type;
1064     ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
1065
1066     m_interpreter.filter(value, SpecInt32Only);
1067     if (value.isClear()) {
1068         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1069         returnFormat = DataFormatInt32;
1070         return allocate();
1071     }
1072
1073     VirtualRegister virtualRegister = edge->virtualRegister();
1074     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1075
1076     switch (info.registerFormat()) {
1077     case DataFormatNone: {
1078         GPRReg gpr = allocate();
1079
1080         if (edge->hasConstant()) {
1081             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1082             ASSERT(edge->isInt32Constant());
1083             m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
1084             info.fillInt32(*m_stream, gpr);
1085             returnFormat = DataFormatInt32;
1086             return gpr;
1087         }
1088         
1089         DataFormat spillFormat = info.spillFormat();
1090         
1091         DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
1092         
1093         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1094         
1095         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
1096             // If we know this was spilled as an integer we can fill without checking.
1097             if (strict) {
1098                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1099                 info.fillInt32(*m_stream, gpr);
1100                 returnFormat = DataFormatInt32;
1101                 return gpr;
1102             }
1103             if (spillFormat == DataFormatInt32) {
1104                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1105                 info.fillInt32(*m_stream, gpr);
1106                 returnFormat = DataFormatInt32;
1107             } else {
1108                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1109                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1110                 returnFormat = DataFormatJSInt32;
1111             }
1112             return gpr;
1113         }
1114         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1115
1116         // Fill as JSValue, and fall through.
1117         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1118         m_gprs.unlock(gpr);
1119         FALLTHROUGH;
1120     }
1121
1122     case DataFormatJS: {
1123         DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
1124         // Check the value is an integer.
1125         GPRReg gpr = info.gpr();
1126         m_gprs.lock(gpr);
1127         if (type & ~SpecInt32Only)
1128             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1129         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1130         // If !strict we're done, return.
1131         if (!strict) {
1132             returnFormat = DataFormatJSInt32;
1133             return gpr;
1134         }
1135         // else fall through & handle as DataFormatJSInt32.
1136         m_gprs.unlock(gpr);
1137         FALLTHROUGH;
1138     }
1139
1140     case DataFormatJSInt32: {
1141         // In a strict fill we need to strip off the value tag.
1142         if (strict) {
1143             GPRReg gpr = info.gpr();
1144             GPRReg result;
1145             // If the register has already been locked we need to take a copy.
1146             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
1147             if (m_gprs.isLocked(gpr))
1148                 result = allocate();
1149             else {
1150                 m_gprs.lock(gpr);
1151                 info.fillInt32(*m_stream, gpr);
1152                 result = gpr;
1153             }
1154             m_jit.zeroExtend32ToPtr(gpr, result);
1155             returnFormat = DataFormatInt32;
1156             return result;
1157         }
1158
1159         GPRReg gpr = info.gpr();
1160         m_gprs.lock(gpr);
1161         returnFormat = DataFormatJSInt32;
1162         return gpr;
1163     }
1164
1165     case DataFormatInt32: {
1166         GPRReg gpr = info.gpr();
1167         m_gprs.lock(gpr);
1168         returnFormat = DataFormatInt32;
1169         return gpr;
1170     }
1171         
1172     case DataFormatJSDouble:
1173     case DataFormatCell:
1174     case DataFormatBoolean:
1175     case DataFormatJSCell:
1176     case DataFormatJSBoolean:
1177     case DataFormatDouble:
1178     case DataFormatStorage:
1179     case DataFormatInt52:
1180     case DataFormatStrictInt52:
1181         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1182         
1183     default:
1184         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1185         return InvalidGPRReg;
1186     }
1187 }
1188 #if COMPILER(CLANG) && defined(__has_warning)
1189 #pragma clang diagnostic pop
1190 #endif
1191
1192 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1193 {
1194     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1195 }
1196
1197 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1198 {
1199     DataFormat mustBeDataFormatInt32;
1200     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1201     DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
1202     return result;
1203 }
1204
1205 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1206 {
1207     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1208     AbstractValue& value = m_state.forNode(edge);
1209
1210     m_interpreter.filter(value, SpecAnyInt);
1211     if (value.isClear()) {
1212         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1213         return allocate();
1214     }
1215
1216     VirtualRegister virtualRegister = edge->virtualRegister();
1217     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1218
1219     switch (info.registerFormat()) {
1220     case DataFormatNone: {
1221         GPRReg gpr = allocate();
1222
1223         if (edge->hasConstant()) {
1224             JSValue jsValue = edge->asJSValue();
1225             ASSERT(jsValue.isAnyInt());
1226             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1227             int64_t value = jsValue.asAnyInt();
1228             if (desiredFormat == DataFormatInt52)
1229                 value = value << JSValue::int52ShiftAmount;
1230             m_jit.move(MacroAssembler::Imm64(value), gpr);
1231             info.fillGPR(*m_stream, gpr, desiredFormat);
1232             return gpr;
1233         }
1234         
1235         DataFormat spillFormat = info.spillFormat();
1236         
1237         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
1238         
1239         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1240         
1241         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1242         if (desiredFormat == DataFormatStrictInt52) {
1243             if (spillFormat == DataFormatInt52)
1244                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1245             info.fillStrictInt52(*m_stream, gpr);
1246             return gpr;
1247         }
1248         if (spillFormat == DataFormatStrictInt52)
1249             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1250         info.fillInt52(*m_stream, gpr);
1251         return gpr;
1252     }
1253
1254     case DataFormatStrictInt52: {
1255         GPRReg gpr = info.gpr();
1256         bool wasLocked = m_gprs.isLocked(gpr);
1257         lock(gpr);
1258         if (desiredFormat == DataFormatStrictInt52)
1259             return gpr;
1260         if (wasLocked) {
1261             GPRReg result = allocate();
1262             m_jit.move(gpr, result);
1263             unlock(gpr);
1264             gpr = result;
1265         } else
1266             info.fillInt52(*m_stream, gpr);
1267         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1268         return gpr;
1269     }
1270         
1271     case DataFormatInt52: {
1272         GPRReg gpr = info.gpr();
1273         bool wasLocked = m_gprs.isLocked(gpr);
1274         lock(gpr);
1275         if (desiredFormat == DataFormatInt52)
1276             return gpr;
1277         if (wasLocked) {
1278             GPRReg result = allocate();
1279             m_jit.move(gpr, result);
1280             unlock(gpr);
1281             gpr = result;
1282         } else
1283             info.fillStrictInt52(*m_stream, gpr);
1284         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1285         return gpr;
1286     }
1287
1288     default:
1289         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1290         return InvalidGPRReg;
1291     }
1292 }
1293
1294 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1295 {
1296     ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1297     ASSERT(edge->hasDoubleResult());
1298     VirtualRegister virtualRegister = edge->virtualRegister();
1299     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1300
1301     if (info.registerFormat() == DataFormatNone) {
1302         if (edge->hasConstant()) {
1303             if (edge->isNumberConstant()) {
1304                 FPRReg fpr = fprAllocate();
1305                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1306                 if (!doubleAsInt)
1307                     m_jit.moveZeroToDouble(fpr);
1308                 else {
1309                     GPRReg gpr = allocate();
1310                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1311                     m_jit.move64ToDouble(gpr, fpr);
1312                     unlock(gpr);
1313                 }
1314
1315                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1316                 info.fillDouble(*m_stream, fpr);
1317                 return fpr;
1318             }
1319             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1320             return fprAllocate();
1321         }
1322         
1323         DataFormat spillFormat = info.spillFormat();
1324         if (spillFormat != DataFormatDouble) {
1325             DFG_CRASH(
1326                 m_jit.graph(), m_currentNode, toCString(
1327                     "Expected ", edge, " to have double format but instead it is spilled as ",
1328                     dataFormatToString(spillFormat)).data());
1329         }
1330         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
1331         FPRReg fpr = fprAllocate();
1332         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1333         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1334         info.fillDouble(*m_stream, fpr);
1335         return fpr;
1336     }
1337
1338     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
1339     FPRReg fpr = info.fpr();
1340     m_fprs.lock(fpr);
1341     return fpr;
1342 }
1343
1344 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1345 {
1346     AbstractValue& value = m_state.forNode(edge);
1347     SpeculatedType type = value.m_type;
1348     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1349
1350     m_interpreter.filter(value, SpecCell);
1351     if (value.isClear()) {
1352         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1353         return allocate();
1354     }
1355
1356     VirtualRegister virtualRegister = edge->virtualRegister();
1357     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1358
1359     switch (info.registerFormat()) {
1360     case DataFormatNone: {
1361         GPRReg gpr = allocate();
1362
1363         if (edge->hasConstant()) {
1364             JSValue jsValue = edge->asJSValue();
1365             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1366             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1367             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1368             return gpr;
1369         }
1370
1371         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1372         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1373
1374         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1375         if (type & ~SpecCell)
1376             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1377         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1378         return gpr;
1379     }
1380
1381     case DataFormatCell:
1382     case DataFormatJSCell: {
1383         GPRReg gpr = info.gpr();
1384         m_gprs.lock(gpr);
1385         if (!ASSERT_DISABLED) {
1386             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1387             m_jit.abortWithReason(DFGIsNotCell);
1388             checkCell.link(&m_jit);
1389         }
1390         return gpr;
1391     }
1392
1393     case DataFormatJS: {
1394         GPRReg gpr = info.gpr();
1395         m_gprs.lock(gpr);
1396         if (type & ~SpecCell)
1397             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1398         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1399         return gpr;
1400     }
1401
1402     case DataFormatJSInt32:
1403     case DataFormatInt32:
1404     case DataFormatJSDouble:
1405     case DataFormatJSBoolean:
1406     case DataFormatBoolean:
1407     case DataFormatDouble:
1408     case DataFormatStorage:
1409     case DataFormatInt52:
1410     case DataFormatStrictInt52:
1411         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1412         
1413     default:
1414         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1415         return InvalidGPRReg;
1416     }
1417 }
1418
1419 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1420 {
1421     AbstractValue& value = m_state.forNode(edge);
1422     SpeculatedType type = value.m_type;
1423     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1424
1425     m_interpreter.filter(value, SpecBoolean);
1426     if (value.isClear()) {
1427         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1428         return allocate();
1429     }
1430
1431     VirtualRegister virtualRegister = edge->virtualRegister();
1432     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1433
1434     switch (info.registerFormat()) {
1435     case DataFormatNone: {
1436         GPRReg gpr = allocate();
1437
1438         if (edge->hasConstant()) {
1439             JSValue jsValue = edge->asJSValue();
1440             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1441             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1442             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1443             return gpr;
1444         }
1445         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
1446         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1447         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1448
1449         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1450         if (type & ~SpecBoolean) {
1451             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1452             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1453             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1454         }
1455         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1456         return gpr;
1457     }
1458
1459     case DataFormatBoolean:
1460     case DataFormatJSBoolean: {
1461         GPRReg gpr = info.gpr();
1462         m_gprs.lock(gpr);
1463         return gpr;
1464     }
1465
1466     case DataFormatJS: {
1467         GPRReg gpr = info.gpr();
1468         m_gprs.lock(gpr);
1469         if (type & ~SpecBoolean) {
1470             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1471             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1472             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1473         }
1474         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1475         return gpr;
1476     }
1477
1478     case DataFormatJSInt32:
1479     case DataFormatInt32:
1480     case DataFormatJSDouble:
1481     case DataFormatJSCell:
1482     case DataFormatCell:
1483     case DataFormatDouble:
1484     case DataFormatStorage:
1485     case DataFormatInt52:
1486     case DataFormatStrictInt52:
1487         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1488         
1489     default:
1490         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1491         return InvalidGPRReg;
1492     }
1493 }
1494
1495 void SpeculativeJIT::compileObjectEquality(Node* node)
1496 {
1497     SpeculateCellOperand op1(this, node->child1());
1498     SpeculateCellOperand op2(this, node->child2());
1499     GPRTemporary result(this, Reuse, op1);
1500     
1501     GPRReg op1GPR = op1.gpr();
1502     GPRReg op2GPR = op2.gpr();
1503     GPRReg resultGPR = result.gpr();
1504    
1505     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1506         DFG_TYPE_CHECK(
1507             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1508         DFG_TYPE_CHECK(
1509             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1510     } else {
1511         DFG_TYPE_CHECK(
1512             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1513         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1514             m_jit.branchTest8(
1515                 MacroAssembler::NonZero, 
1516                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1517                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1518
1519         DFG_TYPE_CHECK(
1520             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1521         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1522             m_jit.branchTest8(
1523                 MacroAssembler::NonZero, 
1524                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1525                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1526     }
1527
1528     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1529     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1530     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1531 }
1532
1533 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1534 {
1535     SpeculateCellOperand op1(this, objectChild);
1536     JSValueOperand op2(this, otherChild);
1537     GPRTemporary result(this);
1538
1539     GPRReg op1GPR = op1.gpr();
1540     GPRReg op2GPR = op2.gpr();
1541     GPRReg resultGPR = result.gpr();
1542
1543     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1544
1545     // At this point we know that we can perform a straight-forward equality comparison on pointer
1546     // values because we are doing strict equality.
1547     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1548     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1549     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1550 }
1551     
1552 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1553 {
1554     BasicBlock* taken = branchNode->branchData()->taken.block;
1555     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1556     
1557     SpeculateCellOperand op1(this, objectChild);
1558     JSValueOperand op2(this, otherChild);
1559     
1560     GPRReg op1GPR = op1.gpr();
1561     GPRReg op2GPR = op2.gpr();
1562     
1563     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1564
1565     if (taken == nextBlock()) {
1566         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1567         jump(taken);
1568     } else {
1569         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1570         jump(notTaken);
1571     }
1572 }
1573
1574 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1575 {
1576     SpeculateCellOperand op1(this, leftChild);
1577     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1578     GPRTemporary result(this);
1579     
1580     GPRReg op1GPR = op1.gpr();
1581     GPRReg op2GPR = op2.gpr();
1582     GPRReg resultGPR = result.gpr();
1583
1584     bool masqueradesAsUndefinedWatchpointValid =
1585         masqueradesAsUndefinedWatchpointIsStillValid();
1586
1587     if (masqueradesAsUndefinedWatchpointValid) {
1588         DFG_TYPE_CHECK(
1589             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1590     } else {
1591         DFG_TYPE_CHECK(
1592             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1593         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1594             m_jit.branchTest8(
1595                 MacroAssembler::NonZero, 
1596                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1597                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1598     }
1599     
1600     // It seems that most of the time when programs do a == b where b may be either null/undefined
1601     // or an object, b is usually an object. Balance the branches to make that case fast.
1602     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1603     
1604     // We know that within this branch, rightChild must be a cell. 
1605     if (masqueradesAsUndefinedWatchpointValid) {
1606         DFG_TYPE_CHECK(
1607             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1608     } else {
1609         DFG_TYPE_CHECK(
1610             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1611         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1612             m_jit.branchTest8(
1613                 MacroAssembler::NonZero, 
1614                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1615                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1616     }
1617     
1618     // At this point we know that we can perform a straight-forward equality comparison on pointer
1619     // values because both left and right are pointers to objects that have no special equality
1620     // protocols.
1621     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1622     MacroAssembler::Jump done = m_jit.jump();
1623     
1624     rightNotCell.link(&m_jit);
1625     
1626     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1627     // prove that it is either null or undefined.
1628     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1629         m_jit.move(op2GPR, resultGPR);
1630         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1631         
1632         typeCheck(
1633             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther,
1634             m_jit.branch64(
1635                 MacroAssembler::NotEqual, resultGPR,
1636                 MacroAssembler::TrustedImm64(ValueNull)));
1637     }
1638     m_jit.move(TrustedImm32(0), result.gpr());
1639
1640     done.link(&m_jit);
1641     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1642     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1643 }
1644
1645 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1646 {
1647     BasicBlock* taken = branchNode->branchData()->taken.block;
1648     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1649     
1650     SpeculateCellOperand op1(this, leftChild);
1651     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1652     GPRTemporary result(this);
1653     
1654     GPRReg op1GPR = op1.gpr();
1655     GPRReg op2GPR = op2.gpr();
1656     GPRReg resultGPR = result.gpr();
1657     
1658     bool masqueradesAsUndefinedWatchpointValid = 
1659         masqueradesAsUndefinedWatchpointIsStillValid();
1660
1661     if (masqueradesAsUndefinedWatchpointValid) {
1662         DFG_TYPE_CHECK(
1663             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1664     } else {
1665         DFG_TYPE_CHECK(
1666             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1667         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1668             m_jit.branchTest8(
1669                 MacroAssembler::NonZero, 
1670                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1671                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1672     }
1673
1674     // It seems that most of the time when programs do a == b where b may be either null/undefined
1675     // or an object, b is usually an object. Balance the branches to make that case fast.
1676     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1677     
1678     // We know that within this branch, rightChild must be a cell. 
1679     if (masqueradesAsUndefinedWatchpointValid) {
1680         DFG_TYPE_CHECK(
1681             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1682     } else {
1683         DFG_TYPE_CHECK(
1684             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1685         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1686             m_jit.branchTest8(
1687                 MacroAssembler::NonZero, 
1688                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1689                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1690     }
1691     
1692     // At this point we know that we can perform a straight-forward equality comparison on pointer
1693     // values because both left and right are pointers to objects that have no special equality
1694     // protocols.
1695     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1696     
1697     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1698     // prove that it is either null or undefined.
1699     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1700         rightNotCell.link(&m_jit);
1701     else {
1702         jump(notTaken, ForceJump);
1703         
1704         rightNotCell.link(&m_jit);
1705         m_jit.move(op2GPR, resultGPR);
1706         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1707         
1708         typeCheck(
1709             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64(
1710                 MacroAssembler::NotEqual, resultGPR,
1711                 MacroAssembler::TrustedImm64(ValueNull)));
1712     }
1713     
1714     jump(notTaken);
1715 }
1716
1717 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1718 {
1719     SpeculateCellOperand symbol(this, symbolEdge);
1720     JSValueOperand untyped(this, untypedEdge);
1721     GPRTemporary result(this, Reuse, symbol, untyped);
1722
1723     GPRReg symbolGPR = symbol.gpr();
1724     GPRReg untypedGPR = untyped.gpr();
1725     GPRReg resultGPR = result.gpr();
1726
1727     speculateSymbol(symbolEdge, symbolGPR);
1728
1729     // At this point we know that we can perform a straight-forward equality comparison on pointer
1730     // values because we are doing strict equality.
1731     m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
1732     unblessedBooleanResult(resultGPR, node);
1733 }
1734
1735 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1736 {
1737     if (node->child1()->isInt32Constant()) {
1738         SpeculateInt32Operand op2(this, node->child2());
1739         GPRTemporary result(this, Reuse, op2);
1740         int32_t imm = node->child1()->asInt32();
1741         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1742
1743         // If we add a DataFormatBool, we should use it here.
1744         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1745         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1746     } else if (node->child2()->isInt32Constant()) {
1747         SpeculateInt32Operand op1(this, node->child1());
1748         GPRTemporary result(this, Reuse, op1);
1749         int32_t imm = node->child2()->asInt32();
1750         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1751
1752         // If we add a DataFormatBool, we should use it here.
1753         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1754         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1755     } else {
1756         SpeculateInt32Operand op1(this, node->child1());
1757         SpeculateInt32Operand op2(this, node->child2());
1758         GPRTemporary result(this, Reuse, op1, op2);
1759         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1760
1761         // If we add a DataFormatBool, we should use it here.
1762         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1763         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1764     }
1765 }
1766
1767 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1768 {
1769     SpeculateWhicheverInt52Operand op1(this, node->child1());
1770     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1771     GPRTemporary result(this, Reuse, op1, op2);
1772     
1773     m_jit.compare64(condition, op1.gpr(), op2.gpr(), 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 }
1779
1780 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1781 {
1782     BasicBlock* taken = branchNode->branchData()->taken.block;
1783     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1784
1785     // The branch instruction will branch to the taken block.
1786     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1787     if (taken == nextBlock()) {
1788         condition = JITCompiler::invert(condition);
1789         BasicBlock* tmp = taken;
1790         taken = notTaken;
1791         notTaken = tmp;
1792     }
1793     
1794     SpeculateWhicheverInt52Operand op1(this, node->child1());
1795     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1796     
1797     branch64(condition, op1.gpr(), op2.gpr(), taken);
1798     jump(notTaken);
1799 }
1800
1801 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1802 {
1803     SpeculateDoubleOperand op1(this, node->child1());
1804     SpeculateDoubleOperand op2(this, node->child2());
1805     GPRTemporary result(this);
1806     
1807     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1808     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1809     m_jit.xor64(TrustedImm32(true), result.gpr());
1810     trueCase.link(&m_jit);
1811     
1812     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1813 }
1814
1815 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1816 {
1817     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1818     GPRTemporary result(this);
1819     GPRReg valueGPR = value.gpr();
1820     GPRReg resultGPR = result.gpr();
1821     GPRTemporary structure;
1822     GPRReg structureGPR = InvalidGPRReg;
1823     GPRTemporary scratch;
1824     GPRReg scratchGPR = InvalidGPRReg;
1825
1826     bool masqueradesAsUndefinedWatchpointValid =
1827         masqueradesAsUndefinedWatchpointIsStillValid();
1828
1829     if (!masqueradesAsUndefinedWatchpointValid) {
1830         // The masquerades as undefined case will use the structure register, so allocate it here.
1831         // Do this at the top of the function to avoid branching around a register allocation.
1832         GPRTemporary realStructure(this);
1833         GPRTemporary realScratch(this);
1834         structure.adopt(realStructure);
1835         scratch.adopt(realScratch);
1836         structureGPR = structure.gpr();
1837         scratchGPR = scratch.gpr();
1838     }
1839
1840     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1841     if (masqueradesAsUndefinedWatchpointValid) {
1842         DFG_TYPE_CHECK(
1843             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1844     } else {
1845         DFG_TYPE_CHECK(
1846             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1847
1848         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1849             m_jit.branchTest8(
1850                 MacroAssembler::Zero, 
1851                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1852                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1853
1854         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1855         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1856             m_jit.branchPtr(
1857                 MacroAssembler::Equal, 
1858                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1859                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1860
1861         isNotMasqueradesAsUndefined.link(&m_jit);
1862     }
1863     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1864     MacroAssembler::Jump done = m_jit.jump();
1865     
1866     notCell.link(&m_jit);
1867
1868     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1869         m_jit.move(valueGPR, resultGPR);
1870         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1871         typeCheck(
1872             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1873                 MacroAssembler::NotEqual, 
1874                 resultGPR, 
1875                 MacroAssembler::TrustedImm64(ValueNull)));
1876     }
1877     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1878     
1879     done.link(&m_jit);
1880     
1881     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1882 }
1883
1884 void SpeculativeJIT::compileLogicalNot(Node* node)
1885 {
1886     switch (node->child1().useKind()) {
1887     case ObjectOrOtherUse: {
1888         compileObjectOrOtherLogicalNot(node->child1());
1889         return;
1890     }
1891         
1892     case Int32Use: {
1893         SpeculateInt32Operand value(this, node->child1());
1894         GPRTemporary result(this, Reuse, value);
1895         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1896         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1897         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1898         return;
1899     }
1900         
1901     case DoubleRepUse: {
1902         SpeculateDoubleOperand value(this, node->child1());
1903         FPRTemporary scratch(this);
1904         GPRTemporary result(this);
1905         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1906         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1907         m_jit.xor32(TrustedImm32(true), result.gpr());
1908         nonZero.link(&m_jit);
1909         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1910         return;
1911     }
1912     
1913     case BooleanUse:
1914     case KnownBooleanUse: {
1915         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1916             SpeculateBooleanOperand value(this, node->child1());
1917             GPRTemporary result(this, Reuse, value);
1918             
1919             m_jit.move(value.gpr(), result.gpr());
1920             m_jit.xor64(TrustedImm32(true), result.gpr());
1921             
1922             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1923             return;
1924         }
1925         
1926         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1927         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1928         
1929         m_jit.move(value.gpr(), result.gpr());
1930         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1931         typeCheck(
1932             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1933                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1934         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1935         
1936         // If we add a DataFormatBool, we should use it here.
1937         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1938         return;
1939     }
1940         
1941     case UntypedUse: {
1942         JSValueOperand arg1(this, node->child1());
1943         GPRTemporary result(this);
1944     
1945         GPRReg arg1GPR = arg1.gpr();
1946         GPRReg resultGPR = result.gpr();
1947
1948         FPRTemporary valueFPR(this);
1949         FPRTemporary tempFPR(this);
1950
1951         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1952         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1953         std::optional<GPRTemporary> scratch;
1954         GPRReg scratchGPR = InvalidGPRReg;
1955         if (shouldCheckMasqueradesAsUndefined) {
1956             scratch.emplace(this);
1957             scratchGPR = scratch->gpr();
1958         }
1959         bool negateResult = true;
1960         m_jit.emitConvertValueToBoolean(JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1961         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1962         jsValueResult(resultGPR, node, DataFormatJSBoolean);
1963         return;
1964     }
1965     case StringUse:
1966         return compileStringZeroLength(node);
1967
1968     case StringOrOtherUse:
1969         return compileLogicalNotStringOrOther(node);
1970
1971     default:
1972         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1973         break;
1974     }
1975 }
1976
1977 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1978 {
1979     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1980     GPRTemporary scratch(this);
1981     GPRTemporary structure;
1982     GPRReg valueGPR = value.gpr();
1983     GPRReg scratchGPR = scratch.gpr();
1984     GPRReg structureGPR = InvalidGPRReg;
1985
1986     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
1987         GPRTemporary realStructure(this);
1988         structure.adopt(realStructure);
1989         structureGPR = structure.gpr();
1990     }
1991
1992     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1993     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1994         DFG_TYPE_CHECK(
1995             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1996     } else {
1997         DFG_TYPE_CHECK(
1998             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1999
2000         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
2001             JITCompiler::Zero, 
2002             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
2003             TrustedImm32(MasqueradesAsUndefined));
2004
2005         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
2006         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
2007             m_jit.branchPtr(
2008                 MacroAssembler::Equal, 
2009                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
2010                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
2011
2012         isNotMasqueradesAsUndefined.link(&m_jit);
2013     }
2014     jump(taken, ForceJump);
2015     
2016     notCell.link(&m_jit);
2017     
2018     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
2019         m_jit.move(valueGPR, scratchGPR);
2020         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2021         typeCheck(
2022             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
2023                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2024     }
2025     jump(notTaken);
2026     
2027     noResult(m_currentNode);
2028 }
2029
2030 void SpeculativeJIT::emitBranch(Node* node)
2031 {
2032     BasicBlock* taken = node->branchData()->taken.block;
2033     BasicBlock* notTaken = node->branchData()->notTaken.block;
2034     
2035     switch (node->child1().useKind()) {
2036     case ObjectOrOtherUse: {
2037         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
2038         return;
2039     }
2040         
2041     case Int32Use:
2042     case DoubleRepUse: {
2043         if (node->child1().useKind() == Int32Use) {
2044             bool invert = false;
2045             
2046             if (taken == nextBlock()) {
2047                 invert = true;
2048                 BasicBlock* tmp = taken;
2049                 taken = notTaken;
2050                 notTaken = tmp;
2051             }
2052
2053             SpeculateInt32Operand value(this, node->child1());
2054             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2055         } else {
2056             SpeculateDoubleOperand value(this, node->child1());
2057             FPRTemporary scratch(this);
2058             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2059         }
2060         
2061         jump(notTaken);
2062         
2063         noResult(node);
2064         return;
2065     }
2066
2067     case StringUse: {
2068         emitStringBranch(node->child1(), taken, notTaken);
2069         return;
2070     }
2071
2072     case StringOrOtherUse: {
2073         emitStringOrOtherBranch(node->child1(), taken, notTaken);
2074         return;
2075     }
2076
2077     case UntypedUse:
2078     case BooleanUse:
2079     case KnownBooleanUse: {
2080         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2081         GPRReg valueGPR = value.gpr();
2082         
2083         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
2084             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
2085                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2086                 
2087                 if (taken == nextBlock()) {
2088                     condition = MacroAssembler::Zero;
2089                     BasicBlock* tmp = taken;
2090                     taken = notTaken;
2091                     notTaken = tmp;
2092                 }
2093                 
2094                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2095                 jump(notTaken);
2096             } else {
2097                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2098                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2099                 
2100                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
2101             }
2102             value.use();
2103         } else {
2104             GPRTemporary result(this);
2105             FPRTemporary fprValue(this);
2106             FPRTemporary fprTemp(this);
2107             std::optional<GPRTemporary> scratch;
2108
2109             GPRReg scratchGPR = InvalidGPRReg;
2110             bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
2111             if (shouldCheckMasqueradesAsUndefined) {
2112                 scratch.emplace(this);
2113                 scratchGPR = scratch->gpr();
2114             }
2115
2116             GPRReg resultGPR = result.gpr();
2117             FPRReg valueFPR = fprValue.fpr();
2118             FPRReg tempFPR = fprTemp.fpr();
2119             
2120             if (node->child1()->prediction() & SpecInt32Only) {
2121                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2122                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2123             }
2124     
2125             if (node->child1()->prediction() & SpecBoolean) {
2126                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2127                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2128             }
2129     
2130             value.use();
2131
2132             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
2133             m_jit.emitConvertValueToBoolean(JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
2134     
2135             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2136             jump(notTaken);
2137         }
2138         
2139         noResult(node, UseChildrenCalledExplicitly);
2140         return;
2141     }
2142         
2143     default:
2144         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
2145     }
2146 }
2147
2148 void SpeculativeJIT::compile(Node* node)
2149 {
2150     NodeType op = node->op();
2151     
2152 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
2153     m_jit.clearRegisterAllocationOffsets();
2154 #endif
2155
2156     switch (op) {
2157     case JSConstant:
2158     case DoubleConstant:
2159     case Int52Constant:
2160     case PhantomDirectArguments:
2161     case PhantomClonedArguments:
2162         initConstantInfo(node);
2163         break;
2164
2165     case LazyJSConstant:
2166         compileLazyJSConstant(node);
2167         break;
2168
2169     case Identity: {
2170         speculate(node, node->child1());
2171         switch (node->child1().useKind()) {
2172         case DoubleRepUse:
2173         case DoubleRepRealUse:
2174         case DoubleRepAnyIntUse: {
2175             SpeculateDoubleOperand op(this, node->child1());
2176             FPRTemporary scratch(this, op);
2177             m_jit.moveDouble(op.fpr(), scratch.fpr());
2178             doubleResult(scratch.fpr(), node);
2179             break;
2180         }
2181         case Int52RepUse: {
2182             SpeculateInt52Operand op(this, node->child1());
2183             GPRTemporary result(this, Reuse, op);
2184             m_jit.move(op.gpr(), result.gpr());
2185             int52Result(result.gpr(), node);
2186             break;
2187         }
2188         default: {
2189             JSValueOperand op(this, node->child1());
2190             GPRTemporary result(this, Reuse, op);
2191             m_jit.move(op.gpr(), result.gpr());
2192             jsValueResult(result.gpr(), node);
2193             break;
2194         }
2195         } // switch
2196         break;
2197     }
2198
2199     case GetLocal: {
2200         AbstractValue& value = m_state.variables().operand(node->local());
2201
2202         // If the CFA is tracking this variable and it found that the variable
2203         // cannot have been assigned, then don't attempt to proceed.
2204         if (value.isClear()) {
2205             m_compileOkay = false;
2206             break;
2207         }
2208         
2209         switch (node->variableAccessData()->flushFormat()) {
2210         case FlushedDouble: {
2211             FPRTemporary result(this);
2212             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2213             VirtualRegister virtualRegister = node->virtualRegister();
2214             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2215             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2216             break;
2217         }
2218         
2219         case FlushedInt32: {
2220             GPRTemporary result(this);
2221             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2222             
2223             // Like int32Result, but don't useChildren - our children are phi nodes,
2224             // and don't represent values within this dataflow with virtual registers.
2225             VirtualRegister virtualRegister = node->virtualRegister();
2226             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2227             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2228             break;
2229         }
2230             
2231         case FlushedInt52: {
2232             GPRTemporary result(this);
2233             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2234             
2235             VirtualRegister virtualRegister = node->virtualRegister();
2236             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2237             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2238             break;
2239         }
2240             
2241         default:
2242             GPRTemporary result(this);
2243             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2244             
2245             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2246             // and don't represent values within this dataflow with virtual registers.
2247             VirtualRegister virtualRegister = node->virtualRegister();
2248             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2249             
2250             DataFormat format;
2251             if (isCellSpeculation(value.m_type))
2252                 format = DataFormatJSCell;
2253             else if (isBooleanSpeculation(value.m_type))
2254                 format = DataFormatJSBoolean;
2255             else
2256                 format = DataFormatJS;
2257             
2258             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2259             break;
2260         }
2261         break;
2262     }
2263
2264     case GetLocalUnlinked: {
2265         GPRTemporary result(this);
2266         
2267         m_jit.load64(JITCompiler::addressFor(node->unlinkedMachineLocal()), result.gpr());
2268         
2269         jsValueResult(result.gpr(), node);
2270         break;
2271     }
2272         
2273     case MovHint: {
2274         compileMovHint(m_currentNode);
2275         noResult(node);
2276         break;
2277     }
2278         
2279     case ZombieHint: {
2280         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2281         noResult(node);
2282         break;
2283     }
2284         
2285     case ExitOK: {
2286         noResult(node);
2287         break;
2288     }
2289         
2290     case SetLocal: {
2291         switch (node->variableAccessData()->flushFormat()) {
2292         case FlushedDouble: {
2293             SpeculateDoubleOperand value(this, node->child1());
2294             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2295             noResult(node);
2296             // Indicate that it's no longer necessary to retrieve the value of
2297             // this bytecode variable from registers or other locations in the stack,
2298             // but that it is stored as a double.
2299             recordSetLocal(DataFormatDouble);
2300             break;
2301         }
2302             
2303         case FlushedInt32: {
2304             SpeculateInt32Operand value(this, node->child1());
2305             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2306             noResult(node);
2307             recordSetLocal(DataFormatInt32);
2308             break;
2309         }
2310             
2311         case FlushedInt52: {
2312             SpeculateInt52Operand value(this, node->child1());
2313             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2314             noResult(node);
2315             recordSetLocal(DataFormatInt52);
2316             break;
2317         }
2318             
2319         case FlushedCell: {
2320             SpeculateCellOperand cell(this, node->child1());
2321             GPRReg cellGPR = cell.gpr();
2322             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2323             noResult(node);
2324             recordSetLocal(DataFormatCell);
2325             break;
2326         }
2327             
2328         case FlushedBoolean: {
2329             SpeculateBooleanOperand boolean(this, node->child1());
2330             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2331             noResult(node);
2332             recordSetLocal(DataFormatBoolean);
2333             break;
2334         }
2335             
2336         case FlushedJSValue: {
2337             JSValueOperand value(this, node->child1());
2338             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2339             noResult(node);
2340             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2341             break;
2342         }
2343             
2344         default:
2345             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2346             break;
2347         }
2348
2349         break;
2350     }
2351
2352     case SetArgument:
2353         // This is a no-op; it just marks the fact that the argument is being used.
2354         // But it may be profitable to use this as a hook to run speculation checks
2355         // on arguments, thereby allowing us to trivially eliminate such checks if
2356         // the argument is not used.
2357         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2358         break;
2359
2360     case BitAnd:
2361     case BitOr:
2362     case BitXor:
2363         compileBitwiseOp(node);
2364         break;
2365
2366     case BitRShift:
2367     case BitLShift:
2368     case BitURShift:
2369         compileShiftOp(node);
2370         break;
2371
2372     case UInt32ToNumber: {
2373         compileUInt32ToNumber(node);
2374         break;
2375     }
2376
2377     case DoubleAsInt32: {
2378         compileDoubleAsInt32(node);
2379         break;
2380     }
2381
2382     case ValueToInt32: {
2383         compileValueToInt32(node);
2384         break;
2385     }
2386         
2387     case DoubleRep: {
2388         compileDoubleRep(node);
2389         break;
2390     }
2391         
2392     case ValueRep: {
2393         compileValueRep(node);
2394         break;
2395     }
2396         
2397     case Int52Rep: {
2398         switch (node->child1().useKind()) {
2399         case Int32Use: {
2400             SpeculateInt32Operand operand(this, node->child1());
2401             GPRTemporary result(this, Reuse, operand);
2402             
2403             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2404             
2405             strictInt52Result(result.gpr(), node);
2406             break;
2407         }
2408             
2409         case AnyIntUse: {
2410             GPRTemporary result(this);
2411             GPRReg resultGPR = result.gpr();
2412             
2413             convertAnyInt(node->child1(), resultGPR);
2414             
2415             strictInt52Result(resultGPR, node);
2416             break;
2417         }
2418             
2419         case DoubleRepAnyIntUse: {
2420             SpeculateDoubleOperand value(this, node->child1());
2421             FPRReg valueFPR = value.fpr();
2422             
2423             GPRFlushedCallResult result(this);
2424             GPRReg resultGPR = result.gpr();
2425             
2426             flushRegisters();
2427             
2428             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2429             
2430             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2431                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2432                 m_jit.branch64(
2433                     JITCompiler::Equal, resultGPR,
2434                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2435             
2436             strictInt52Result(resultGPR, node);
2437             break;
2438         }
2439             
2440         default:
2441             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2442         }
2443         break;
2444     }
2445
2446     case ValueAdd:
2447         compileValueAdd(node);
2448         break;
2449
2450     case StrCat: {
2451         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2452         JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
2453         JSValueOperand op3(this, node->child3(), ManualOperandSpeculation);
2454         
2455         GPRReg op1GPR = op1.gpr();
2456         GPRReg op2GPR = op2.gpr();
2457         GPRReg op3GPR;
2458         if (node->child3())
2459             op3GPR = op3.gpr();
2460         else
2461             op3GPR = InvalidGPRReg;
2462         
2463         flushRegisters();
2464
2465         GPRFlushedCallResult result(this);
2466         if (node->child3())
2467             callOperation(operationStrCat3, result.gpr(), op1GPR, op2GPR, op3GPR);
2468         else
2469             callOperation(operationStrCat2, result.gpr(), op1GPR, op2GPR);
2470         m_jit.exceptionCheck();
2471         
2472         cellResult(result.gpr(), node);
2473         break;
2474     }
2475
2476     case ArithAdd:
2477         compileArithAdd(node);
2478         break;
2479
2480     case ArithClz32:
2481         compileArithClz32(node);
2482         break;
2483         
2484     case MakeRope:
2485         compileMakeRope(node);
2486         break;
2487
2488     case ArithSub:
2489         compileArithSub(node);
2490         break;
2491
2492     case ArithNegate:
2493         compileArithNegate(node);
2494         break;
2495
2496     case ArithMul:
2497         compileArithMul(node);
2498         break;
2499
2500     case ArithDiv: {
2501         compileArithDiv(node);
2502         break;
2503     }
2504
2505     case ArithMod: {
2506         compileArithMod(node);
2507         break;
2508     }
2509
2510     case ArithAbs:
2511         compileArithAbs(node);
2512         break;
2513         
2514     case ArithMin:
2515     case ArithMax: {
2516         switch (node->binaryUseKind()) {
2517         case Int32Use: {
2518             SpeculateStrictInt32Operand op1(this, node->child1());
2519             SpeculateStrictInt32Operand op2(this, node->child2());
2520             GPRTemporary result(this, Reuse, op1);
2521             
2522             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2523             m_jit.move(op2.gpr(), result.gpr());
2524             if (op1.gpr() != result.gpr()) {
2525                 MacroAssembler::Jump done = m_jit.jump();
2526                 op1Less.link(&m_jit);
2527                 m_jit.move(op1.gpr(), result.gpr());
2528                 done.link(&m_jit);
2529             } else
2530                 op1Less.link(&m_jit);
2531             
2532             int32Result(result.gpr(), node);
2533             break;
2534         }
2535         
2536         case DoubleRepUse: {
2537             SpeculateDoubleOperand op1(this, node->child1());
2538             SpeculateDoubleOperand op2(this, node->child2());
2539             FPRTemporary result(this, op1);
2540             
2541             FPRReg op1FPR = op1.fpr();
2542             FPRReg op2FPR = op2.fpr();
2543             FPRReg resultFPR = result.fpr();
2544         
2545             MacroAssembler::JumpList done;
2546         
2547             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2548         
2549             // op2 is eather the lesser one or one of then is NaN
2550             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2551         
2552             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2553             // op1 + op2 and putting it into result.
2554             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2555             done.append(m_jit.jump());
2556         
2557             op2Less.link(&m_jit);
2558             m_jit.moveDouble(op2FPR, resultFPR);
2559         
2560             if (op1FPR != resultFPR) {
2561                 done.append(m_jit.jump());
2562             
2563                 op1Less.link(&m_jit);
2564                 m_jit.moveDouble(op1FPR, resultFPR);
2565             } else
2566                 op1Less.link(&m_jit);
2567         
2568             done.link(&m_jit);
2569         
2570             doubleResult(resultFPR, node);
2571             break;
2572         }
2573             
2574         default:
2575             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2576             break;
2577         }
2578         break;
2579     }
2580
2581     case ArithPow:
2582         compileArithPow(node);
2583         break;
2584
2585     case ArithSqrt:
2586         compileArithSqrt(node);
2587         break;
2588
2589     case ArithFRound:
2590         compileArithFRound(node);
2591         break;
2592
2593     case ArithRandom:
2594         compileArithRandom(node);
2595         break;
2596
2597     case ArithRound:
2598     case ArithFloor:
2599     case ArithCeil:
2600     case ArithTrunc:
2601         compileArithRounding(node);
2602         break;
2603
2604     case ArithSin:
2605         compileArithSin(node);
2606         break;
2607
2608     case ArithCos:
2609         compileArithCos(node);
2610         break;
2611
2612     case ArithTan:
2613         compileArithTan(node);
2614         break;
2615
2616     case ArithLog:
2617         compileArithLog(node);
2618         break;
2619
2620     case LogicalNot:
2621         compileLogicalNot(node);
2622         break;
2623
2624     case CompareLess:
2625         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2626             return;
2627         break;
2628
2629     case CompareLessEq:
2630         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2631             return;
2632         break;
2633
2634     case CompareGreater:
2635         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2636             return;
2637         break;
2638
2639     case CompareGreaterEq:
2640         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2641             return;
2642         break;
2643
2644     case CompareEq:
2645         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2646             return;
2647         break;
2648
2649     case CompareStrictEq:
2650         if (compileStrictEq(node))
2651             return;
2652         break;
2653         
2654     case CompareEqPtr:
2655         compileCompareEqPtr(node);
2656         break;
2657
2658     case StringCharCodeAt: {
2659         compileGetCharCodeAt(node);
2660         break;
2661     }
2662
2663     case StringCharAt: {
2664         // Relies on StringCharAt node having same basic layout as GetByVal
2665         compileGetByValOnString(node);
2666         break;
2667     }
2668
2669     case StringFromCharCode: {
2670         compileFromCharCode(node);
2671         break;
2672     }
2673         
2674     case CheckArray: {
2675         checkArray(node);
2676         break;
2677     }
2678         
2679     case Arrayify:
2680     case ArrayifyToStructure: {
2681         arrayify(node);
2682         break;
2683     }
2684
2685     case GetByVal: {
2686         switch (node->arrayMode().type()) {
2687         case Array::SelectUsingPredictions:
2688         case Array::ForceExit:
2689             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2690             break;
2691         case Array::Undecided: {
2692             SpeculateStrictInt32Operand index(this, node->child2());
2693             GPRTemporary result(this, Reuse, index);
2694             GPRReg indexGPR = index.gpr();
2695             GPRReg resultGPR = result.gpr();
2696
2697             speculationCheck(OutOfBounds, JSValueRegs(), node,
2698                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2699
2700             use(node->child1());
2701             index.use();
2702
2703             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2704             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2705             break;
2706         }
2707         case Array::Generic: {
2708             JSValueOperand base(this, node->child1());
2709             JSValueOperand property(this, node->child2());
2710             GPRReg baseGPR = base.gpr();
2711             GPRReg propertyGPR = property.gpr();
2712             
2713             flushRegisters();
2714             GPRFlushedCallResult result(this);
2715             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2716             m_jit.exceptionCheck();
2717             
2718             jsValueResult(result.gpr(), node);
2719             break;
2720         }
2721         case Array::Int32:
2722         case Array::Contiguous: {
2723             if (node->arrayMode().isInBounds()) {
2724                 SpeculateStrictInt32Operand property(this, node->child2());
2725                 StorageOperand storage(this, node->child3());
2726                 
2727                 GPRReg propertyReg = property.gpr();
2728                 GPRReg storageReg = storage.gpr();
2729                 
2730                 if (!m_compileOkay)
2731                     return;
2732                 
2733                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2734                 
2735                 GPRTemporary result(this);
2736                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2737                 if (node->arrayMode().isSaneChain()) {
2738                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2739                     JITCompiler::Jump notHole = m_jit.branchTest64(
2740                         MacroAssembler::NonZero, result.gpr());
2741                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2742                     notHole.link(&m_jit);
2743                 } else {
2744                     speculationCheck(
2745                         LoadFromHole, JSValueRegs(), 0,
2746                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2747                 }
2748                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2749                 break;
2750             }
2751             
2752             SpeculateCellOperand base(this, node->child1());
2753             SpeculateStrictInt32Operand property(this, node->child2());
2754             StorageOperand storage(this, node->child3());
2755             
2756             GPRReg baseReg = base.gpr();
2757             GPRReg propertyReg = property.gpr();
2758             GPRReg storageReg = storage.gpr();
2759             
2760             if (!m_compileOkay)
2761                 return;
2762             
2763             GPRTemporary result(this);
2764             GPRReg resultReg = result.gpr();
2765             
2766             MacroAssembler::JumpList slowCases;
2767             
2768             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2769             
2770             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2771             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2772             
2773             addSlowPathGenerator(
2774                 slowPathCall(
2775                     slowCases, this, operationGetByValArrayInt,
2776                     result.gpr(), baseReg, propertyReg));
2777             
2778             jsValueResult(resultReg, node);
2779             break;
2780         }
2781
2782         case Array::Double: {
2783             if (node->arrayMode().isInBounds()) {
2784                 SpeculateStrictInt32Operand property(this, node->child2());
2785                 StorageOperand storage(this, node->child3());
2786             
2787                 GPRReg propertyReg = property.gpr();
2788                 GPRReg storageReg = storage.gpr();
2789             
2790                 if (!m_compileOkay)
2791                     return;
2792             
2793                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2794             
2795                 FPRTemporary result(this);
2796                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2797                 if (!node->arrayMode().isSaneChain())
2798                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2799                 doubleResult(result.fpr(), node);
2800                 break;
2801             }
2802
2803             SpeculateCellOperand base(this, node->child1());
2804             SpeculateStrictInt32Operand property(this, node->child2());
2805             StorageOperand storage(this, node->child3());
2806             
2807             GPRReg baseReg = base.gpr();
2808             GPRReg propertyReg = property.gpr();
2809             GPRReg storageReg = storage.gpr();
2810             
2811             if (!m_compileOkay)
2812                 return;
2813             
2814             GPRTemporary result(this);
2815             FPRTemporary temp(this);
2816             GPRReg resultReg = result.gpr();
2817             FPRReg tempReg = temp.fpr();
2818             
2819             MacroAssembler::JumpList slowCases;
2820             
2821             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2822             
2823             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2824             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2825             boxDouble(tempReg, resultReg);
2826             
2827             addSlowPathGenerator(
2828                 slowPathCall(
2829                     slowCases, this, operationGetByValArrayInt,
2830                     result.gpr(), baseReg, propertyReg));
2831             
2832             jsValueResult(resultReg, node);
2833             break;
2834         }
2835
2836         case Array::ArrayStorage:
2837         case Array::SlowPutArrayStorage: {
2838             if (node->arrayMode().isInBounds()) {
2839                 SpeculateStrictInt32Operand property(this, node->child2());
2840                 StorageOperand storage(this, node->child3());
2841             
2842                 GPRReg propertyReg = property.gpr();
2843                 GPRReg storageReg = storage.gpr();
2844             
2845                 if (!m_compileOkay)
2846                     return;
2847             
2848                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2849             
2850                 GPRTemporary result(this);
2851                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2852                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2853             
2854                 jsValueResult(result.gpr(), node);
2855                 break;
2856             }
2857
2858             SpeculateCellOperand base(this, node->child1());
2859             SpeculateStrictInt32Operand property(this, node->child2());
2860             StorageOperand storage(this, node->child3());
2861             
2862             GPRReg baseReg = base.gpr();
2863             GPRReg propertyReg = property.gpr();
2864             GPRReg storageReg = storage.gpr();
2865             
2866             if (!m_compileOkay)
2867                 return;
2868             
2869             GPRTemporary result(this);
2870             GPRReg resultReg = result.gpr();
2871             
2872             MacroAssembler::JumpList slowCases;
2873             
2874             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2875     
2876             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2877             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2878     
2879             addSlowPathGenerator(
2880                 slowPathCall(
2881                     slowCases, this, operationGetByValArrayInt,
2882                     result.gpr(), baseReg, propertyReg));
2883             
2884             jsValueResult(resultReg, node);
2885             break;
2886         }
2887         case Array::String:
2888             compileGetByValOnString(node);
2889             break;
2890         case Array::DirectArguments:
2891             compileGetByValOnDirectArguments(node);
2892             break;
2893         case Array::ScopedArguments:
2894             compileGetByValOnScopedArguments(node);
2895             break;
2896         default: {
2897             TypedArrayType type = node->arrayMode().typedArrayType();
2898             if (isInt(type))
2899                 compileGetByValOnIntTypedArray(node, type);
2900             else
2901                 compileGetByValOnFloatTypedArray(node, type);
2902         } }
2903         break;
2904     }
2905
2906     case GetByValWithThis: {
2907         JSValueOperand base(this, node->child1());
2908         GPRReg baseGPR = base.gpr();
2909         JSValueOperand thisValue(this, node->child2());
2910         GPRReg thisValueGPR = thisValue.gpr();
2911         JSValueOperand subscript(this, node->child3());
2912         GPRReg subscriptGPR = subscript.gpr();
2913
2914         GPRFlushedCallResult result(this);
2915         GPRReg resultGPR = result.gpr();
2916
2917         flushRegisters();
2918         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2919         m_jit.exceptionCheck();
2920
2921         jsValueResult(resultGPR, node);
2922         break;
2923     }
2924
2925     case PutByValDirect:
2926     case PutByVal:
2927     case PutByValAlias: {
2928         Edge child1 = m_jit.graph().varArgChild(node, 0);
2929         Edge child2 = m_jit.graph().varArgChild(node, 1);
2930         Edge child3 = m_jit.graph().varArgChild(node, 2);
2931         Edge child4 = m_jit.graph().varArgChild(node, 3);
2932         
2933         ArrayMode arrayMode = node->arrayMode().modeForPut();
2934         bool alreadyHandled = false;
2935         
2936         switch (arrayMode.type()) {
2937         case Array::SelectUsingPredictions:
2938         case Array::ForceExit:
2939             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2940             break;
2941         case Array::Generic: {
2942             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2943             
2944             JSValueOperand arg1(this, child1);
2945             JSValueOperand arg2(this, child2);
2946             JSValueOperand arg3(this, child3);
2947             GPRReg arg1GPR = arg1.gpr();
2948             GPRReg arg2GPR = arg2.gpr();
2949             GPRReg arg3GPR = arg3.gpr();
2950             flushRegisters();
2951             if (node->op() == PutByValDirect)
2952                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2953             else
2954                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2955             m_jit.exceptionCheck();
2956             
2957             noResult(node);
2958             alreadyHandled = true;
2959             break;
2960         }
2961         default:
2962             break;
2963         }
2964         
2965         if (alreadyHandled)
2966             break;
2967         
2968         // FIXME: the base may not be necessary for some array access modes. But we have to
2969         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2970         // no harm in locking it here.
2971         SpeculateCellOperand base(this, child1);
2972         SpeculateStrictInt32Operand property(this, child2);
2973         
2974         GPRReg baseReg = base.gpr();
2975         GPRReg propertyReg = property.gpr();
2976
2977         switch (arrayMode.type()) {
2978         case Array::Int32:
2979         case Array::Contiguous: {
2980             JSValueOperand value(this, child3, ManualOperandSpeculation);
2981
2982             GPRReg valueReg = value.gpr();
2983         
2984             if (!m_compileOkay)
2985                 return;
2986             
2987             if (arrayMode.type() == Array::Int32) {
2988                 DFG_TYPE_CHECK(
2989                     JSValueRegs(valueReg), child3, SpecInt32Only,
2990                     m_jit.branch64(
2991                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2992             }
2993
2994             StorageOperand storage(this, child4);
2995             GPRReg storageReg = storage.gpr();
2996
2997             if (node->op() == PutByValAlias) {
2998                 // Store the value to the array.
2999                 GPRReg propertyReg = property.gpr();
3000                 GPRReg valueReg = value.gpr();
3001                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3002                 
3003                 noResult(node);
3004                 break;
3005             }
3006             
3007             GPRTemporary temporary;
3008             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3009
3010             MacroAssembler::Jump slowCase;
3011             
3012             if (arrayMode.isInBounds()) {
3013                 speculationCheck(
3014                     OutOfBounds, JSValueRegs(), 0,
3015                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3016             } else {
3017                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3018                 
3019                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3020                 
3021                 if (!arrayMode.isOutOfBounds())
3022                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3023                 
3024                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3025                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3026                 
3027                 inBounds.link(&m_jit);
3028             }
3029             
3030             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3031
3032             base.use();
3033             property.use();
3034             value.use();
3035             storage.use();
3036             
3037             if (arrayMode.isOutOfBounds()) {
3038                 if (node->op() == PutByValDirect) {
3039                     addSlowPathGenerator(slowPathCall(
3040                         slowCase, this,
3041                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3042                         NoResult, baseReg, propertyReg, valueReg));
3043                 } else {
3044                     addSlowPathGenerator(slowPathCall(
3045                         slowCase, this,
3046                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3047                         NoResult, baseReg, propertyReg, valueReg));
3048                 }
3049             }
3050
3051             noResult(node, UseChildrenCalledExplicitly);
3052             break;
3053         }
3054             
3055         case Array::Double: {
3056             compileDoublePutByVal(node, base, property);
3057             break;
3058         }
3059             
3060         case Array::ArrayStorage:
3061         case Array::SlowPutArrayStorage: {
3062             JSValueOperand value(this, child3);
3063
3064             GPRReg valueReg = value.gpr();
3065         
3066             if (!m_compileOkay)
3067                 return;
3068
3069             StorageOperand storage(this, child4);
3070             GPRReg storageReg = storage.gpr();
3071
3072             if (node->op() == PutByValAlias) {
3073                 // Store the value to the array.
3074                 GPRReg propertyReg = property.gpr();
3075                 GPRReg valueReg = value.gpr();
3076                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3077                 
3078                 noResult(node);
3079                 break;
3080             }
3081             
3082             GPRTemporary temporary;
3083             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3084
3085             MacroAssembler::JumpList slowCases;
3086
3087             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3088             if (!arrayMode.isOutOfBounds())
3089                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3090             else
3091                 slowCases.append(beyondArrayBounds);
3092
3093             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3094             if (arrayMode.isInBounds()) {
3095                 speculationCheck(
3096                     StoreToHole, JSValueRegs(), 0,
3097                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
3098             } else {
3099                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3100                 if (arrayMode.isSlowPut()) {
3101                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3102                     // the above branch. But it's simply not worth it since this only happens if we're
3103                     // already having a bad time.
3104                     slowCases.append(m_jit.jump());
3105                 } else {
3106                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3107                 
3108                     // If we're writing to a hole we might be growing the array; 
3109                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3110                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3111                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3112                 
3113                     lengthDoesNotNeedUpdate.link(&m_jit);
3114                 }
3115                 notHoleValue.link(&m_jit);
3116             }
3117     
3118             // Store the value to the array.
3119             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3120
3121             base.use();
3122             property.use();
3123             value.use();
3124             storage.use();
3125             
3126             if (!slowCases.empty()) {
3127                 if (node->op() == PutByValDirect) {
3128                     addSlowPathGenerator(slowPathCall(
3129                         slowCases, this,
3130                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3131                         NoResult, baseReg, propertyReg, valueReg));
3132                 } else {
3133                     addSlowPathGenerator(slowPathCall(
3134                         slowCases, this,
3135                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3136                         NoResult, baseReg, propertyReg, valueReg));
3137                 }
3138             }
3139
3140             noResult(node, UseChildrenCalledExplicitly);
3141             break;
3142         }
3143             
3144         default: {
3145             TypedArrayType type = arrayMode.typedArrayType();
3146             if (isInt(type))
3147                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3148             else
3149                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3150         } }
3151
3152         break;
3153     }
3154
3155     case RegExpExec: {
3156         bool sample = false;
3157
3158         if (sample)
3159             m_jit.incrementSuperSamplerCount();
3160         
3161         SpeculateCellOperand globalObject(this, node->child1());
3162         GPRReg globalObjectGPR = globalObject.gpr();
3163         
3164         if (node->child2().useKind() == RegExpObjectUse) {
3165             if (node->child3().useKind() == StringUse) {
3166                 SpeculateCellOperand base(this, node->child2());
3167                 SpeculateCellOperand argument(this, node->child3());
3168                 GPRReg baseGPR = base.gpr();
3169                 GPRReg argumentGPR = argument.gpr();
3170                 speculateRegExpObject(node->child2(), baseGPR);
3171                 speculateString(node->child3(), argumentGPR);
3172                 
3173                 flushRegisters();
3174                 GPRFlushedCallResult result(this);
3175                 callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3176                 m_jit.exceptionCheck();
3177                 
3178                 jsValueResult(result.gpr(), node);
3179
3180                 if (sample)
3181                     m_jit.decrementSuperSamplerCount();
3182                 break;
3183             }
3184             
3185             SpeculateCellOperand base(this, node->child2());
3186             JSValueOperand argument(this, node->child3());
3187             GPRReg baseGPR = base.gpr();
3188