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