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