[WTF] Import std::optional reference implementation as WTF::Optional
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT64.cpp
1 /*
2  * Copyright (C) 2011-2016 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
855             for (unsigned i = 0; i < numPassedArgs; ++i) {
856                 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
857                 GenerationInfo& info = generationInfo(argEdge.node());
858                 if (!isDirect)
859                     use(argEdge);
860                 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
861             }
862             
863             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
864                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
865
866             shuffleData.setupCalleeSaveRegisters(m_jit.codeBlock());
867         } else {
868             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCount));
869
870             for (unsigned i = 0; i < numPassedArgs; i++) {
871                 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
872                 JSValueOperand arg(this, argEdge);
873                 GPRReg argGPR = arg.gpr();
874                 use(argEdge);
875                 
876                 m_jit.store64(argGPR, JITCompiler::calleeArgumentSlot(i));
877             }
878             
879             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
880                 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
881         }
882     }
883     
884     if (!isTail || isVarargs || isForwardVarargs) {
885         Edge calleeEdge = m_jit.graph().child(node, 0);
886         JSValueOperand callee(this, calleeEdge);
887         calleeGPR = callee.gpr();
888         callee.use();
889         m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
890
891         flushRegisters();
892     }
893
894     CodeOrigin staticOrigin = node->origin.semantic;
895     ASSERT(!isTail || !staticOrigin.inlineCallFrame || !staticOrigin.inlineCallFrame->getCallerSkippingTailCalls());
896     ASSERT(!isEmulatedTail || (staticOrigin.inlineCallFrame && staticOrigin.inlineCallFrame->getCallerSkippingTailCalls()));
897     CodeOrigin dynamicOrigin =
898         isEmulatedTail ? *staticOrigin.inlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
899
900     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
901     
902     auto setResultAndResetStack = [&] () {
903         GPRFlushedCallResult result(this);
904         GPRReg resultGPR = result.gpr();
905         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
906
907         jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
908
909         // After the calls are done, we need to reestablish our stack
910         // pointer. We rely on this for varargs calls, calls with arity
911         // mismatch (the callframe is slided) and tail calls.
912         m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
913     };
914     
915     CallLinkInfo* callLinkInfo = m_jit.codeBlock()->addCallLinkInfo();
916     callLinkInfo->setUpCall(callType, m_currentNode->origin.semantic, calleeGPR);
917
918     if (node->op() == CallEval) {
919         // We want to call operationCallEval but we don't want to overwrite the parameter area in
920         // which we have created a prototypical eval call frame. This means that we have to
921         // subtract stack to make room for the call. Lucky for us, at this point we have the whole
922         // register file to ourselves.
923         
924         m_jit.emitStoreCallSiteIndex(callSite);
925         m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
926         m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
927         
928         // Now we need to make room for:
929         // - The caller frame and PC of a call to operationCallEval.
930         // - Potentially two arguments on the stack.
931         unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
932         requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
933         m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
934         m_jit.setupArgumentsWithExecState(GPRInfo::regT0);
935         prepareForExternalCall();
936         m_jit.appendCall(operationCallEval);
937         m_jit.exceptionCheck();
938         JITCompiler::Jump done = m_jit.branchTest64(JITCompiler::NonZero, GPRInfo::returnValueGPR);
939         
940         // This is the part where we meant to make a normal call. Oops.
941         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
942         m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
943         m_jit.emitDumbVirtualCall(callLinkInfo);
944         
945         done.link(&m_jit);
946         setResultAndResetStack();
947         return;
948     }
949     
950     if (isDirect) {
951         callLinkInfo->setExecutableDuringCompilation(executable);
952         callLinkInfo->setMaxNumArguments(numAllocatedArgs);
953
954         if (isTail) {
955             RELEASE_ASSERT(node->op() == DirectTailCall);
956             
957             JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
958             JITCompiler::Label mainPath = m_jit.label();
959             
960             m_jit.emitStoreCallSiteIndex(callSite);
961             
962             callLinkInfo->setFrameShuffleData(shuffleData);
963             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
964             
965             JITCompiler::Call call = m_jit.nearTailCall();
966             
967             JITCompiler::Label slowPath = m_jit.label();
968             patchableJump.m_jump.linkTo(slowPath, &m_jit);
969             
970             silentSpillAllRegisters(InvalidGPRReg);
971             callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
972             silentFillAllRegisters(InvalidGPRReg);
973             m_jit.exceptionCheck();
974             m_jit.jump().linkTo(mainPath, &m_jit);
975             
976             useChildren(node);
977             
978             m_jit.addJSDirectTailCall(patchableJump, call, slowPath, callLinkInfo);
979             return;
980         }
981         
982         JITCompiler::Label mainPath = m_jit.label();
983         
984         m_jit.emitStoreCallSiteIndex(callSite);
985         
986         JITCompiler::Call call = m_jit.nearCall();
987         JITCompiler::Jump done = m_jit.jump();
988         
989         JITCompiler::Label slowPath = m_jit.label();
990         if (isX86())
991             m_jit.pop(JITCompiler::selectScratchGPR(calleeGPR));
992
993         callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
994         m_jit.exceptionCheck();
995         m_jit.jump().linkTo(mainPath, &m_jit);
996         
997         done.link(&m_jit);
998         
999         setResultAndResetStack();
1000         
1001         m_jit.addJSDirectCall(call, slowPath, callLinkInfo);
1002         return;
1003     }
1004     
1005     m_jit.emitStoreCallSiteIndex(callSite);
1006     
1007     JITCompiler::DataLabelPtr targetToCheck;
1008     JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0));
1009
1010     if (isTail) {
1011         if (node->op() == TailCall) {
1012             callLinkInfo->setFrameShuffleData(shuffleData);
1013             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
1014         } else {
1015             m_jit.emitRestoreCalleeSaves();
1016             m_jit.prepareForTailCallSlow();
1017         }
1018     }
1019
1020     JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
1021
1022     JITCompiler::Jump done = m_jit.jump();
1023
1024     slowPath.link(&m_jit);
1025
1026     if (node->op() == TailCall) {
1027         CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
1028         callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
1029         callFrameShuffler.prepareForSlowPath();
1030     } else {
1031         m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
1032
1033         if (isTail)
1034             m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
1035     }
1036
1037     m_jit.move(MacroAssembler::TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
1038     JITCompiler::Call slowCall = m_jit.nearCall();
1039
1040     done.link(&m_jit);
1041
1042     if (isTail)
1043         m_jit.abortWithReason(JITDidReturnFromTailCall);
1044     else
1045         setResultAndResetStack();
1046
1047     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
1048 }
1049
1050 // Clang should allow unreachable [[clang::fallthrough]] in template functions if any template expansion uses it
1051 // http://llvm.org/bugs/show_bug.cgi?id=18619
1052 #if COMPILER(CLANG) && defined(__has_warning)
1053 #pragma clang diagnostic push
1054 #if __has_warning("-Wimplicit-fallthrough")
1055 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
1056 #endif
1057 #endif
1058 template<bool strict>
1059 GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
1060 {
1061     AbstractValue& value = m_state.forNode(edge);
1062     SpeculatedType type = value.m_type;
1063     ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
1064
1065     m_interpreter.filter(value, SpecInt32Only);
1066     if (value.isClear()) {
1067         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1068         returnFormat = DataFormatInt32;
1069         return allocate();
1070     }
1071
1072     VirtualRegister virtualRegister = edge->virtualRegister();
1073     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1074
1075     switch (info.registerFormat()) {
1076     case DataFormatNone: {
1077         GPRReg gpr = allocate();
1078
1079         if (edge->hasConstant()) {
1080             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1081             ASSERT(edge->isInt32Constant());
1082             m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
1083             info.fillInt32(*m_stream, gpr);
1084             returnFormat = DataFormatInt32;
1085             return gpr;
1086         }
1087         
1088         DataFormat spillFormat = info.spillFormat();
1089         
1090         DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
1091         
1092         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1093         
1094         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
1095             // If we know this was spilled as an integer we can fill without checking.
1096             if (strict) {
1097                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1098                 info.fillInt32(*m_stream, gpr);
1099                 returnFormat = DataFormatInt32;
1100                 return gpr;
1101             }
1102             if (spillFormat == DataFormatInt32) {
1103                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1104                 info.fillInt32(*m_stream, gpr);
1105                 returnFormat = DataFormatInt32;
1106             } else {
1107                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1108                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1109                 returnFormat = DataFormatJSInt32;
1110             }
1111             return gpr;
1112         }
1113         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1114
1115         // Fill as JSValue, and fall through.
1116         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1117         m_gprs.unlock(gpr);
1118         FALLTHROUGH;
1119     }
1120
1121     case DataFormatJS: {
1122         DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
1123         // Check the value is an integer.
1124         GPRReg gpr = info.gpr();
1125         m_gprs.lock(gpr);
1126         if (type & ~SpecInt32Only)
1127             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1128         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1129         // If !strict we're done, return.
1130         if (!strict) {
1131             returnFormat = DataFormatJSInt32;
1132             return gpr;
1133         }
1134         // else fall through & handle as DataFormatJSInt32.
1135         m_gprs.unlock(gpr);
1136         FALLTHROUGH;
1137     }
1138
1139     case DataFormatJSInt32: {
1140         // In a strict fill we need to strip off the value tag.
1141         if (strict) {
1142             GPRReg gpr = info.gpr();
1143             GPRReg result;
1144             // If the register has already been locked we need to take a copy.
1145             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
1146             if (m_gprs.isLocked(gpr))
1147                 result = allocate();
1148             else {
1149                 m_gprs.lock(gpr);
1150                 info.fillInt32(*m_stream, gpr);
1151                 result = gpr;
1152             }
1153             m_jit.zeroExtend32ToPtr(gpr, result);
1154             returnFormat = DataFormatInt32;
1155             return result;
1156         }
1157
1158         GPRReg gpr = info.gpr();
1159         m_gprs.lock(gpr);
1160         returnFormat = DataFormatJSInt32;
1161         return gpr;
1162     }
1163
1164     case DataFormatInt32: {
1165         GPRReg gpr = info.gpr();
1166         m_gprs.lock(gpr);
1167         returnFormat = DataFormatInt32;
1168         return gpr;
1169     }
1170         
1171     case DataFormatJSDouble:
1172     case DataFormatCell:
1173     case DataFormatBoolean:
1174     case DataFormatJSCell:
1175     case DataFormatJSBoolean:
1176     case DataFormatDouble:
1177     case DataFormatStorage:
1178     case DataFormatInt52:
1179     case DataFormatStrictInt52:
1180         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1181         
1182     default:
1183         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1184         return InvalidGPRReg;
1185     }
1186 }
1187 #if COMPILER(CLANG) && defined(__has_warning)
1188 #pragma clang diagnostic pop
1189 #endif
1190
1191 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1192 {
1193     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1194 }
1195
1196 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1197 {
1198     DataFormat mustBeDataFormatInt32;
1199     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1200     DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
1201     return result;
1202 }
1203
1204 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1205 {
1206     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1207     AbstractValue& value = m_state.forNode(edge);
1208
1209     m_interpreter.filter(value, SpecAnyInt);
1210     if (value.isClear()) {
1211         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1212         return allocate();
1213     }
1214
1215     VirtualRegister virtualRegister = edge->virtualRegister();
1216     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1217
1218     switch (info.registerFormat()) {
1219     case DataFormatNone: {
1220         GPRReg gpr = allocate();
1221
1222         if (edge->hasConstant()) {
1223             JSValue jsValue = edge->asJSValue();
1224             ASSERT(jsValue.isAnyInt());
1225             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1226             int64_t value = jsValue.asAnyInt();
1227             if (desiredFormat == DataFormatInt52)
1228                 value = value << JSValue::int52ShiftAmount;
1229             m_jit.move(MacroAssembler::Imm64(value), gpr);
1230             info.fillGPR(*m_stream, gpr, desiredFormat);
1231             return gpr;
1232         }
1233         
1234         DataFormat spillFormat = info.spillFormat();
1235         
1236         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
1237         
1238         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1239         
1240         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1241         if (desiredFormat == DataFormatStrictInt52) {
1242             if (spillFormat == DataFormatInt52)
1243                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1244             info.fillStrictInt52(*m_stream, gpr);
1245             return gpr;
1246         }
1247         if (spillFormat == DataFormatStrictInt52)
1248             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1249         info.fillInt52(*m_stream, gpr);
1250         return gpr;
1251     }
1252
1253     case DataFormatStrictInt52: {
1254         GPRReg gpr = info.gpr();
1255         bool wasLocked = m_gprs.isLocked(gpr);
1256         lock(gpr);
1257         if (desiredFormat == DataFormatStrictInt52)
1258             return gpr;
1259         if (wasLocked) {
1260             GPRReg result = allocate();
1261             m_jit.move(gpr, result);
1262             unlock(gpr);
1263             gpr = result;
1264         } else
1265             info.fillInt52(*m_stream, gpr);
1266         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1267         return gpr;
1268     }
1269         
1270     case DataFormatInt52: {
1271         GPRReg gpr = info.gpr();
1272         bool wasLocked = m_gprs.isLocked(gpr);
1273         lock(gpr);
1274         if (desiredFormat == DataFormatInt52)
1275             return gpr;
1276         if (wasLocked) {
1277             GPRReg result = allocate();
1278             m_jit.move(gpr, result);
1279             unlock(gpr);
1280             gpr = result;
1281         } else
1282             info.fillStrictInt52(*m_stream, gpr);
1283         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1284         return gpr;
1285     }
1286
1287     default:
1288         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1289         return InvalidGPRReg;
1290     }
1291 }
1292
1293 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1294 {
1295     ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1296     ASSERT(edge->hasDoubleResult());
1297     VirtualRegister virtualRegister = edge->virtualRegister();
1298     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1299
1300     if (info.registerFormat() == DataFormatNone) {
1301         if (edge->hasConstant()) {
1302             if (edge->isNumberConstant()) {
1303                 FPRReg fpr = fprAllocate();
1304                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1305                 if (!doubleAsInt)
1306                     m_jit.moveZeroToDouble(fpr);
1307                 else {
1308                     GPRReg gpr = allocate();
1309                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1310                     m_jit.move64ToDouble(gpr, fpr);
1311                     unlock(gpr);
1312                 }
1313
1314                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1315                 info.fillDouble(*m_stream, fpr);
1316                 return fpr;
1317             }
1318             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1319             return fprAllocate();
1320         }
1321         
1322         DataFormat spillFormat = info.spillFormat();
1323         if (spillFormat != DataFormatDouble) {
1324             DFG_CRASH(
1325                 m_jit.graph(), m_currentNode, toCString(
1326                     "Expected ", edge, " to have double format but instead it is spilled as ",
1327                     dataFormatToString(spillFormat)).data());
1328         }
1329         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
1330         FPRReg fpr = fprAllocate();
1331         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1332         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1333         info.fillDouble(*m_stream, fpr);
1334         return fpr;
1335     }
1336
1337     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
1338     FPRReg fpr = info.fpr();
1339     m_fprs.lock(fpr);
1340     return fpr;
1341 }
1342
1343 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1344 {
1345     AbstractValue& value = m_state.forNode(edge);
1346     SpeculatedType type = value.m_type;
1347     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1348
1349     m_interpreter.filter(value, SpecCell);
1350     if (value.isClear()) {
1351         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1352         return allocate();
1353     }
1354
1355     VirtualRegister virtualRegister = edge->virtualRegister();
1356     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1357
1358     switch (info.registerFormat()) {
1359     case DataFormatNone: {
1360         GPRReg gpr = allocate();
1361
1362         if (edge->hasConstant()) {
1363             JSValue jsValue = edge->asJSValue();
1364             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1365             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1366             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1367             return gpr;
1368         }
1369
1370         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1371         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1372
1373         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1374         if (type & ~SpecCell)
1375             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1376         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1377         return gpr;
1378     }
1379
1380     case DataFormatCell:
1381     case DataFormatJSCell: {
1382         GPRReg gpr = info.gpr();
1383         m_gprs.lock(gpr);
1384         if (!ASSERT_DISABLED) {
1385             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1386             m_jit.abortWithReason(DFGIsNotCell);
1387             checkCell.link(&m_jit);
1388         }
1389         return gpr;
1390     }
1391
1392     case DataFormatJS: {
1393         GPRReg gpr = info.gpr();
1394         m_gprs.lock(gpr);
1395         if (type & ~SpecCell)
1396             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1397         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1398         return gpr;
1399     }
1400
1401     case DataFormatJSInt32:
1402     case DataFormatInt32:
1403     case DataFormatJSDouble:
1404     case DataFormatJSBoolean:
1405     case DataFormatBoolean:
1406     case DataFormatDouble:
1407     case DataFormatStorage:
1408     case DataFormatInt52:
1409     case DataFormatStrictInt52:
1410         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1411         
1412     default:
1413         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1414         return InvalidGPRReg;
1415     }
1416 }
1417
1418 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1419 {
1420     AbstractValue& value = m_state.forNode(edge);
1421     SpeculatedType type = value.m_type;
1422     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1423
1424     m_interpreter.filter(value, SpecBoolean);
1425     if (value.isClear()) {
1426         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1427         return allocate();
1428     }
1429
1430     VirtualRegister virtualRegister = edge->virtualRegister();
1431     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1432
1433     switch (info.registerFormat()) {
1434     case DataFormatNone: {
1435         GPRReg gpr = allocate();
1436
1437         if (edge->hasConstant()) {
1438             JSValue jsValue = edge->asJSValue();
1439             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1440             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1441             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1442             return gpr;
1443         }
1444         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
1445         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1446         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1447
1448         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1449         if (type & ~SpecBoolean) {
1450             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1451             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1452             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1453         }
1454         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1455         return gpr;
1456     }
1457
1458     case DataFormatBoolean:
1459     case DataFormatJSBoolean: {
1460         GPRReg gpr = info.gpr();
1461         m_gprs.lock(gpr);
1462         return gpr;
1463     }
1464
1465     case DataFormatJS: {
1466         GPRReg gpr = info.gpr();
1467         m_gprs.lock(gpr);
1468         if (type & ~SpecBoolean) {
1469             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1470             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1471             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1472         }
1473         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1474         return gpr;
1475     }
1476
1477     case DataFormatJSInt32:
1478     case DataFormatInt32:
1479     case DataFormatJSDouble:
1480     case DataFormatJSCell:
1481     case DataFormatCell:
1482     case DataFormatDouble:
1483     case DataFormatStorage:
1484     case DataFormatInt52:
1485     case DataFormatStrictInt52:
1486         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1487         
1488     default:
1489         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1490         return InvalidGPRReg;
1491     }
1492 }
1493
1494 void SpeculativeJIT::compileObjectEquality(Node* node)
1495 {
1496     SpeculateCellOperand op1(this, node->child1());
1497     SpeculateCellOperand op2(this, node->child2());
1498     GPRTemporary result(this, Reuse, op1);
1499     
1500     GPRReg op1GPR = op1.gpr();
1501     GPRReg op2GPR = op2.gpr();
1502     GPRReg resultGPR = result.gpr();
1503    
1504     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1505         DFG_TYPE_CHECK(
1506             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1507         DFG_TYPE_CHECK(
1508             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1509     } else {
1510         DFG_TYPE_CHECK(
1511             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1512         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1513             m_jit.branchTest8(
1514                 MacroAssembler::NonZero, 
1515                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1516                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1517
1518         DFG_TYPE_CHECK(
1519             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1520         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1521             m_jit.branchTest8(
1522                 MacroAssembler::NonZero, 
1523                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1524                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1525     }
1526
1527     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1528     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1529     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1530 }
1531
1532 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1533 {
1534     SpeculateCellOperand op1(this, objectChild);
1535     JSValueOperand op2(this, otherChild);
1536     GPRTemporary result(this);
1537
1538     GPRReg op1GPR = op1.gpr();
1539     GPRReg op2GPR = op2.gpr();
1540     GPRReg resultGPR = result.gpr();
1541
1542     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1543
1544     // At this point we know that we can perform a straight-forward equality comparison on pointer
1545     // values because we are doing strict equality.
1546     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1547     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1548     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1549 }
1550     
1551 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1552 {
1553     BasicBlock* taken = branchNode->branchData()->taken.block;
1554     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1555     
1556     SpeculateCellOperand op1(this, objectChild);
1557     JSValueOperand op2(this, otherChild);
1558     
1559     GPRReg op1GPR = op1.gpr();
1560     GPRReg op2GPR = op2.gpr();
1561     
1562     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1563
1564     if (taken == nextBlock()) {
1565         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1566         jump(taken);
1567     } else {
1568         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1569         jump(notTaken);
1570     }
1571 }
1572
1573 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1574 {
1575     SpeculateCellOperand op1(this, leftChild);
1576     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1577     GPRTemporary result(this);
1578     
1579     GPRReg op1GPR = op1.gpr();
1580     GPRReg op2GPR = op2.gpr();
1581     GPRReg resultGPR = result.gpr();
1582
1583     bool masqueradesAsUndefinedWatchpointValid =
1584         masqueradesAsUndefinedWatchpointIsStillValid();
1585
1586     if (masqueradesAsUndefinedWatchpointValid) {
1587         DFG_TYPE_CHECK(
1588             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1589     } else {
1590         DFG_TYPE_CHECK(
1591             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1592         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1593             m_jit.branchTest8(
1594                 MacroAssembler::NonZero, 
1595                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1596                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1597     }
1598     
1599     // It seems that most of the time when programs do a == b where b may be either null/undefined
1600     // or an object, b is usually an object. Balance the branches to make that case fast.
1601     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1602     
1603     // We know that within this branch, rightChild must be a cell. 
1604     if (masqueradesAsUndefinedWatchpointValid) {
1605         DFG_TYPE_CHECK(
1606             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1607     } else {
1608         DFG_TYPE_CHECK(
1609             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1610         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1611             m_jit.branchTest8(
1612                 MacroAssembler::NonZero, 
1613                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1614                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1615     }
1616     
1617     // At this point we know that we can perform a straight-forward equality comparison on pointer
1618     // values because both left and right are pointers to objects that have no special equality
1619     // protocols.
1620     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1621     MacroAssembler::Jump done = m_jit.jump();
1622     
1623     rightNotCell.link(&m_jit);
1624     
1625     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1626     // prove that it is either null or undefined.
1627     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1628         m_jit.move(op2GPR, resultGPR);
1629         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1630         
1631         typeCheck(
1632             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther,
1633             m_jit.branch64(
1634                 MacroAssembler::NotEqual, resultGPR,
1635                 MacroAssembler::TrustedImm64(ValueNull)));
1636     }
1637     m_jit.move(TrustedImm32(0), result.gpr());
1638
1639     done.link(&m_jit);
1640     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1641     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1642 }
1643
1644 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1645 {
1646     BasicBlock* taken = branchNode->branchData()->taken.block;
1647     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1648     
1649     SpeculateCellOperand op1(this, leftChild);
1650     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1651     GPRTemporary result(this);
1652     
1653     GPRReg op1GPR = op1.gpr();
1654     GPRReg op2GPR = op2.gpr();
1655     GPRReg resultGPR = result.gpr();
1656     
1657     bool masqueradesAsUndefinedWatchpointValid = 
1658         masqueradesAsUndefinedWatchpointIsStillValid();
1659
1660     if (masqueradesAsUndefinedWatchpointValid) {
1661         DFG_TYPE_CHECK(
1662             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1663     } else {
1664         DFG_TYPE_CHECK(
1665             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1666         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1667             m_jit.branchTest8(
1668                 MacroAssembler::NonZero, 
1669                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1670                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1671     }
1672
1673     // It seems that most of the time when programs do a == b where b may be either null/undefined
1674     // or an object, b is usually an object. Balance the branches to make that case fast.
1675     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1676     
1677     // We know that within this branch, rightChild must be a cell. 
1678     if (masqueradesAsUndefinedWatchpointValid) {
1679         DFG_TYPE_CHECK(
1680             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1681     } else {
1682         DFG_TYPE_CHECK(
1683             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1684         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1685             m_jit.branchTest8(
1686                 MacroAssembler::NonZero, 
1687                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1688                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1689     }
1690     
1691     // At this point we know that we can perform a straight-forward equality comparison on pointer
1692     // values because both left and right are pointers to objects that have no special equality
1693     // protocols.
1694     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1695     
1696     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1697     // prove that it is either null or undefined.
1698     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1699         rightNotCell.link(&m_jit);
1700     else {
1701         jump(notTaken, ForceJump);
1702         
1703         rightNotCell.link(&m_jit);
1704         m_jit.move(op2GPR, resultGPR);
1705         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1706         
1707         typeCheck(
1708             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64(
1709                 MacroAssembler::NotEqual, resultGPR,
1710                 MacroAssembler::TrustedImm64(ValueNull)));
1711     }
1712     
1713     jump(notTaken);
1714 }
1715
1716 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1717 {
1718     SpeculateCellOperand symbol(this, symbolEdge);
1719     JSValueOperand untyped(this, untypedEdge);
1720     GPRTemporary result(this, Reuse, symbol, untyped);
1721
1722     GPRReg symbolGPR = symbol.gpr();
1723     GPRReg untypedGPR = untyped.gpr();
1724     GPRReg resultGPR = result.gpr();
1725
1726     speculateSymbol(symbolEdge, symbolGPR);
1727
1728     // At this point we know that we can perform a straight-forward equality comparison on pointer
1729     // values because we are doing strict equality.
1730     m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
1731     unblessedBooleanResult(resultGPR, node);
1732 }
1733
1734 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1735 {
1736     if (node->child1()->isInt32Constant()) {
1737         SpeculateInt32Operand op2(this, node->child2());
1738         GPRTemporary result(this, Reuse, op2);
1739         int32_t imm = node->child1()->asInt32();
1740         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1741
1742         // If we add a DataFormatBool, we should use it here.
1743         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1744         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1745     } else if (node->child2()->isInt32Constant()) {
1746         SpeculateInt32Operand op1(this, node->child1());
1747         GPRTemporary result(this, Reuse, op1);
1748         int32_t imm = node->child2()->asInt32();
1749         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1750
1751         // If we add a DataFormatBool, we should use it here.
1752         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1753         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1754     } else {
1755         SpeculateInt32Operand op1(this, node->child1());
1756         SpeculateInt32Operand op2(this, node->child2());
1757         GPRTemporary result(this, Reuse, op1, op2);
1758         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1759
1760         // If we add a DataFormatBool, we should use it here.
1761         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1762         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1763     }
1764 }
1765
1766 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1767 {
1768     SpeculateWhicheverInt52Operand op1(this, node->child1());
1769     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1770     GPRTemporary result(this, Reuse, op1, op2);
1771     
1772     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1773     
1774     // If we add a DataFormatBool, we should use it here.
1775     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1776     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1777 }
1778
1779 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1780 {
1781     BasicBlock* taken = branchNode->branchData()->taken.block;
1782     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1783
1784     // The branch instruction will branch to the taken block.
1785     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1786     if (taken == nextBlock()) {
1787         condition = JITCompiler::invert(condition);
1788         BasicBlock* tmp = taken;
1789         taken = notTaken;
1790         notTaken = tmp;
1791     }
1792     
1793     SpeculateWhicheverInt52Operand op1(this, node->child1());
1794     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1795     
1796     branch64(condition, op1.gpr(), op2.gpr(), taken);
1797     jump(notTaken);
1798 }
1799
1800 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1801 {
1802     SpeculateDoubleOperand op1(this, node->child1());
1803     SpeculateDoubleOperand op2(this, node->child2());
1804     GPRTemporary result(this);
1805     
1806     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1807     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1808     m_jit.xor64(TrustedImm32(true), result.gpr());
1809     trueCase.link(&m_jit);
1810     
1811     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1812 }
1813
1814 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1815 {
1816     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1817     GPRTemporary result(this);
1818     GPRReg valueGPR = value.gpr();
1819     GPRReg resultGPR = result.gpr();
1820     GPRTemporary structure;
1821     GPRReg structureGPR = InvalidGPRReg;
1822     GPRTemporary scratch;
1823     GPRReg scratchGPR = InvalidGPRReg;
1824
1825     bool masqueradesAsUndefinedWatchpointValid =
1826         masqueradesAsUndefinedWatchpointIsStillValid();
1827
1828     if (!masqueradesAsUndefinedWatchpointValid) {
1829         // The masquerades as undefined case will use the structure register, so allocate it here.
1830         // Do this at the top of the function to avoid branching around a register allocation.
1831         GPRTemporary realStructure(this);
1832         GPRTemporary realScratch(this);
1833         structure.adopt(realStructure);
1834         scratch.adopt(realScratch);
1835         structureGPR = structure.gpr();
1836         scratchGPR = scratch.gpr();
1837     }
1838
1839     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1840     if (masqueradesAsUndefinedWatchpointValid) {
1841         DFG_TYPE_CHECK(
1842             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1843     } else {
1844         DFG_TYPE_CHECK(
1845             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1846
1847         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1848             m_jit.branchTest8(
1849                 MacroAssembler::Zero, 
1850                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1851                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1852
1853         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1854         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1855             m_jit.branchPtr(
1856                 MacroAssembler::Equal, 
1857                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1858                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1859
1860         isNotMasqueradesAsUndefined.link(&m_jit);
1861     }
1862     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1863     MacroAssembler::Jump done = m_jit.jump();
1864     
1865     notCell.link(&m_jit);
1866
1867     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1868         m_jit.move(valueGPR, resultGPR);
1869         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1870         typeCheck(
1871             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1872                 MacroAssembler::NotEqual, 
1873                 resultGPR, 
1874                 MacroAssembler::TrustedImm64(ValueNull)));
1875     }
1876     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1877     
1878     done.link(&m_jit);
1879     
1880     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1881 }
1882
1883 void SpeculativeJIT::compileLogicalNot(Node* node)
1884 {
1885     switch (node->child1().useKind()) {
1886     case ObjectOrOtherUse: {
1887         compileObjectOrOtherLogicalNot(node->child1());
1888         return;
1889     }
1890         
1891     case Int32Use: {
1892         SpeculateInt32Operand value(this, node->child1());
1893         GPRTemporary result(this, Reuse, value);
1894         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1895         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1896         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1897         return;
1898     }
1899         
1900     case DoubleRepUse: {
1901         SpeculateDoubleOperand value(this, node->child1());
1902         FPRTemporary scratch(this);
1903         GPRTemporary result(this);
1904         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1905         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1906         m_jit.xor32(TrustedImm32(true), result.gpr());
1907         nonZero.link(&m_jit);
1908         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1909         return;
1910     }
1911     
1912     case BooleanUse:
1913     case KnownBooleanUse: {
1914         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1915             SpeculateBooleanOperand value(this, node->child1());
1916             GPRTemporary result(this, Reuse, value);
1917             
1918             m_jit.move(value.gpr(), result.gpr());
1919             m_jit.xor64(TrustedImm32(true), result.gpr());
1920             
1921             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1922             return;
1923         }
1924         
1925         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1926         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1927         
1928         m_jit.move(value.gpr(), result.gpr());
1929         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1930         typeCheck(
1931             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1932                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1933         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1934         
1935         // If we add a DataFormatBool, we should use it here.
1936         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1937         return;
1938     }
1939         
1940     case UntypedUse: {
1941         JSValueOperand arg1(this, node->child1());
1942         GPRTemporary result(this);
1943     
1944         GPRReg arg1GPR = arg1.gpr();
1945         GPRReg resultGPR = result.gpr();
1946
1947         FPRTemporary valueFPR(this);
1948         FPRTemporary tempFPR(this);
1949
1950         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1951         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1952         std::optional<GPRTemporary> scratch;
1953         GPRReg scratchGPR = InvalidGPRReg;
1954         if (shouldCheckMasqueradesAsUndefined) {
1955             scratch.emplace(this);
1956             scratchGPR = scratch->gpr();
1957         }
1958         bool negateResult = true;
1959         m_jit.emitConvertValueToBoolean(JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1960         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1961         jsValueResult(resultGPR, node, DataFormatJSBoolean);
1962         return;
1963     }
1964     case StringUse:
1965         return compileStringZeroLength(node);
1966
1967     case StringOrOtherUse:
1968         return compileLogicalNotStringOrOther(node);
1969
1970     default:
1971         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1972         break;
1973     }
1974 }
1975
1976 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1977 {
1978     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1979     GPRTemporary scratch(this);
1980     GPRTemporary structure;
1981     GPRReg valueGPR = value.gpr();
1982     GPRReg scratchGPR = scratch.gpr();
1983     GPRReg structureGPR = InvalidGPRReg;
1984
1985     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
1986         GPRTemporary realStructure(this);
1987         structure.adopt(realStructure);
1988         structureGPR = structure.gpr();
1989     }
1990
1991     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1992     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1993         DFG_TYPE_CHECK(
1994             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1995     } else {
1996         DFG_TYPE_CHECK(
1997             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1998
1999         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
2000             JITCompiler::Zero, 
2001             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
2002             TrustedImm32(MasqueradesAsUndefined));
2003
2004         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
2005         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
2006             m_jit.branchPtr(
2007                 MacroAssembler::Equal, 
2008                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
2009                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
2010
2011         isNotMasqueradesAsUndefined.link(&m_jit);
2012     }
2013     jump(taken, ForceJump);
2014     
2015     notCell.link(&m_jit);
2016     
2017     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
2018         m_jit.move(valueGPR, scratchGPR);
2019         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2020         typeCheck(
2021             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
2022                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2023     }
2024     jump(notTaken);
2025     
2026     noResult(m_currentNode);
2027 }
2028
2029 void SpeculativeJIT::emitBranch(Node* node)
2030 {
2031     BasicBlock* taken = node->branchData()->taken.block;
2032     BasicBlock* notTaken = node->branchData()->notTaken.block;
2033     
2034     switch (node->child1().useKind()) {
2035     case ObjectOrOtherUse: {
2036         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
2037         return;
2038     }
2039         
2040     case Int32Use:
2041     case DoubleRepUse: {
2042         if (node->child1().useKind() == Int32Use) {
2043             bool invert = false;
2044             
2045             if (taken == nextBlock()) {
2046                 invert = true;
2047                 BasicBlock* tmp = taken;
2048                 taken = notTaken;
2049                 notTaken = tmp;
2050             }
2051
2052             SpeculateInt32Operand value(this, node->child1());
2053             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2054         } else {
2055             SpeculateDoubleOperand value(this, node->child1());
2056             FPRTemporary scratch(this);
2057             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2058         }
2059         
2060         jump(notTaken);
2061         
2062         noResult(node);
2063         return;
2064     }
2065
2066     case StringUse: {
2067         emitStringBranch(node->child1(), taken, notTaken);
2068         return;
2069     }
2070
2071     case StringOrOtherUse: {
2072         emitStringOrOtherBranch(node->child1(), taken, notTaken);
2073         return;
2074     }
2075
2076     case UntypedUse:
2077     case BooleanUse:
2078     case KnownBooleanUse: {
2079         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2080         GPRReg valueGPR = value.gpr();
2081         
2082         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
2083             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
2084                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2085                 
2086                 if (taken == nextBlock()) {
2087                     condition = MacroAssembler::Zero;
2088                     BasicBlock* tmp = taken;
2089                     taken = notTaken;
2090                     notTaken = tmp;
2091                 }
2092                 
2093                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2094                 jump(notTaken);
2095             } else {
2096                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2097                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2098                 
2099                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
2100             }
2101             value.use();
2102         } else {
2103             GPRTemporary result(this);
2104             FPRTemporary fprValue(this);
2105             FPRTemporary fprTemp(this);
2106             std::optional<GPRTemporary> scratch;
2107
2108             GPRReg scratchGPR = InvalidGPRReg;
2109             bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
2110             if (shouldCheckMasqueradesAsUndefined) {
2111                 scratch.emplace(this);
2112                 scratchGPR = scratch->gpr();
2113             }
2114
2115             GPRReg resultGPR = result.gpr();
2116             FPRReg valueFPR = fprValue.fpr();
2117             FPRReg tempFPR = fprTemp.fpr();
2118             
2119             if (node->child1()->prediction() & SpecInt32Only) {
2120                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2121                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2122             }
2123     
2124             if (node->child1()->prediction() & SpecBoolean) {
2125                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2126                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2127             }
2128     
2129             value.use();
2130
2131             JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
2132             m_jit.emitConvertValueToBoolean(JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
2133     
2134             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2135             jump(notTaken);
2136         }
2137         
2138         noResult(node, UseChildrenCalledExplicitly);
2139         return;
2140     }
2141         
2142     default:
2143         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
2144     }
2145 }
2146
2147 void SpeculativeJIT::compile(Node* node)
2148 {
2149     NodeType op = node->op();
2150     
2151 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
2152     m_jit.clearRegisterAllocationOffsets();
2153 #endif
2154
2155     switch (op) {
2156     case JSConstant:
2157     case DoubleConstant:
2158     case Int52Constant:
2159     case PhantomDirectArguments:
2160     case PhantomClonedArguments:
2161         initConstantInfo(node);
2162         break;
2163
2164     case LazyJSConstant:
2165         compileLazyJSConstant(node);
2166         break;
2167
2168     case Identity: {
2169         speculate(node, node->child1());
2170         switch (node->child1().useKind()) {
2171         case DoubleRepUse:
2172         case DoubleRepRealUse:
2173         case DoubleRepAnyIntUse: {
2174             SpeculateDoubleOperand op(this, node->child1());
2175             FPRTemporary scratch(this, op);
2176             m_jit.moveDouble(op.fpr(), scratch.fpr());
2177             doubleResult(scratch.fpr(), node);
2178             break;
2179         }
2180         case Int52RepUse: {
2181             SpeculateInt52Operand op(this, node->child1());
2182             GPRTemporary result(this, Reuse, op);
2183             m_jit.move(op.gpr(), result.gpr());
2184             int52Result(result.gpr(), node);
2185             break;
2186         }
2187         default: {
2188             JSValueOperand op(this, node->child1());
2189             GPRTemporary result(this, Reuse, op);
2190             m_jit.move(op.gpr(), result.gpr());
2191             jsValueResult(result.gpr(), node);
2192             break;
2193         }
2194         } // switch
2195         break;
2196     }
2197
2198     case GetLocal: {
2199         AbstractValue& value = m_state.variables().operand(node->local());
2200
2201         // If the CFA is tracking this variable and it found that the variable
2202         // cannot have been assigned, then don't attempt to proceed.
2203         if (value.isClear()) {
2204             m_compileOkay = false;
2205             break;
2206         }
2207         
2208         switch (node->variableAccessData()->flushFormat()) {
2209         case FlushedDouble: {
2210             FPRTemporary result(this);
2211             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2212             VirtualRegister virtualRegister = node->virtualRegister();
2213             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2214             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2215             break;
2216         }
2217         
2218         case FlushedInt32: {
2219             GPRTemporary result(this);
2220             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2221             
2222             // Like int32Result, but don't useChildren - our children are phi nodes,
2223             // and don't represent values within this dataflow with virtual registers.
2224             VirtualRegister virtualRegister = node->virtualRegister();
2225             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2226             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2227             break;
2228         }
2229             
2230         case FlushedInt52: {
2231             GPRTemporary result(this);
2232             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2233             
2234             VirtualRegister virtualRegister = node->virtualRegister();
2235             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2236             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2237             break;
2238         }
2239             
2240         default:
2241             GPRTemporary result(this);
2242             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2243             
2244             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2245             // and don't represent values within this dataflow with virtual registers.
2246             VirtualRegister virtualRegister = node->virtualRegister();
2247             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2248             
2249             DataFormat format;
2250             if (isCellSpeculation(value.m_type))
2251                 format = DataFormatJSCell;
2252             else if (isBooleanSpeculation(value.m_type))
2253                 format = DataFormatJSBoolean;
2254             else
2255                 format = DataFormatJS;
2256             
2257             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2258             break;
2259         }
2260         break;
2261     }
2262
2263     case GetLocalUnlinked: {
2264         GPRTemporary result(this);
2265         
2266         m_jit.load64(JITCompiler::addressFor(node->unlinkedMachineLocal()), result.gpr());
2267         
2268         jsValueResult(result.gpr(), node);
2269         break;
2270     }
2271         
2272     case MovHint: {
2273         compileMovHint(m_currentNode);
2274         noResult(node);
2275         break;
2276     }
2277         
2278     case ZombieHint: {
2279         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2280         noResult(node);
2281         break;
2282     }
2283         
2284     case ExitOK: {
2285         noResult(node);
2286         break;
2287     }
2288         
2289     case SetLocal: {
2290         switch (node->variableAccessData()->flushFormat()) {
2291         case FlushedDouble: {
2292             SpeculateDoubleOperand value(this, node->child1());
2293             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2294             noResult(node);
2295             // Indicate that it's no longer necessary to retrieve the value of
2296             // this bytecode variable from registers or other locations in the stack,
2297             // but that it is stored as a double.
2298             recordSetLocal(DataFormatDouble);
2299             break;
2300         }
2301             
2302         case FlushedInt32: {
2303             SpeculateInt32Operand value(this, node->child1());
2304             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2305             noResult(node);
2306             recordSetLocal(DataFormatInt32);
2307             break;
2308         }
2309             
2310         case FlushedInt52: {
2311             SpeculateInt52Operand value(this, node->child1());
2312             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2313             noResult(node);
2314             recordSetLocal(DataFormatInt52);
2315             break;
2316         }
2317             
2318         case FlushedCell: {
2319             SpeculateCellOperand cell(this, node->child1());
2320             GPRReg cellGPR = cell.gpr();
2321             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2322             noResult(node);
2323             recordSetLocal(DataFormatCell);
2324             break;
2325         }
2326             
2327         case FlushedBoolean: {
2328             SpeculateBooleanOperand boolean(this, node->child1());
2329             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2330             noResult(node);
2331             recordSetLocal(DataFormatBoolean);
2332             break;
2333         }
2334             
2335         case FlushedJSValue: {
2336             JSValueOperand value(this, node->child1());
2337             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2338             noResult(node);
2339             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2340             break;
2341         }
2342             
2343         default:
2344             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2345             break;
2346         }
2347
2348         break;
2349     }
2350
2351     case SetArgument:
2352         // This is a no-op; it just marks the fact that the argument is being used.
2353         // But it may be profitable to use this as a hook to run speculation checks
2354         // on arguments, thereby allowing us to trivially eliminate such checks if
2355         // the argument is not used.
2356         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2357         break;
2358
2359     case BitAnd:
2360     case BitOr:
2361     case BitXor:
2362         compileBitwiseOp(node);
2363         break;
2364
2365     case BitRShift:
2366     case BitLShift:
2367     case BitURShift:
2368         compileShiftOp(node);
2369         break;
2370
2371     case UInt32ToNumber: {
2372         compileUInt32ToNumber(node);
2373         break;
2374     }
2375
2376     case DoubleAsInt32: {
2377         compileDoubleAsInt32(node);
2378         break;
2379     }
2380
2381     case ValueToInt32: {
2382         compileValueToInt32(node);
2383         break;
2384     }
2385         
2386     case DoubleRep: {
2387         compileDoubleRep(node);
2388         break;
2389     }
2390         
2391     case ValueRep: {
2392         compileValueRep(node);
2393         break;
2394     }
2395         
2396     case Int52Rep: {
2397         switch (node->child1().useKind()) {
2398         case Int32Use: {
2399             SpeculateInt32Operand operand(this, node->child1());
2400             GPRTemporary result(this, Reuse, operand);
2401             
2402             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2403             
2404             strictInt52Result(result.gpr(), node);
2405             break;
2406         }
2407             
2408         case AnyIntUse: {
2409             GPRTemporary result(this);
2410             GPRReg resultGPR = result.gpr();
2411             
2412             convertAnyInt(node->child1(), resultGPR);
2413             
2414             strictInt52Result(resultGPR, node);
2415             break;
2416         }
2417             
2418         case DoubleRepAnyIntUse: {
2419             SpeculateDoubleOperand value(this, node->child1());
2420             FPRReg valueFPR = value.fpr();
2421             
2422             GPRFlushedCallResult result(this);
2423             GPRReg resultGPR = result.gpr();
2424             
2425             flushRegisters();
2426             
2427             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2428             
2429             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2430                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2431                 m_jit.branch64(
2432                     JITCompiler::Equal, resultGPR,
2433                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2434             
2435             strictInt52Result(resultGPR, node);
2436             break;
2437         }
2438             
2439         default:
2440             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2441         }
2442         break;
2443     }
2444
2445     case ValueAdd:
2446         compileValueAdd(node);
2447         break;
2448
2449     case StrCat: {
2450         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2451         JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
2452         JSValueOperand op3(this, node->child3(), ManualOperandSpeculation);
2453         
2454         GPRReg op1GPR = op1.gpr();
2455         GPRReg op2GPR = op2.gpr();
2456         GPRReg op3GPR;
2457         if (node->child3())
2458             op3GPR = op3.gpr();
2459         else
2460             op3GPR = InvalidGPRReg;
2461         
2462         flushRegisters();
2463
2464         GPRFlushedCallResult result(this);
2465         if (node->child3())
2466             callOperation(operationStrCat3, result.gpr(), op1GPR, op2GPR, op3GPR);
2467         else
2468             callOperation(operationStrCat2, result.gpr(), op1GPR, op2GPR);
2469         m_jit.exceptionCheck();
2470         
2471         cellResult(result.gpr(), node);
2472         break;
2473     }
2474
2475     case ArithAdd:
2476         compileArithAdd(node);
2477         break;
2478
2479     case ArithClz32:
2480         compileArithClz32(node);
2481         break;
2482         
2483     case MakeRope:
2484         compileMakeRope(node);
2485         break;
2486
2487     case ArithSub:
2488         compileArithSub(node);
2489         break;
2490
2491     case ArithNegate:
2492         compileArithNegate(node);
2493         break;
2494
2495     case ArithMul:
2496         compileArithMul(node);
2497         break;
2498
2499     case ArithDiv: {
2500         compileArithDiv(node);
2501         break;
2502     }
2503
2504     case ArithMod: {
2505         compileArithMod(node);
2506         break;
2507     }
2508
2509     case ArithAbs:
2510         compileArithAbs(node);
2511         break;
2512         
2513     case ArithMin:
2514     case ArithMax: {
2515         switch (node->binaryUseKind()) {
2516         case Int32Use: {
2517             SpeculateStrictInt32Operand op1(this, node->child1());
2518             SpeculateStrictInt32Operand op2(this, node->child2());
2519             GPRTemporary result(this, Reuse, op1);
2520             
2521             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2522             m_jit.move(op2.gpr(), result.gpr());
2523             if (op1.gpr() != result.gpr()) {
2524                 MacroAssembler::Jump done = m_jit.jump();
2525                 op1Less.link(&m_jit);
2526                 m_jit.move(op1.gpr(), result.gpr());
2527                 done.link(&m_jit);
2528             } else
2529                 op1Less.link(&m_jit);
2530             
2531             int32Result(result.gpr(), node);
2532             break;
2533         }
2534         
2535         case DoubleRepUse: {
2536             SpeculateDoubleOperand op1(this, node->child1());
2537             SpeculateDoubleOperand op2(this, node->child2());
2538             FPRTemporary result(this, op1);
2539             
2540             FPRReg op1FPR = op1.fpr();
2541             FPRReg op2FPR = op2.fpr();
2542             FPRReg resultFPR = result.fpr();
2543         
2544             MacroAssembler::JumpList done;
2545         
2546             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2547         
2548             // op2 is eather the lesser one or one of then is NaN
2549             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2550         
2551             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2552             // op1 + op2 and putting it into result.
2553             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2554             done.append(m_jit.jump());
2555         
2556             op2Less.link(&m_jit);
2557             m_jit.moveDouble(op2FPR, resultFPR);
2558         
2559             if (op1FPR != resultFPR) {
2560                 done.append(m_jit.jump());
2561             
2562                 op1Less.link(&m_jit);
2563                 m_jit.moveDouble(op1FPR, resultFPR);
2564             } else
2565                 op1Less.link(&m_jit);
2566         
2567             done.link(&m_jit);
2568         
2569             doubleResult(resultFPR, node);
2570             break;
2571         }
2572             
2573         default:
2574             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2575             break;
2576         }
2577         break;
2578     }
2579
2580     case ArithPow:
2581         compileArithPow(node);
2582         break;
2583
2584     case ArithSqrt:
2585         compileArithSqrt(node);
2586         break;
2587
2588     case ArithFRound:
2589         compileArithFRound(node);
2590         break;
2591
2592     case ArithRandom:
2593         compileArithRandom(node);
2594         break;
2595
2596     case ArithRound:
2597     case ArithFloor:
2598     case ArithCeil:
2599     case ArithTrunc:
2600         compileArithRounding(node);
2601         break;
2602
2603     case ArithSin:
2604         compileArithSin(node);
2605         break;
2606
2607     case ArithCos:
2608         compileArithCos(node);
2609         break;
2610
2611     case ArithTan:
2612         compileArithTan(node);
2613         break;
2614
2615     case ArithLog:
2616         compileArithLog(node);
2617         break;
2618
2619     case LogicalNot:
2620         compileLogicalNot(node);
2621         break;
2622
2623     case CompareLess:
2624         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2625             return;
2626         break;
2627
2628     case CompareLessEq:
2629         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2630             return;
2631         break;
2632
2633     case CompareGreater:
2634         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2635             return;
2636         break;
2637
2638     case CompareGreaterEq:
2639         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2640             return;
2641         break;
2642
2643     case CompareEq:
2644         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2645             return;
2646         break;
2647
2648     case CompareStrictEq:
2649         if (compileStrictEq(node))
2650             return;
2651         break;
2652         
2653     case CompareEqPtr:
2654         compileCompareEqPtr(node);
2655         break;
2656
2657     case StringCharCodeAt: {
2658         compileGetCharCodeAt(node);
2659         break;
2660     }
2661
2662     case StringCharAt: {
2663         // Relies on StringCharAt node having same basic layout as GetByVal
2664         compileGetByValOnString(node);
2665         break;
2666     }
2667
2668     case StringFromCharCode: {
2669         compileFromCharCode(node);
2670         break;
2671     }
2672         
2673     case CheckArray: {
2674         checkArray(node);
2675         break;
2676     }
2677         
2678     case Arrayify:
2679     case ArrayifyToStructure: {
2680         arrayify(node);
2681         break;
2682     }
2683
2684     case GetByVal: {
2685         switch (node->arrayMode().type()) {
2686         case Array::SelectUsingPredictions:
2687         case Array::ForceExit:
2688             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2689             break;
2690         case Array::Undecided: {
2691             SpeculateStrictInt32Operand index(this, node->child2());
2692             GPRTemporary result(this, Reuse, index);
2693             GPRReg indexGPR = index.gpr();
2694             GPRReg resultGPR = result.gpr();
2695
2696             speculationCheck(OutOfBounds, JSValueRegs(), node,
2697                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2698
2699             use(node->child1());
2700             index.use();
2701
2702             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2703             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2704             break;
2705         }
2706         case Array::Generic: {
2707             JSValueOperand base(this, node->child1());
2708             JSValueOperand property(this, node->child2());
2709             GPRReg baseGPR = base.gpr();
2710             GPRReg propertyGPR = property.gpr();
2711             
2712             flushRegisters();
2713             GPRFlushedCallResult result(this);
2714             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2715             m_jit.exceptionCheck();
2716             
2717             jsValueResult(result.gpr(), node);
2718             break;
2719         }
2720         case Array::Int32:
2721         case Array::Contiguous: {
2722             if (node->arrayMode().isInBounds()) {
2723                 SpeculateStrictInt32Operand property(this, node->child2());
2724                 StorageOperand storage(this, node->child3());
2725                 
2726                 GPRReg propertyReg = property.gpr();
2727                 GPRReg storageReg = storage.gpr();
2728                 
2729                 if (!m_compileOkay)
2730                     return;
2731                 
2732                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2733                 
2734                 GPRTemporary result(this);
2735                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2736                 if (node->arrayMode().isSaneChain()) {
2737                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2738                     JITCompiler::Jump notHole = m_jit.branchTest64(
2739                         MacroAssembler::NonZero, result.gpr());
2740                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2741                     notHole.link(&m_jit);
2742                 } else {
2743                     speculationCheck(
2744                         LoadFromHole, JSValueRegs(), 0,
2745                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2746                 }
2747                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2748                 break;
2749             }
2750             
2751             SpeculateCellOperand base(this, node->child1());
2752             SpeculateStrictInt32Operand property(this, node->child2());
2753             StorageOperand storage(this, node->child3());
2754             
2755             GPRReg baseReg = base.gpr();
2756             GPRReg propertyReg = property.gpr();
2757             GPRReg storageReg = storage.gpr();
2758             
2759             if (!m_compileOkay)
2760                 return;
2761             
2762             GPRTemporary result(this);
2763             GPRReg resultReg = result.gpr();
2764             
2765             MacroAssembler::JumpList slowCases;
2766             
2767             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2768             
2769             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2770             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2771             
2772             addSlowPathGenerator(
2773                 slowPathCall(
2774                     slowCases, this, operationGetByValArrayInt,
2775                     result.gpr(), baseReg, propertyReg));
2776             
2777             jsValueResult(resultReg, node);
2778             break;
2779         }
2780
2781         case Array::Double: {
2782             if (node->arrayMode().isInBounds()) {
2783                 SpeculateStrictInt32Operand property(this, node->child2());
2784                 StorageOperand storage(this, node->child3());
2785             
2786                 GPRReg propertyReg = property.gpr();
2787                 GPRReg storageReg = storage.gpr();
2788             
2789                 if (!m_compileOkay)
2790                     return;
2791             
2792                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2793             
2794                 FPRTemporary result(this);
2795                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2796                 if (!node->arrayMode().isSaneChain())
2797                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2798                 doubleResult(result.fpr(), node);
2799                 break;
2800             }
2801
2802             SpeculateCellOperand base(this, node->child1());
2803             SpeculateStrictInt32Operand property(this, node->child2());
2804             StorageOperand storage(this, node->child3());
2805             
2806             GPRReg baseReg = base.gpr();
2807             GPRReg propertyReg = property.gpr();
2808             GPRReg storageReg = storage.gpr();
2809             
2810             if (!m_compileOkay)
2811                 return;
2812             
2813             GPRTemporary result(this);
2814             FPRTemporary temp(this);
2815             GPRReg resultReg = result.gpr();
2816             FPRReg tempReg = temp.fpr();
2817             
2818             MacroAssembler::JumpList slowCases;
2819             
2820             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2821             
2822             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2823             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2824             boxDouble(tempReg, resultReg);
2825             
2826             addSlowPathGenerator(
2827                 slowPathCall(
2828                     slowCases, this, operationGetByValArrayInt,
2829                     result.gpr(), baseReg, propertyReg));
2830             
2831             jsValueResult(resultReg, node);
2832             break;
2833         }
2834
2835         case Array::ArrayStorage:
2836         case Array::SlowPutArrayStorage: {
2837             if (node->arrayMode().isInBounds()) {
2838                 SpeculateStrictInt32Operand property(this, node->child2());
2839                 StorageOperand storage(this, node->child3());
2840             
2841                 GPRReg propertyReg = property.gpr();
2842                 GPRReg storageReg = storage.gpr();
2843             
2844                 if (!m_compileOkay)
2845                     return;
2846             
2847                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2848             
2849                 GPRTemporary result(this);
2850                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2851                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2852             
2853                 jsValueResult(result.gpr(), node);
2854                 break;
2855             }
2856
2857             SpeculateCellOperand base(this, node->child1());
2858             SpeculateStrictInt32Operand property(this, node->child2());
2859             StorageOperand storage(this, node->child3());
2860             
2861             GPRReg baseReg = base.gpr();
2862             GPRReg propertyReg = property.gpr();
2863             GPRReg storageReg = storage.gpr();
2864             
2865             if (!m_compileOkay)
2866                 return;
2867             
2868             GPRTemporary result(this);
2869             GPRReg resultReg = result.gpr();
2870             
2871             MacroAssembler::JumpList slowCases;
2872             
2873             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2874     
2875             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2876             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2877     
2878             addSlowPathGenerator(
2879                 slowPathCall(
2880                     slowCases, this, operationGetByValArrayInt,
2881                     result.gpr(), baseReg, propertyReg));
2882             
2883             jsValueResult(resultReg, node);
2884             break;
2885         }
2886         case Array::String:
2887             compileGetByValOnString(node);
2888             break;
2889         case Array::DirectArguments:
2890             compileGetByValOnDirectArguments(node);
2891             break;
2892         case Array::ScopedArguments:
2893             compileGetByValOnScopedArguments(node);
2894             break;
2895         default: {
2896             TypedArrayType type = node->arrayMode().typedArrayType();
2897             if (isInt(type))
2898                 compileGetByValOnIntTypedArray(node, type);
2899             else
2900                 compileGetByValOnFloatTypedArray(node, type);
2901         } }
2902         break;
2903     }
2904
2905     case GetByValWithThis: {
2906         JSValueOperand base(this, node->child1());
2907         GPRReg baseGPR = base.gpr();
2908         JSValueOperand thisValue(this, node->child2());
2909         GPRReg thisValueGPR = thisValue.gpr();
2910         JSValueOperand subscript(this, node->child3());
2911         GPRReg subscriptGPR = subscript.gpr();
2912
2913         GPRFlushedCallResult result(this);
2914         GPRReg resultGPR = result.gpr();
2915
2916         flushRegisters();
2917         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2918         m_jit.exceptionCheck();
2919
2920         jsValueResult(resultGPR, node);
2921         break;
2922     }
2923
2924     case PutByValDirect:
2925     case PutByVal:
2926     case PutByValAlias: {
2927         Edge child1 = m_jit.graph().varArgChild(node, 0);
2928         Edge child2 = m_jit.graph().varArgChild(node, 1);
2929         Edge child3 = m_jit.graph().varArgChild(node, 2);
2930         Edge child4 = m_jit.graph().varArgChild(node, 3);
2931         
2932         ArrayMode arrayMode = node->arrayMode().modeForPut();
2933         bool alreadyHandled = false;
2934         
2935         switch (arrayMode.type()) {
2936         case Array::SelectUsingPredictions:
2937         case Array::ForceExit:
2938             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2939             break;
2940         case Array::Generic: {
2941             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2942             
2943             JSValueOperand arg1(this, child1);
2944             JSValueOperand arg2(this, child2);
2945             JSValueOperand arg3(this, child3);
2946             GPRReg arg1GPR = arg1.gpr();
2947             GPRReg arg2GPR = arg2.gpr();
2948             GPRReg arg3GPR = arg3.gpr();
2949             flushRegisters();
2950             if (node->op() == PutByValDirect)
2951                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2952             else
2953                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2954             m_jit.exceptionCheck();
2955             
2956             noResult(node);
2957             alreadyHandled = true;
2958             break;
2959         }
2960         default:
2961             break;
2962         }
2963         
2964         if (alreadyHandled)
2965             break;
2966         
2967         // FIXME: the base may not be necessary for some array access modes. But we have to
2968         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2969         // no harm in locking it here.
2970         SpeculateCellOperand base(this, child1);
2971         SpeculateStrictInt32Operand property(this, child2);
2972         
2973         GPRReg baseReg = base.gpr();
2974         GPRReg propertyReg = property.gpr();
2975
2976         switch (arrayMode.type()) {
2977         case Array::Int32:
2978         case Array::Contiguous: {
2979             JSValueOperand value(this, child3, ManualOperandSpeculation);
2980
2981             GPRReg valueReg = value.gpr();
2982         
2983             if (!m_compileOkay)
2984                 return;
2985             
2986             if (arrayMode.type() == Array::Int32) {
2987                 DFG_TYPE_CHECK(
2988                     JSValueRegs(valueReg), child3, SpecInt32Only,
2989                     m_jit.branch64(
2990                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2991             }
2992
2993             StorageOperand storage(this, child4);
2994             GPRReg storageReg = storage.gpr();
2995
2996             if (node->op() == PutByValAlias) {
2997                 // Store the value to the array.
2998                 GPRReg propertyReg = property.gpr();
2999                 GPRReg valueReg = value.gpr();
3000                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3001                 
3002                 noResult(node);
3003                 break;
3004             }
3005             
3006             GPRTemporary temporary;
3007             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3008
3009             MacroAssembler::Jump slowCase;
3010             
3011             if (arrayMode.isInBounds()) {
3012                 speculationCheck(
3013                     OutOfBounds, JSValueRegs(), 0,
3014                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3015             } else {
3016                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3017                 
3018                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3019                 
3020                 if (!arrayMode.isOutOfBounds())
3021                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3022                 
3023                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3024                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3025                 
3026                 inBounds.link(&m_jit);
3027             }
3028             
3029             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3030
3031             base.use();
3032             property.use();
3033             value.use();
3034             storage.use();
3035             
3036             if (arrayMode.isOutOfBounds()) {
3037                 if (node->op() == PutByValDirect) {
3038                     addSlowPathGenerator(slowPathCall(
3039                         slowCase, this,
3040                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3041                         NoResult, baseReg, propertyReg, valueReg));
3042                 } else {
3043                     addSlowPathGenerator(slowPathCall(
3044                         slowCase, this,
3045                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3046                         NoResult, baseReg, propertyReg, valueReg));
3047                 }
3048             }
3049
3050             noResult(node, UseChildrenCalledExplicitly);
3051             break;
3052         }
3053             
3054         case Array::Double: {
3055             compileDoublePutByVal(node, base, property);
3056             break;
3057         }
3058             
3059         case Array::ArrayStorage:
3060         case Array::SlowPutArrayStorage: {
3061             JSValueOperand value(this, child3);
3062
3063             GPRReg valueReg = value.gpr();
3064         
3065             if (!m_compileOkay)
3066                 return;
3067
3068             StorageOperand storage(this, child4);
3069             GPRReg storageReg = storage.gpr();
3070
3071             if (node->op() == PutByValAlias) {
3072                 // Store the value to the array.
3073                 GPRReg propertyReg = property.gpr();
3074                 GPRReg valueReg = value.gpr();
3075                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3076                 
3077                 noResult(node);
3078                 break;
3079             }
3080             
3081             GPRTemporary temporary;
3082             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3083
3084             MacroAssembler::JumpList slowCases;
3085
3086             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3087             if (!arrayMode.isOutOfBounds())
3088                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3089             else
3090                 slowCases.append(beyondArrayBounds);
3091
3092             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3093             if (arrayMode.isInBounds()) {
3094                 speculationCheck(
3095                     StoreToHole, JSValueRegs(), 0,
3096                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
3097             } else {
3098                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3099                 if (arrayMode.isSlowPut()) {
3100                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3101                     // the above branch. But it's simply not worth it since this only happens if we're
3102                     // already having a bad time.
3103                     slowCases.append(m_jit.jump());
3104                 } else {
3105                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3106                 
3107                     // If we're writing to a hole we might be growing the array; 
3108                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3109                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3110                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3111                 
3112                     lengthDoesNotNeedUpdate.link(&m_jit);
3113                 }
3114                 notHoleValue.link(&m_jit);
3115             }
3116     
3117             // Store the value to the array.
3118             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3119
3120             base.use();
3121             property.use();
3122             value.use();
3123             storage.use();
3124             
3125             if (!slowCases.empty()) {
3126                 if (node->op() == PutByValDirect) {
3127                     addSlowPathGenerator(slowPathCall(
3128                         slowCases, this,
3129                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
3130                         NoResult, baseReg, propertyReg, valueReg));
3131                 } else {
3132                     addSlowPathGenerator(slowPathCall(
3133                         slowCases, this,
3134                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3135                         NoResult, baseReg, propertyReg, valueReg));
3136                 }
3137             }
3138
3139             noResult(node, UseChildrenCalledExplicitly);
3140             break;
3141         }
3142             
3143         default: {
3144             TypedArrayType type = arrayMode.typedArrayType();
3145             if (isInt(type))
3146                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3147             else
3148                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3149         } }
3150
3151         break;
3152     }
3153
3154     case RegExpExec: {
3155         bool sample = false;
3156
3157         if (sample)
3158             m_jit.incrementSuperSamplerCount();
3159         
3160         SpeculateCellOperand globalObject(this, node->child1());
3161         GPRReg globalObjectGPR = globalObject.gpr();
3162         
3163         if (node->child2().useKind() == RegExpObjectUse) {
3164             if (node->child3().useKind() == StringUse) {
3165                 SpeculateCellOperand base(this, node->child2());
3166                 SpeculateCellOperand argument(this, node->child3());
3167                 GPRReg baseGPR = base.gpr();
3168                 GPRReg argumentGPR = argument.gpr();
3169                 speculateRegExpObject(node->child2(), baseGPR);
3170                 speculateString(node->child3(), argumentGPR);
3171                 
3172                 flushRegisters();
3173                 GPRFlushedCallResult result(this);
3174                 callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3175                 m_jit.exceptionCheck();
3176                 
3177                 jsValueResult(result.gpr(), node);
3178
3179                 if (sample)
3180                     m_jit.decrementSuperSamplerCount();
3181                 break;
3182             }
3183             
3184             SpeculateCellOperand base(this, node->child2());
3185             JSValueOperand argument(this, node->child3());
3186             GPRReg baseGPR = base.gpr();
3187             GPRReg argumentGPR = argument.gpr();
3188           &