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