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