[JSC] Object.create should have intrinsic
[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             m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
1892     
1893             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
1894             jump(notTaken);
1895         }
1896         
1897         noResult(node, UseChildrenCalledExplicitly);
1898         return;
1899     }
1900         
1901     default:
1902         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
1903     }
1904 }
1905
1906 void SpeculativeJIT::compile(Node* node)
1907 {
1908     NodeType op = node->op();
1909     
1910 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1911     m_jit.clearRegisterAllocationOffsets();
1912 #endif
1913
1914     switch (op) {
1915     case JSConstant:
1916     case DoubleConstant:
1917     case Int52Constant:
1918     case PhantomDirectArguments:
1919     case PhantomClonedArguments:
1920         initConstantInfo(node);
1921         break;
1922
1923     case LazyJSConstant:
1924         compileLazyJSConstant(node);
1925         break;
1926
1927     case Identity: {
1928         compileIdentity(node);
1929         break;
1930     }
1931
1932     case GetLocal: {
1933         AbstractValue& value = m_state.operand(node->local());
1934
1935         // If the CFA is tracking this variable and it found that the variable
1936         // cannot have been assigned, then don't attempt to proceed.
1937         if (value.isClear()) {
1938             m_compileOkay = false;
1939             break;
1940         }
1941         
1942         switch (node->variableAccessData()->flushFormat()) {
1943         case FlushedDouble: {
1944             FPRTemporary result(this);
1945             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
1946             VirtualRegister virtualRegister = node->virtualRegister();
1947             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
1948             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
1949             break;
1950         }
1951         
1952         case FlushedInt32: {
1953             GPRTemporary result(this);
1954             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1955             
1956             // Like int32Result, but don't useChildren - our children are phi nodes,
1957             // and don't represent values within this dataflow with virtual registers.
1958             VirtualRegister virtualRegister = node->virtualRegister();
1959             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
1960             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
1961             break;
1962         }
1963             
1964         case FlushedInt52: {
1965             GPRTemporary result(this);
1966             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
1967             
1968             VirtualRegister virtualRegister = node->virtualRegister();
1969             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1970             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
1971             break;
1972         }
1973             
1974         default:
1975             GPRTemporary result(this);
1976             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
1977             
1978             // Like jsValueResult, but don't useChildren - our children are phi nodes,
1979             // and don't represent values within this dataflow with virtual registers.
1980             VirtualRegister virtualRegister = node->virtualRegister();
1981             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1982             
1983             DataFormat format;
1984             if (isCellSpeculation(value.m_type))
1985                 format = DataFormatJSCell;
1986             else if (isBooleanSpeculation(value.m_type))
1987                 format = DataFormatJSBoolean;
1988             else
1989                 format = DataFormatJS;
1990             
1991             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
1992             break;
1993         }
1994         break;
1995     }
1996
1997     case MovHint: {
1998         compileMovHint(m_currentNode);
1999         noResult(node);
2000         break;
2001     }
2002         
2003     case ZombieHint: {
2004         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2005         noResult(node);
2006         break;
2007     }
2008         
2009     case ExitOK: {
2010         noResult(node);
2011         break;
2012     }
2013         
2014     case SetLocal: {
2015         switch (node->variableAccessData()->flushFormat()) {
2016         case FlushedDouble: {
2017             SpeculateDoubleOperand value(this, node->child1());
2018             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2019             noResult(node);
2020             // Indicate that it's no longer necessary to retrieve the value of
2021             // this bytecode variable from registers or other locations in the stack,
2022             // but that it is stored as a double.
2023             recordSetLocal(DataFormatDouble);
2024             break;
2025         }
2026             
2027         case FlushedInt32: {
2028             SpeculateInt32Operand value(this, node->child1());
2029             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2030             noResult(node);
2031             recordSetLocal(DataFormatInt32);
2032             break;
2033         }
2034             
2035         case FlushedInt52: {
2036             SpeculateInt52Operand value(this, node->child1());
2037             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2038             noResult(node);
2039             recordSetLocal(DataFormatInt52);
2040             break;
2041         }
2042             
2043         case FlushedCell: {
2044             SpeculateCellOperand cell(this, node->child1());
2045             GPRReg cellGPR = cell.gpr();
2046             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2047             noResult(node);
2048             recordSetLocal(DataFormatCell);
2049             break;
2050         }
2051             
2052         case FlushedBoolean: {
2053             SpeculateBooleanOperand boolean(this, node->child1());
2054             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2055             noResult(node);
2056             recordSetLocal(DataFormatBoolean);
2057             break;
2058         }
2059             
2060         case FlushedJSValue: {
2061             JSValueOperand value(this, node->child1());
2062             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2063             noResult(node);
2064             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2065             break;
2066         }
2067             
2068         default:
2069             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2070             break;
2071         }
2072
2073         break;
2074     }
2075
2076     case SetArgument:
2077         // This is a no-op; it just marks the fact that the argument is being used.
2078         // But it may be profitable to use this as a hook to run speculation checks
2079         // on arguments, thereby allowing us to trivially eliminate such checks if
2080         // the argument is not used.
2081         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2082         break;
2083
2084     case BitAnd:
2085     case BitOr:
2086     case BitXor:
2087         compileBitwiseOp(node);
2088         break;
2089
2090     case BitRShift:
2091     case BitLShift:
2092     case BitURShift:
2093         compileShiftOp(node);
2094         break;
2095
2096     case UInt32ToNumber: {
2097         compileUInt32ToNumber(node);
2098         break;
2099     }
2100
2101     case DoubleAsInt32: {
2102         compileDoubleAsInt32(node);
2103         break;
2104     }
2105
2106     case ValueToInt32: {
2107         compileValueToInt32(node);
2108         break;
2109     }
2110         
2111     case DoubleRep: {
2112         compileDoubleRep(node);
2113         break;
2114     }
2115         
2116     case ValueRep: {
2117         compileValueRep(node);
2118         break;
2119     }
2120         
2121     case Int52Rep: {
2122         switch (node->child1().useKind()) {
2123         case Int32Use: {
2124             SpeculateInt32Operand operand(this, node->child1());
2125             GPRTemporary result(this, Reuse, operand);
2126             
2127             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2128             
2129             strictInt52Result(result.gpr(), node);
2130             break;
2131         }
2132             
2133         case AnyIntUse: {
2134             GPRTemporary result(this);
2135             GPRReg resultGPR = result.gpr();
2136             
2137             convertAnyInt(node->child1(), resultGPR);
2138             
2139             strictInt52Result(resultGPR, node);
2140             break;
2141         }
2142             
2143         case DoubleRepAnyIntUse: {
2144             SpeculateDoubleOperand value(this, node->child1());
2145             FPRReg valueFPR = value.fpr();
2146             
2147             flushRegisters();
2148             GPRFlushedCallResult result(this);
2149             GPRReg resultGPR = result.gpr();
2150             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2151             
2152             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2153                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2154                 m_jit.branch64(
2155                     JITCompiler::Equal, resultGPR,
2156                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2157             
2158             strictInt52Result(resultGPR, node);
2159             break;
2160         }
2161             
2162         default:
2163             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2164         }
2165         break;
2166     }
2167
2168     case ValueNegate:
2169         compileValueNegate(node);
2170         break;
2171
2172     case ValueAdd:
2173         compileValueAdd(node);
2174         break;
2175
2176     case StrCat: {
2177         compileStrCat(node);
2178         break;
2179     }
2180
2181     case ArithAdd:
2182         compileArithAdd(node);
2183         break;
2184
2185     case ArithClz32:
2186         compileArithClz32(node);
2187         break;
2188         
2189     case MakeRope:
2190         compileMakeRope(node);
2191         break;
2192
2193     case ArithSub:
2194         compileArithSub(node);
2195         break;
2196
2197     case ArithNegate:
2198         compileArithNegate(node);
2199         break;
2200
2201     case ArithMul:
2202         compileArithMul(node);
2203         break;
2204
2205     case ArithDiv: {
2206         compileArithDiv(node);
2207         break;
2208     }
2209
2210     case ArithMod: {
2211         compileArithMod(node);
2212         break;
2213     }
2214
2215     case ArithAbs:
2216         compileArithAbs(node);
2217         break;
2218         
2219     case ArithMin:
2220     case ArithMax: {
2221         compileArithMinMax(node);
2222         break;
2223     }
2224
2225     case ArithPow:
2226         compileArithPow(node);
2227         break;
2228
2229     case ArithSqrt:
2230         compileArithSqrt(node);
2231         break;
2232
2233     case ArithFRound:
2234         compileArithFRound(node);
2235         break;
2236
2237     case ArithRandom:
2238         compileArithRandom(node);
2239         break;
2240
2241     case ArithRound:
2242     case ArithFloor:
2243     case ArithCeil:
2244     case ArithTrunc:
2245         compileArithRounding(node);
2246         break;
2247
2248     case ArithUnary:
2249         compileArithUnary(node);
2250         break;
2251
2252     case LogicalNot:
2253         compileLogicalNot(node);
2254         break;
2255
2256     case CompareLess:
2257         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2258             return;
2259         break;
2260
2261     case CompareLessEq:
2262         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2263             return;
2264         break;
2265
2266     case CompareGreater:
2267         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2268             return;
2269         break;
2270
2271     case CompareGreaterEq:
2272         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2273             return;
2274         break;
2275
2276     case CompareBelow:
2277         compileCompareUnsigned(node, JITCompiler::Below);
2278         break;
2279
2280     case CompareBelowEq:
2281         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2282         break;
2283
2284     case CompareEq:
2285         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2286             return;
2287         break;
2288
2289     case CompareStrictEq:
2290         if (compileStrictEq(node))
2291             return;
2292         break;
2293         
2294     case CompareEqPtr:
2295         compileCompareEqPtr(node);
2296         break;
2297
2298     case SameValue:
2299         compileSameValue(node);
2300         break;
2301
2302     case StringCharCodeAt: {
2303         compileGetCharCodeAt(node);
2304         break;
2305     }
2306
2307     case StringCharAt: {
2308         // Relies on StringCharAt node having same basic layout as GetByVal
2309         compileGetByValOnString(node);
2310         break;
2311     }
2312
2313     case StringFromCharCode: {
2314         compileFromCharCode(node);
2315         break;
2316     }
2317         
2318     case CheckArray: {
2319         checkArray(node);
2320         break;
2321     }
2322         
2323     case Arrayify:
2324     case ArrayifyToStructure: {
2325         arrayify(node);
2326         break;
2327     }
2328
2329     case GetByVal: {
2330         switch (node->arrayMode().type()) {
2331         case Array::SelectUsingPredictions:
2332         case Array::ForceExit:
2333             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2334             break;
2335         case Array::Undecided: {
2336             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2337             GPRTemporary result(this, Reuse, index);
2338             GPRReg indexGPR = index.gpr();
2339             GPRReg resultGPR = result.gpr();
2340
2341             speculationCheck(OutOfBounds, JSValueRegs(), node,
2342                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2343
2344             use(m_graph.varArgChild(node, 0));
2345             index.use();
2346
2347             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2348             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2349             break;
2350         }
2351         case Array::Generic: {
2352             if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2353                 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2354                     compileGetByValForObjectWithString(node);
2355                     break;
2356                 }
2357
2358                 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2359                     compileGetByValForObjectWithSymbol(node);
2360                     break;
2361                 }
2362             }
2363             JSValueOperand base(this, m_graph.varArgChild(node, 0));
2364             JSValueOperand property(this, m_graph.varArgChild(node, 1));
2365             GPRReg baseGPR = base.gpr();
2366             GPRReg propertyGPR = property.gpr();
2367             
2368             flushRegisters();
2369             GPRFlushedCallResult result(this);
2370             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2371             m_jit.exceptionCheck();
2372             
2373             jsValueResult(result.gpr(), node);
2374             break;
2375         }
2376         case Array::Int32:
2377         case Array::Contiguous: {
2378             if (node->arrayMode().isInBounds()) {
2379                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2380                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2381
2382                 GPRReg propertyReg = property.gpr();
2383                 GPRReg storageReg = storage.gpr();
2384
2385                 if (!m_compileOkay)
2386                     return;
2387                 
2388                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2389                 
2390                 GPRTemporary result(this);
2391
2392                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2393                 if (node->arrayMode().isSaneChain()) {
2394                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2395                     JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result.gpr());
2396                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2397                     notHole.link(&m_jit);
2398                 } else {
2399                     speculationCheck(
2400                         LoadFromHole, JSValueRegs(), 0,
2401                         m_jit.branchIfEmpty(result.gpr()));
2402                 }
2403                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2404                 break;
2405             }
2406             
2407             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2408             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2409             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2410             
2411             GPRReg baseReg = base.gpr();
2412             GPRReg propertyReg = property.gpr();
2413             GPRReg storageReg = storage.gpr();
2414             
2415             if (!m_compileOkay)
2416                 return;
2417             
2418             GPRTemporary result(this);
2419             GPRReg resultReg = result.gpr();
2420             
2421             MacroAssembler::JumpList slowCases;
2422             
2423             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2424
2425             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2426             slowCases.append(m_jit.branchIfEmpty(resultReg));
2427             
2428             addSlowPathGenerator(
2429                 slowPathCall(
2430                     slowCases, this, operationGetByValObjectInt,
2431                     result.gpr(), baseReg, propertyReg));
2432             
2433             jsValueResult(resultReg, node);
2434             break;
2435         }
2436
2437         case Array::Double: {
2438             if (node->arrayMode().isInBounds()) {
2439                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2440                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2441
2442                 GPRReg propertyReg = property.gpr();
2443                 GPRReg storageReg = storage.gpr();
2444
2445                 if (!m_compileOkay)
2446                     return;
2447
2448                 FPRTemporary result(this);
2449                 FPRReg resultReg = result.fpr();
2450
2451                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2452
2453                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2454                 if (!node->arrayMode().isSaneChain())
2455                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, resultReg, resultReg));
2456                 doubleResult(resultReg, node);
2457                 break;
2458             }
2459
2460             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2461             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2462             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2463             
2464             GPRReg baseReg = base.gpr();
2465             GPRReg propertyReg = property.gpr();
2466             GPRReg storageReg = storage.gpr();
2467             
2468             if (!m_compileOkay)
2469                 return;
2470             
2471             GPRTemporary result(this);
2472             FPRTemporary temp(this);
2473             GPRReg resultReg = result.gpr();
2474             FPRReg tempReg = temp.fpr();
2475             
2476             MacroAssembler::JumpList slowCases;
2477             
2478             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2479
2480             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2481             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2482             boxDouble(tempReg, resultReg);
2483             
2484             addSlowPathGenerator(
2485                 slowPathCall(
2486                     slowCases, this, operationGetByValObjectInt,
2487                     result.gpr(), baseReg, propertyReg));
2488             
2489             jsValueResult(resultReg, node);
2490             break;
2491         }
2492
2493         case Array::ArrayStorage:
2494         case Array::SlowPutArrayStorage: {
2495             if (node->arrayMode().isInBounds()) {
2496                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2497                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2498             
2499                 GPRReg propertyReg = property.gpr();
2500                 GPRReg storageReg = storage.gpr();
2501             
2502                 if (!m_compileOkay)
2503                     return;
2504             
2505                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2506             
2507                 GPRTemporary result(this);
2508                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2509                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(result.gpr()));
2510             
2511                 jsValueResult(result.gpr(), node);
2512                 break;
2513             }
2514
2515             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2516             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2517             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2518             
2519             GPRReg baseReg = base.gpr();
2520             GPRReg propertyReg = property.gpr();
2521             GPRReg storageReg = storage.gpr();
2522             
2523             if (!m_compileOkay)
2524                 return;
2525             
2526             GPRTemporary result(this);
2527             GPRReg resultReg = result.gpr();
2528             
2529             MacroAssembler::JumpList slowCases;
2530             
2531             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2532     
2533             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2534             slowCases.append(m_jit.branchIfEmpty(resultReg));
2535     
2536             addSlowPathGenerator(
2537                 slowPathCall(
2538                     slowCases, this, operationGetByValObjectInt,
2539                     result.gpr(), baseReg, propertyReg));
2540             
2541             jsValueResult(resultReg, node);
2542             break;
2543         }
2544         case Array::String:
2545             compileGetByValOnString(node);
2546             break;
2547         case Array::DirectArguments:
2548             compileGetByValOnDirectArguments(node);
2549             break;
2550         case Array::ScopedArguments:
2551             compileGetByValOnScopedArguments(node);
2552             break;
2553         default: {
2554             TypedArrayType type = node->arrayMode().typedArrayType();
2555             if (isInt(type))
2556                 compileGetByValOnIntTypedArray(node, type);
2557             else
2558                 compileGetByValOnFloatTypedArray(node, type);
2559         } }
2560         break;
2561     }
2562
2563     case GetByValWithThis: {
2564         compileGetByValWithThis(node);
2565         break;
2566     }
2567
2568     case PutByValDirect:
2569     case PutByVal:
2570     case PutByValAlias: {
2571         Edge child1 = m_jit.graph().varArgChild(node, 0);
2572         Edge child2 = m_jit.graph().varArgChild(node, 1);
2573         Edge child3 = m_jit.graph().varArgChild(node, 2);
2574         Edge child4 = m_jit.graph().varArgChild(node, 3);
2575         
2576         ArrayMode arrayMode = node->arrayMode().modeForPut();
2577         bool alreadyHandled = false;
2578         
2579         switch (arrayMode.type()) {
2580         case Array::SelectUsingPredictions:
2581         case Array::ForceExit:
2582             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2583             break;
2584         case Array::Generic: {
2585             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
2586
2587             if (child1.useKind() == CellUse) {
2588                 if (child2.useKind() == StringUse) {
2589                     compilePutByValForCellWithString(node, child1, child2, child3);
2590                     alreadyHandled = true;
2591                     break;
2592                 }
2593
2594                 if (child2.useKind() == SymbolUse) {
2595                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2596                     alreadyHandled = true;
2597                     break;
2598                 }
2599             }
2600             
2601             JSValueOperand arg1(this, child1);
2602             JSValueOperand arg2(this, child2);
2603             JSValueOperand arg3(this, child3);
2604             GPRReg arg1GPR = arg1.gpr();
2605             GPRReg arg2GPR = arg2.gpr();
2606             GPRReg arg3GPR = arg3.gpr();
2607             flushRegisters();
2608             if (node->op() == PutByValDirect)
2609                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2610             else
2611                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2612             m_jit.exceptionCheck();
2613             
2614             noResult(node);
2615             alreadyHandled = true;
2616             break;
2617         }
2618         default:
2619             break;
2620         }
2621         
2622         if (alreadyHandled)
2623             break;
2624
2625         SpeculateCellOperand base(this, child1);
2626         SpeculateStrictInt32Operand property(this, child2);
2627         
2628         GPRReg baseReg = base.gpr();
2629         GPRReg propertyReg = property.gpr();
2630
2631         switch (arrayMode.type()) {
2632         case Array::Int32:
2633         case Array::Contiguous: {
2634             JSValueOperand value(this, child3, ManualOperandSpeculation);
2635
2636             GPRReg valueReg = value.gpr();
2637         
2638             if (!m_compileOkay)
2639                 return;
2640             
2641             if (arrayMode.type() == Array::Int32) {
2642                 DFG_TYPE_CHECK(
2643                     JSValueRegs(valueReg), child3, SpecInt32Only,
2644                     m_jit.branchIfNotInt32(valueReg));
2645             }
2646
2647             StorageOperand storage(this, child4);
2648             GPRReg storageReg = storage.gpr();
2649
2650             if (node->op() == PutByValAlias) {
2651                 // Store the value to the array.
2652                 GPRReg propertyReg = property.gpr();
2653                 GPRReg valueReg = value.gpr();
2654                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2655                 
2656                 noResult(node);
2657                 break;
2658             }
2659             
2660             GPRTemporary temporary;
2661             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2662
2663             MacroAssembler::Jump slowCase;
2664             
2665             if (arrayMode.isInBounds()) {
2666                 speculationCheck(
2667                     OutOfBounds, JSValueRegs(), 0,
2668                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2669             } else {
2670                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2671                 
2672                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2673                 
2674                 if (!arrayMode.isOutOfBounds())
2675                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2676                 
2677                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2678                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2679
2680                 inBounds.link(&m_jit);
2681             }
2682
2683             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2684
2685             base.use();
2686             property.use();
2687             value.use();
2688             storage.use();
2689             
2690             if (arrayMode.isOutOfBounds()) {
2691                 addSlowPathGenerator(slowPathCall(
2692                     slowCase, this,
2693                     m_jit.codeBlock()->isStrictMode()
2694                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2695                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2696                     NoResult, baseReg, propertyReg, valueReg));
2697             }
2698
2699             noResult(node, UseChildrenCalledExplicitly);
2700             break;
2701         }
2702             
2703         case Array::Double: {
2704             compileDoublePutByVal(node, base, property);
2705             break;
2706         }
2707             
2708         case Array::ArrayStorage:
2709         case Array::SlowPutArrayStorage: {
2710             JSValueOperand value(this, child3);
2711
2712             GPRReg valueReg = value.gpr();
2713         
2714             if (!m_compileOkay)
2715                 return;
2716
2717             StorageOperand storage(this, child4);
2718             GPRReg storageReg = storage.gpr();
2719
2720             if (node->op() == PutByValAlias) {
2721                 // Store the value to the array.
2722                 GPRReg propertyReg = property.gpr();
2723                 GPRReg valueReg = value.gpr();
2724                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2725                 
2726                 noResult(node);
2727                 break;
2728             }
2729             
2730             GPRTemporary temporary;
2731             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2732
2733             MacroAssembler::JumpList slowCases;
2734
2735             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2736             if (!arrayMode.isOutOfBounds())
2737                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2738             else
2739                 slowCases.append(beyondArrayBounds);
2740
2741             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2742             if (arrayMode.isInBounds()) {
2743                 speculationCheck(
2744                     StoreToHole, JSValueRegs(), 0,
2745                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
2746             } else {
2747                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2748                 if (arrayMode.isSlowPut()) {
2749                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2750                     // the above branch. But it's simply not worth it since this only happens if we're
2751                     // already having a bad time.
2752                     slowCases.append(m_jit.jump());
2753                 } else {
2754                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2755                 
2756                     // If we're writing to a hole we might be growing the array; 
2757                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2758                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2759                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2760                 
2761                     lengthDoesNotNeedUpdate.link(&m_jit);
2762                 }
2763                 notHoleValue.link(&m_jit);
2764             }
2765     
2766             // Store the value to the array.
2767             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2768
2769             base.use();
2770             property.use();
2771             value.use();
2772             storage.use();
2773             
2774             if (!slowCases.empty()) {
2775                 addSlowPathGenerator(slowPathCall(
2776                     slowCases, this,
2777                     m_jit.codeBlock()->isStrictMode()
2778                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2779                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2780                     NoResult, baseReg, propertyReg, valueReg));
2781             }
2782
2783             noResult(node, UseChildrenCalledExplicitly);
2784             break;
2785         }
2786             
2787         default: {
2788             TypedArrayType type = arrayMode.typedArrayType();
2789             if (isInt(type))
2790                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2791             else
2792                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2793         } }
2794
2795         break;
2796     }
2797         
2798     case AtomicsAdd:
2799     case AtomicsAnd:
2800     case AtomicsCompareExchange:
2801     case AtomicsExchange:
2802     case AtomicsLoad:
2803     case AtomicsOr:
2804     case AtomicsStore:
2805     case AtomicsSub:
2806     case AtomicsXor: {
2807         unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
2808         Edge baseEdge = m_jit.graph().child(node, 0);
2809         Edge indexEdge = m_jit.graph().child(node, 1);
2810         Edge argEdges[maxNumExtraAtomicsArgs];
2811         for (unsigned i = numExtraArgs; i--;)
2812             argEdges[i] = m_jit.graph().child(node, 2 + i);
2813         Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
2814
2815         GPRReg baseGPR;
2816         GPRReg indexGPR;
2817         GPRReg argGPRs[2];
2818         GPRReg resultGPR;
2819
2820         auto callSlowPath = [&] () {
2821             switch (node->op()) {
2822             case AtomicsAdd:
2823                 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2824                 break;
2825             case AtomicsAnd:
2826                 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2827                 break;
2828             case AtomicsCompareExchange:
2829                 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
2830                 break;
2831             case AtomicsExchange:
2832                 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2833                 break;
2834             case AtomicsLoad:
2835                 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
2836                 break;
2837             case AtomicsOr:
2838                 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2839                 break;
2840             case AtomicsStore:
2841                 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2842                 break;
2843             case AtomicsSub:
2844                 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2845                 break;
2846             case AtomicsXor:
2847                 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2848                 break;
2849             default:
2850                 RELEASE_ASSERT_NOT_REACHED();
2851                 break;
2852             }
2853         };
2854         
2855         if (!storageEdge) {
2856             // We are in generic mode!
2857             JSValueOperand base(this, baseEdge);
2858             JSValueOperand index(this, indexEdge);
2859             std::optional<JSValueOperand> args[2];
2860             baseGPR = base.gpr();
2861             indexGPR = index.gpr();
2862             for (unsigned i = numExtraArgs; i--;) {
2863                 args[i].emplace(this, argEdges[i]);
2864                 argGPRs[i] = args[i]->gpr();
2865             }
2866             
2867             flushRegisters();
2868             GPRFlushedCallResult result(this);
2869             resultGPR = result.gpr();
2870             callSlowPath();
2871             m_jit.exceptionCheck();
2872             
2873             jsValueResult(resultGPR, node);
2874             break;
2875         }
2876         
2877         TypedArrayType type = node->arrayMode().typedArrayType();
2878         
2879         SpeculateCellOperand base(this, baseEdge);
2880         SpeculateStrictInt32Operand index(this, indexEdge);
2881
2882         baseGPR = base.gpr();
2883         indexGPR = index.gpr();
2884         
2885         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
2886         
2887         GPRTemporary args[2];
2888         
2889         JITCompiler::JumpList slowPathCases;
2890         
2891         bool ok = true;
2892         for (unsigned i = numExtraArgs; i--;) {
2893             if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
2894                 noResult(node);
2895                 ok = false;
2896             }
2897             argGPRs[i] = args[i].gpr();
2898         }
2899         if (!ok)
2900             break;
2901         
2902         StorageOperand storage(this, storageEdge);
2903         GPRTemporary oldValue(this);
2904         GPRTemporary result(this);
2905         GPRTemporary newValue(this);
2906         GPRReg storageGPR = storage.gpr();
2907         GPRReg oldValueGPR = oldValue.gpr();
2908         resultGPR = result.gpr();
2909         GPRReg newValueGPR = newValue.gpr();
2910         
2911         // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
2912         // https://bugs.webkit.org/show_bug.cgi?id=170974
2913         m_jit.nop();
2914         
2915         JITCompiler::Label loop = m_jit.label();
2916         
2917         loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
2918         m_jit.move(oldValueGPR, newValueGPR);
2919         m_jit.move(oldValueGPR, resultGPR);
2920         
2921         switch (node->op()) {
2922         case AtomicsAdd:
2923             m_jit.add32(argGPRs[0], newValueGPR);
2924             break;
2925         case AtomicsAnd:
2926             m_jit.and32(argGPRs[0], newValueGPR);
2927             break;
2928         case AtomicsCompareExchange: {
2929             switch (elementSize(type)) {
2930             case 1:
2931                 if (isSigned(type))
2932                     m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
2933                 else
2934                     m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
2935                 break;
2936             case 2:
2937                 if (isSigned(type))
2938                     m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
2939                 else
2940                     m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
2941                 break;
2942             case 4:
2943                 break;
2944             default:
2945                 RELEASE_ASSERT_NOT_REACHED();
2946                 break;
2947             }
2948             JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
2949             m_jit.move(argGPRs[1], newValueGPR);
2950             fail.link(&m_jit);
2951             break;
2952         }
2953         case AtomicsExchange:
2954             m_jit.move(argGPRs[0], newValueGPR);
2955             break;
2956         case AtomicsLoad:
2957             break;
2958         case AtomicsOr:
2959             m_jit.or32(argGPRs[0], newValueGPR);
2960             break;
2961         case AtomicsStore:
2962             m_jit.move(argGPRs[0], newValueGPR);
2963             m_jit.move(argGPRs[0], resultGPR);
2964             break;
2965         case AtomicsSub:
2966             m_jit.sub32(argGPRs[0], newValueGPR);
2967             break;
2968         case AtomicsXor:
2969             m_jit.xor32(argGPRs[0], newValueGPR);
2970             break;
2971         default:
2972             RELEASE_ASSERT_NOT_REACHED();
2973             break;
2974         }
2975         
2976         JITCompiler::JumpList success;
2977         switch (elementSize(type)) {
2978         case 1:
2979             success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
2980             break;
2981         case 2:
2982             success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
2983             break;
2984         case 4:
2985             success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
2986             break;
2987         default:
2988             RELEASE_ASSERT_NOT_REACHED();
2989             break;
2990         }
2991         m_jit.jump().linkTo(loop, &m_jit);
2992         
2993         if (!slowPathCases.empty()) {
2994             slowPathCases.link(&m_jit);
2995             silentSpillAllRegisters(resultGPR);
2996             // Since we spilled, we can do things to registers.
2997             m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
2998             m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
2999             for (unsigned i = numExtraArgs; i--;)
3000                 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3001             callSlowPath();
3002             silentFillAllRegisters();
3003             m_jit.exceptionCheck();
3004         }
3005         
3006         success.link(&m_jit);
3007         setIntTypedArrayLoadResult(node, resultGPR, type);
3008         break;
3009     }
3010         
3011     case AtomicsIsLockFree: {
3012         if (node->child1().useKind() != Int32Use) {
3013             JSValueOperand operand(this, node->child1());
3014             GPRReg operandGPR = operand.gpr();
3015             flushRegisters();
3016             GPRFlushedCallResult result(this);
3017             GPRReg resultGPR = result.gpr();
3018             callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3019             m_jit.exceptionCheck();
3020             jsValueResult(resultGPR, node);
3021             break;
3022         }
3023
3024         SpeculateInt32Operand operand(this, node->child1());
3025         GPRTemporary result(this);
3026         GPRReg operandGPR = operand.gpr();
3027         GPRReg resultGPR = result.gpr();
3028         m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3029         JITCompiler::JumpList done;
3030         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3031         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3032         done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3033         m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3034         done.link(&m_jit);
3035         jsValueResult(resultGPR, node);
3036         break;
3037     }
3038
3039     case RegExpExec: {
3040         compileRegExpExec(node);
3041         break;
3042     }
3043
3044     case RegExpExecNonGlobalOrSticky: {
3045         compileRegExpExecNonGlobalOrSticky(node);
3046         break;
3047     }
3048
3049     case RegExpMatchFastGlobal: {
3050         compileRegExpMatchFastGlobal(node);
3051         break;
3052     }
3053
3054     case RegExpTest: {
3055         compileRegExpTest(node);
3056         break;
3057     }
3058
3059     case RegExpMatchFast: {
3060         compileRegExpMatchFast(node);
3061         break;
3062     }
3063
3064     case StringReplace:
3065     case StringReplaceRegExp: {
3066         compileStringReplace(node);
3067         break;
3068     }
3069         
3070     case GetRegExpObjectLastIndex: {
3071         compileGetRegExpObjectLastIndex(node);
3072         break;
3073     }
3074         
3075     case SetRegExpObjectLastIndex: {
3076         compileSetRegExpObjectLastIndex(node);
3077         break;
3078     }
3079
3080     case RecordRegExpCachedResult: {
3081         compileRecordRegExpCachedResult(node);
3082         break;
3083     }
3084         
3085     case ArrayPush: {
3086         compileArrayPush(node);
3087         break;
3088     }
3089
3090     case ArraySlice: {
3091         compileArraySlice(node);
3092         break;
3093     }
3094
3095     case ArrayIndexOf: {
3096         compileArrayIndexOf(node);
3097         break;
3098     }
3099         
3100     case ArrayPop: {
3101         ASSERT(node->arrayMode().isJSArray());
3102
3103         SpeculateCellOperand base(this, node->child1());
3104         StorageOperand storage(this, node->child2());
3105         GPRTemporary value(this);
3106         GPRTemporary storageLength(this);
3107         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().
3108         
3109         GPRReg baseGPR = base.gpr();
3110         GPRReg storageGPR = storage.gpr();
3111         GPRReg valueGPR = value.gpr();
3112         GPRReg storageLengthGPR = storageLength.gpr();
3113         FPRReg tempFPR = temp.fpr();
3114         
3115         switch (node->arrayMode().type()) {
3116         case Array::Int32:
3117         case Array::Double:
3118         case Array::Contiguous: {
3119             m_jit.load32(
3120                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3121             MacroAssembler::Jump undefinedCase =
3122                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3123             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3124             m_jit.store32(
3125                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3126             MacroAssembler::Jump slowCase;
3127             if (node->arrayMode().type() == Array::Double) {
3128                 m_jit.loadDouble(
3129                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3130                     tempFPR);
3131                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3132                 // length and the new length.
3133                 m_jit.store64(
3134                     MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3135                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3136                 boxDouble(tempFPR, valueGPR);
3137             } else {
3138                 m_jit.load64(
3139                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3140                     valueGPR);
3141                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3142                 // length and the new length.
3143                 m_jit.store64(
3144                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3145                 slowCase = m_jit.branchIfEmpty(valueGPR);
3146             }
3147
3148             addSlowPathGenerator(
3149                 slowPathMove(
3150                     undefinedCase, this,
3151                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3152             addSlowPathGenerator(
3153                 slowPathCall(
3154                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3155             
3156             // We can't know for sure that the result is an int because of the slow paths. :-/
3157             jsValueResult(valueGPR, node);
3158             break;
3159         }
3160             
3161         case Array::ArrayStorage: {
3162             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3163         
3164             JITCompiler::Jump undefinedCase =
3165                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3166         
3167             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3168         
3169             JITCompiler::JumpList slowCases;
3170             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3171         
3172             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3173             slowCases.append(m_jit.branchIfEmpty(valueGPR));
3174         
3175             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3176         
3177             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight,  ArrayStorage::vectorOffset()));
3178             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3179         
3180             addSlowPathGenerator(
3181                 slowPathMove(
3182                     undefinedCase, this,
3183                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3184  &n