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