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