Source/JavaScriptCore:
[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), AccessType::Get);
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             if (edge->isNumberConstant()) {
1137                 FPRReg fpr = fprAllocate();
1138                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1139                 if (!doubleAsInt)
1140                     m_jit.moveZeroToDouble(fpr);
1141                 else {
1142                     GPRReg gpr = allocate();
1143                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1144                     m_jit.move64ToDouble(gpr, fpr);
1145                     unlock(gpr);
1146                 }
1147
1148                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1149                 info.fillDouble(*m_stream, fpr);
1150                 return fpr;
1151             }
1152             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1153             return fprAllocate();
1154         }
1155         
1156         DataFormat spillFormat = info.spillFormat();
1157         if (spillFormat != DataFormatDouble) {
1158             DFG_CRASH(
1159                 m_jit.graph(), m_currentNode, toCString(
1160                     "Expected ", edge, " to have double format but instead it is spilled as ",
1161                     dataFormatToString(spillFormat)).data());
1162         }
1163         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
1164         FPRReg fpr = fprAllocate();
1165         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1166         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1167         info.fillDouble(*m_stream, fpr);
1168         return fpr;
1169     }
1170
1171     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
1172     FPRReg fpr = info.fpr();
1173     m_fprs.lock(fpr);
1174     return fpr;
1175 }
1176
1177 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1178 {
1179     AbstractValue& value = m_state.forNode(edge);
1180     SpeculatedType type = value.m_type;
1181     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1182
1183     m_interpreter.filter(value, SpecCell);
1184     if (value.isClear()) {
1185         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1186         return allocate();
1187     }
1188
1189     VirtualRegister virtualRegister = edge->virtualRegister();
1190     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1191
1192     switch (info.registerFormat()) {
1193     case DataFormatNone: {
1194         GPRReg gpr = allocate();
1195
1196         if (edge->hasConstant()) {
1197             JSValue jsValue = edge->asJSValue();
1198             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1199             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1200             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1201             return gpr;
1202         }
1203
1204         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1205         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1206
1207         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1208         if (type & ~SpecCell)
1209             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1210         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1211         return gpr;
1212     }
1213
1214     case DataFormatCell:
1215     case DataFormatJSCell: {
1216         GPRReg gpr = info.gpr();
1217         m_gprs.lock(gpr);
1218         if (!ASSERT_DISABLED) {
1219             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1220             m_jit.abortWithReason(DFGIsNotCell);
1221             checkCell.link(&m_jit);
1222         }
1223         return gpr;
1224     }
1225
1226     case DataFormatJS: {
1227         GPRReg gpr = info.gpr();
1228         m_gprs.lock(gpr);
1229         if (type & ~SpecCell)
1230             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1231         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1232         return gpr;
1233     }
1234
1235     case DataFormatJSInt32:
1236     case DataFormatInt32:
1237     case DataFormatJSDouble:
1238     case DataFormatJSBoolean:
1239     case DataFormatBoolean:
1240     case DataFormatDouble:
1241     case DataFormatStorage:
1242     case DataFormatInt52:
1243     case DataFormatStrictInt52:
1244         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1245         
1246     default:
1247         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1248         return InvalidGPRReg;
1249     }
1250 }
1251
1252 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1253 {
1254     AbstractValue& value = m_state.forNode(edge);
1255     SpeculatedType type = value.m_type;
1256     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1257
1258     m_interpreter.filter(value, SpecBoolean);
1259     if (value.isClear()) {
1260         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1261         return allocate();
1262     }
1263
1264     VirtualRegister virtualRegister = edge->virtualRegister();
1265     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1266
1267     switch (info.registerFormat()) {
1268     case DataFormatNone: {
1269         GPRReg gpr = allocate();
1270
1271         if (edge->hasConstant()) {
1272             JSValue jsValue = edge->asJSValue();
1273             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1274             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1275             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1276             return gpr;
1277         }
1278         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
1279         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1280         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1281
1282         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1283         if (type & ~SpecBoolean) {
1284             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1285             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1286             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1287         }
1288         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1289         return gpr;
1290     }
1291
1292     case DataFormatBoolean:
1293     case DataFormatJSBoolean: {
1294         GPRReg gpr = info.gpr();
1295         m_gprs.lock(gpr);
1296         return gpr;
1297     }
1298
1299     case DataFormatJS: {
1300         GPRReg gpr = info.gpr();
1301         m_gprs.lock(gpr);
1302         if (type & ~SpecBoolean) {
1303             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1304             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1305             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1306         }
1307         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1308         return gpr;
1309     }
1310
1311     case DataFormatJSInt32:
1312     case DataFormatInt32:
1313     case DataFormatJSDouble:
1314     case DataFormatJSCell:
1315     case DataFormatCell:
1316     case DataFormatDouble:
1317     case DataFormatStorage:
1318     case DataFormatInt52:
1319     case DataFormatStrictInt52:
1320         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1321         
1322     default:
1323         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1324         return InvalidGPRReg;
1325     }
1326 }
1327
1328 void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge)
1329 {
1330     ASSERT(!isKnownNotCell(valueEdge.node()));
1331
1332     SpeculateCellOperand base(this, baseEdge);
1333     JSValueOperand value(this, valueEdge);
1334     GPRTemporary scratch1(this);
1335     GPRTemporary scratch2(this);
1336
1337     writeBarrier(base.gpr(), value.gpr(), valueEdge, scratch1.gpr(), scratch2.gpr());
1338 }
1339
1340 void SpeculativeJIT::compileObjectEquality(Node* node)
1341 {
1342     SpeculateCellOperand op1(this, node->child1());
1343     SpeculateCellOperand op2(this, node->child2());
1344     GPRTemporary result(this, Reuse, op1);
1345     
1346     GPRReg op1GPR = op1.gpr();
1347     GPRReg op2GPR = op2.gpr();
1348     GPRReg resultGPR = result.gpr();
1349    
1350     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1351         DFG_TYPE_CHECK(
1352             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1353         DFG_TYPE_CHECK(
1354             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1355     } else {
1356         DFG_TYPE_CHECK(
1357             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1358         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1359             m_jit.branchTest8(
1360                 MacroAssembler::NonZero, 
1361                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1362                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1363
1364         DFG_TYPE_CHECK(
1365             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1366         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1367             m_jit.branchTest8(
1368                 MacroAssembler::NonZero, 
1369                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1370                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1371     }
1372
1373     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1374     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1375     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1376 }
1377
1378 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1379 {
1380     SpeculateCellOperand op1(this, objectChild);
1381     JSValueOperand op2(this, otherChild);
1382     GPRTemporary result(this);
1383
1384     GPRReg op1GPR = op1.gpr();
1385     GPRReg op2GPR = op2.gpr();
1386     GPRReg resultGPR = result.gpr();
1387
1388     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1389
1390     // At this point we know that we can perform a straight-forward equality comparison on pointer
1391     // values because we are doing strict equality.
1392     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1393     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1394     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1395 }
1396     
1397 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1398 {
1399     BasicBlock* taken = branchNode->branchData()->taken.block;
1400     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1401     
1402     SpeculateCellOperand op1(this, objectChild);
1403     JSValueOperand op2(this, otherChild);
1404     
1405     GPRReg op1GPR = op1.gpr();
1406     GPRReg op2GPR = op2.gpr();
1407     
1408     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1409
1410     if (taken == nextBlock()) {
1411         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1412         jump(taken);
1413     } else {
1414         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1415         jump(notTaken);
1416     }
1417 }
1418
1419 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1420 {
1421     SpeculateCellOperand op1(this, leftChild);
1422     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1423     GPRTemporary result(this);
1424     
1425     GPRReg op1GPR = op1.gpr();
1426     GPRReg op2GPR = op2.gpr();
1427     GPRReg resultGPR = result.gpr();
1428
1429     bool masqueradesAsUndefinedWatchpointValid =
1430         masqueradesAsUndefinedWatchpointIsStillValid();
1431
1432     if (masqueradesAsUndefinedWatchpointValid) {
1433         DFG_TYPE_CHECK(
1434             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1435     } else {
1436         DFG_TYPE_CHECK(
1437             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1438         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1439             m_jit.branchTest8(
1440                 MacroAssembler::NonZero, 
1441                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1442                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1443     }
1444     
1445     // It seems that most of the time when programs do a == b where b may be either null/undefined
1446     // or an object, b is usually an object. Balance the branches to make that case fast.
1447     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1448     
1449     // We know that within this branch, rightChild must be a cell. 
1450     if (masqueradesAsUndefinedWatchpointValid) {
1451         DFG_TYPE_CHECK(
1452             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1453     } else {
1454         DFG_TYPE_CHECK(
1455             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1456         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1457             m_jit.branchTest8(
1458                 MacroAssembler::NonZero, 
1459                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1460                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1461     }
1462     
1463     // At this point we know that we can perform a straight-forward equality comparison on pointer
1464     // values because both left and right are pointers to objects that have no special equality
1465     // protocols.
1466     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1467     MacroAssembler::Jump done = m_jit.jump();
1468     
1469     rightNotCell.link(&m_jit);
1470     
1471     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1472     // prove that it is either null or undefined.
1473     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1474         m_jit.move(op2GPR, resultGPR);
1475         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1476         
1477         typeCheck(
1478             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther,
1479             m_jit.branch64(
1480                 MacroAssembler::NotEqual, resultGPR,
1481                 MacroAssembler::TrustedImm64(ValueNull)));
1482     }
1483     m_jit.move(TrustedImm32(0), result.gpr());
1484
1485     done.link(&m_jit);
1486     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1487     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1488 }
1489
1490 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1491 {
1492     BasicBlock* taken = branchNode->branchData()->taken.block;
1493     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1494     
1495     SpeculateCellOperand op1(this, leftChild);
1496     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1497     GPRTemporary result(this);
1498     
1499     GPRReg op1GPR = op1.gpr();
1500     GPRReg op2GPR = op2.gpr();
1501     GPRReg resultGPR = result.gpr();
1502     
1503     bool masqueradesAsUndefinedWatchpointValid = 
1504         masqueradesAsUndefinedWatchpointIsStillValid();
1505
1506     if (masqueradesAsUndefinedWatchpointValid) {
1507         DFG_TYPE_CHECK(
1508             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1509     } else {
1510         DFG_TYPE_CHECK(
1511             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1512         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1513             m_jit.branchTest8(
1514                 MacroAssembler::NonZero, 
1515                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1516                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1517     }
1518
1519     // It seems that most of the time when programs do a == b where b may be either null/undefined
1520     // or an object, b is usually an object. Balance the branches to make that case fast.
1521     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1522     
1523     // We know that within this branch, rightChild must be a cell. 
1524     if (masqueradesAsUndefinedWatchpointValid) {
1525         DFG_TYPE_CHECK(
1526             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1527     } else {
1528         DFG_TYPE_CHECK(
1529             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1530         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1531             m_jit.branchTest8(
1532                 MacroAssembler::NonZero, 
1533                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1534                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1535     }
1536     
1537     // At this point we know that we can perform a straight-forward equality comparison on pointer
1538     // values because both left and right are pointers to objects that have no special equality
1539     // protocols.
1540     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1541     
1542     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1543     // prove that it is either null or undefined.
1544     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1545         rightNotCell.link(&m_jit);
1546     else {
1547         jump(notTaken, ForceJump);
1548         
1549         rightNotCell.link(&m_jit);
1550         m_jit.move(op2GPR, resultGPR);
1551         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1552         
1553         typeCheck(
1554             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64(
1555                 MacroAssembler::NotEqual, resultGPR,
1556                 MacroAssembler::TrustedImm64(ValueNull)));
1557     }
1558     
1559     jump(notTaken);
1560 }
1561
1562 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1563 {
1564     if (node->child1()->isInt32Constant()) {
1565         SpeculateInt32Operand op2(this, node->child2());
1566         GPRTemporary result(this, Reuse, op2);
1567         int32_t imm = node->child1()->asInt32();
1568         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1569
1570         // If we add a DataFormatBool, we should use it here.
1571         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1572         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1573     } else if (node->child2()->isInt32Constant()) {
1574         SpeculateInt32Operand op1(this, node->child1());
1575         GPRTemporary result(this, Reuse, op1);
1576         int32_t imm = node->child2()->asInt32();
1577         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1578
1579         // If we add a DataFormatBool, we should use it here.
1580         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1581         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1582     } else {
1583         SpeculateInt32Operand op1(this, node->child1());
1584         SpeculateInt32Operand op2(this, node->child2());
1585         GPRTemporary result(this, Reuse, op1, op2);
1586         m_jit.compare32(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
1594 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1595 {
1596     SpeculateWhicheverInt52Operand op1(this, node->child1());
1597     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1598     GPRTemporary result(this, Reuse, op1, op2);
1599     
1600     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1601     
1602     // If we add a DataFormatBool, we should use it here.
1603     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1604     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1605 }
1606
1607 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1608 {
1609     BasicBlock* taken = branchNode->branchData()->taken.block;
1610     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1611
1612     // The branch instruction will branch to the taken block.
1613     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1614     if (taken == nextBlock()) {
1615         condition = JITCompiler::invert(condition);
1616         BasicBlock* tmp = taken;
1617         taken = notTaken;
1618         notTaken = tmp;
1619     }
1620     
1621     SpeculateWhicheverInt52Operand op1(this, node->child1());
1622     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1623     
1624     branch64(condition, op1.gpr(), op2.gpr(), taken);
1625     jump(notTaken);
1626 }
1627
1628 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1629 {
1630     SpeculateDoubleOperand op1(this, node->child1());
1631     SpeculateDoubleOperand op2(this, node->child2());
1632     GPRTemporary result(this);
1633     
1634     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1635     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1636     m_jit.xor64(TrustedImm32(true), result.gpr());
1637     trueCase.link(&m_jit);
1638     
1639     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1640 }
1641
1642 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1643 {
1644     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1645     GPRTemporary result(this);
1646     GPRReg valueGPR = value.gpr();
1647     GPRReg resultGPR = result.gpr();
1648     GPRTemporary structure;
1649     GPRReg structureGPR = InvalidGPRReg;
1650     GPRTemporary scratch;
1651     GPRReg scratchGPR = InvalidGPRReg;
1652
1653     bool masqueradesAsUndefinedWatchpointValid =
1654         masqueradesAsUndefinedWatchpointIsStillValid();
1655
1656     if (!masqueradesAsUndefinedWatchpointValid) {
1657         // The masquerades as undefined case will use the structure register, so allocate it here.
1658         // Do this at the top of the function to avoid branching around a register allocation.
1659         GPRTemporary realStructure(this);
1660         GPRTemporary realScratch(this);
1661         structure.adopt(realStructure);
1662         scratch.adopt(realScratch);
1663         structureGPR = structure.gpr();
1664         scratchGPR = scratch.gpr();
1665     }
1666
1667     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1668     if (masqueradesAsUndefinedWatchpointValid) {
1669         DFG_TYPE_CHECK(
1670             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1671     } else {
1672         DFG_TYPE_CHECK(
1673             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1674
1675         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1676             m_jit.branchTest8(
1677                 MacroAssembler::Zero, 
1678                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1679                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1680
1681         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1682         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1683             m_jit.branchPtr(
1684                 MacroAssembler::Equal, 
1685                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1686                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1687
1688         isNotMasqueradesAsUndefined.link(&m_jit);
1689     }
1690     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1691     MacroAssembler::Jump done = m_jit.jump();
1692     
1693     notCell.link(&m_jit);
1694
1695     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1696         m_jit.move(valueGPR, resultGPR);
1697         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1698         typeCheck(
1699             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1700                 MacroAssembler::NotEqual, 
1701                 resultGPR, 
1702                 MacroAssembler::TrustedImm64(ValueNull)));
1703     }
1704     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1705     
1706     done.link(&m_jit);
1707     
1708     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1709 }
1710
1711 void SpeculativeJIT::compileLogicalNot(Node* node)
1712 {
1713     switch (node->child1().useKind()) {
1714     case ObjectOrOtherUse: {
1715         compileObjectOrOtherLogicalNot(node->child1());
1716         return;
1717     }
1718         
1719     case Int32Use: {
1720         SpeculateInt32Operand value(this, node->child1());
1721         GPRTemporary result(this, Reuse, value);
1722         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1723         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1724         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1725         return;
1726     }
1727         
1728     case DoubleRepUse: {
1729         SpeculateDoubleOperand value(this, node->child1());
1730         FPRTemporary scratch(this);
1731         GPRTemporary result(this);
1732         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1733         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1734         m_jit.xor32(TrustedImm32(true), result.gpr());
1735         nonZero.link(&m_jit);
1736         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1737         return;
1738     }
1739     
1740     case BooleanUse:
1741     case KnownBooleanUse: {
1742         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1743             SpeculateBooleanOperand value(this, node->child1());
1744             GPRTemporary result(this, Reuse, value);
1745             
1746             m_jit.move(value.gpr(), result.gpr());
1747             m_jit.xor64(TrustedImm32(true), result.gpr());
1748             
1749             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1750             return;
1751         }
1752         
1753         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1754         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1755         
1756         m_jit.move(value.gpr(), result.gpr());
1757         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1758         typeCheck(
1759             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1760                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1761         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1762         
1763         // If we add a DataFormatBool, we should use it here.
1764         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1765         return;
1766     }
1767         
1768     case UntypedUse: {
1769         JSValueOperand arg1(this, node->child1());
1770         GPRTemporary result(this);
1771     
1772         GPRReg arg1GPR = arg1.gpr();
1773         GPRReg resultGPR = result.gpr();
1774     
1775         arg1.use();
1776     
1777         m_jit.move(arg1GPR, resultGPR);
1778         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1779         JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
1780     
1781         addSlowPathGenerator(
1782             slowPathCall(slowCase, this, operationConvertJSValueToBoolean, resultGPR, arg1GPR, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded));
1783     
1784         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1785         jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1786         return;
1787     }
1788     case StringUse:
1789         return compileStringZeroLength(node);
1790
1791     case StringOrOtherUse:
1792         return compileLogicalNotStringOrOther(node);
1793
1794     default:
1795         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1796         break;
1797     }
1798 }
1799
1800 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1801 {
1802     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1803     GPRTemporary scratch(this);
1804     GPRTemporary structure;
1805     GPRReg valueGPR = value.gpr();
1806     GPRReg scratchGPR = scratch.gpr();
1807     GPRReg structureGPR = InvalidGPRReg;
1808
1809     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
1810         GPRTemporary realStructure(this);
1811         structure.adopt(realStructure);
1812         structureGPR = structure.gpr();
1813     }
1814
1815     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1816     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1817         DFG_TYPE_CHECK(
1818             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1819     } else {
1820         DFG_TYPE_CHECK(
1821             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1822
1823         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1824             JITCompiler::Zero, 
1825             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1826             TrustedImm32(MasqueradesAsUndefined));
1827
1828         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1829         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1830             m_jit.branchPtr(
1831                 MacroAssembler::Equal, 
1832                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1833                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1834
1835         isNotMasqueradesAsUndefined.link(&m_jit);
1836     }
1837     jump(taken, ForceJump);
1838     
1839     notCell.link(&m_jit);
1840     
1841     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1842         m_jit.move(valueGPR, scratchGPR);
1843         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
1844         typeCheck(
1845             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1846                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
1847     }
1848     jump(notTaken);
1849     
1850     noResult(m_currentNode);
1851 }
1852
1853 void SpeculativeJIT::emitBranch(Node* node)
1854 {
1855     BasicBlock* taken = node->branchData()->taken.block;
1856     BasicBlock* notTaken = node->branchData()->notTaken.block;
1857     
1858     switch (node->child1().useKind()) {
1859     case ObjectOrOtherUse: {
1860         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1861         return;
1862     }
1863         
1864     case Int32Use:
1865     case DoubleRepUse: {
1866         if (node->child1().useKind() == Int32Use) {
1867             bool invert = false;
1868             
1869             if (taken == nextBlock()) {
1870                 invert = true;
1871                 BasicBlock* tmp = taken;
1872                 taken = notTaken;
1873                 notTaken = tmp;
1874             }
1875
1876             SpeculateInt32Operand value(this, node->child1());
1877             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1878         } else {
1879             SpeculateDoubleOperand value(this, node->child1());
1880             FPRTemporary scratch(this);
1881             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1882         }
1883         
1884         jump(notTaken);
1885         
1886         noResult(node);
1887         return;
1888     }
1889
1890     case StringUse: {
1891         emitStringBranch(node->child1(), taken, notTaken);
1892         return;
1893     }
1894
1895     case StringOrOtherUse: {
1896         emitStringOrOtherBranch(node->child1(), taken, notTaken);
1897         return;
1898     }
1899
1900     case UntypedUse:
1901     case BooleanUse:
1902     case KnownBooleanUse: {
1903         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1904         GPRReg valueGPR = value.gpr();
1905         
1906         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
1907             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1908                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1909                 
1910                 if (taken == nextBlock()) {
1911                     condition = MacroAssembler::Zero;
1912                     BasicBlock* tmp = taken;
1913                     taken = notTaken;
1914                     notTaken = tmp;
1915                 }
1916                 
1917                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
1918                 jump(notTaken);
1919             } else {
1920                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1921                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1922                 
1923                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
1924             }
1925             value.use();
1926         } else {
1927             GPRTemporary result(this);
1928             GPRReg resultGPR = result.gpr();
1929             
1930             if (node->child1()->prediction() & SpecInt32) {
1931                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
1932                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
1933             }
1934     
1935             if (node->child1()->prediction() & SpecBoolean) {
1936                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1937                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1938             }
1939     
1940             value.use();
1941     
1942             silentSpillAllRegisters(resultGPR);
1943             callOperation(operationConvertJSValueToBoolean, resultGPR, valueGPR);
1944             silentFillAllRegisters(resultGPR);
1945     
1946             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
1947             jump(notTaken);
1948         }
1949         
1950         noResult(node, UseChildrenCalledExplicitly);
1951         return;
1952     }
1953         
1954     default:
1955         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
1956     }
1957 }
1958
1959 void SpeculativeJIT::compile(Node* node)
1960 {
1961     NodeType op = node->op();
1962     
1963 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1964     m_jit.clearRegisterAllocationOffsets();
1965 #endif
1966
1967     switch (op) {
1968     case JSConstant:
1969     case DoubleConstant:
1970     case Int52Constant:
1971     case PhantomDirectArguments:
1972     case PhantomClonedArguments:
1973         initConstantInfo(node);
1974         break;
1975
1976     case LazyJSConstant:
1977         compileLazyJSConstant(node);
1978         break;
1979
1980     case Identity: {
1981         speculate(node, node->child1());
1982         switch (node->child1().useKind()) {
1983         case DoubleRepUse:
1984         case DoubleRepRealUse:
1985         case DoubleRepMachineIntUse: {
1986             SpeculateDoubleOperand op(this, node->child1());
1987             FPRTemporary scratch(this, op);
1988             m_jit.moveDouble(op.fpr(), scratch.fpr());
1989             doubleResult(scratch.fpr(), node);
1990             break;
1991         }
1992         case Int52RepUse: {
1993             SpeculateInt52Operand op(this, node->child1());
1994             GPRTemporary result(this, Reuse, op);
1995             m_jit.move(op.gpr(), result.gpr());
1996             int52Result(result.gpr(), node);
1997             break;
1998         }
1999         default: {
2000             JSValueOperand op(this, node->child1());
2001             GPRTemporary result(this, Reuse, op);
2002             m_jit.move(op.gpr(), result.gpr());
2003             jsValueResult(result.gpr(), node);
2004             break;
2005         }
2006         } // switch
2007         break;
2008     }
2009
2010     case GetLocal: {
2011         AbstractValue& value = m_state.variables().operand(node->local());
2012
2013         // If the CFA is tracking this variable and it found that the variable
2014         // cannot have been assigned, then don't attempt to proceed.
2015         if (value.isClear()) {
2016             m_compileOkay = false;
2017             break;
2018         }
2019         
2020         switch (node->variableAccessData()->flushFormat()) {
2021         case FlushedDouble: {
2022             FPRTemporary result(this);
2023             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2024             VirtualRegister virtualRegister = node->virtualRegister();
2025             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2026             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2027             break;
2028         }
2029         
2030         case FlushedInt32: {
2031             GPRTemporary result(this);
2032             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2033             
2034             // Like int32Result, but don't useChildren - our children are phi nodes,
2035             // and don't represent values within this dataflow with virtual registers.
2036             VirtualRegister virtualRegister = node->virtualRegister();
2037             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2038             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2039             break;
2040         }
2041             
2042         case FlushedInt52: {
2043             GPRTemporary result(this);
2044             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2045             
2046             VirtualRegister virtualRegister = node->virtualRegister();
2047             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2048             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2049             break;
2050         }
2051             
2052         default:
2053             GPRTemporary result(this);
2054             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2055             
2056             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2057             // and don't represent values within this dataflow with virtual registers.
2058             VirtualRegister virtualRegister = node->virtualRegister();
2059             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2060             
2061             DataFormat format;
2062             if (isCellSpeculation(value.m_type))
2063                 format = DataFormatJSCell;
2064             else if (isBooleanSpeculation(value.m_type))
2065                 format = DataFormatJSBoolean;
2066             else
2067                 format = DataFormatJS;
2068             
2069             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2070             break;
2071         }
2072         break;
2073     }
2074
2075     case GetLocalUnlinked: {
2076         GPRTemporary result(this);
2077         
2078         m_jit.load64(JITCompiler::addressFor(node->unlinkedMachineLocal()), result.gpr());
2079         
2080         jsValueResult(result.gpr(), node);
2081         break;
2082     }
2083         
2084     case MovHint: {
2085         compileMovHint(m_currentNode);
2086         noResult(node);
2087         break;
2088     }
2089         
2090     case ZombieHint: {
2091         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2092         noResult(node);
2093         break;
2094     }
2095         
2096     case ExitOK: {
2097         noResult(node);
2098         break;
2099     }
2100         
2101     case SetLocal: {
2102         switch (node->variableAccessData()->flushFormat()) {
2103         case FlushedDouble: {
2104             SpeculateDoubleOperand value(this, node->child1());
2105             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2106             noResult(node);
2107             // Indicate that it's no longer necessary to retrieve the value of
2108             // this bytecode variable from registers or other locations in the stack,
2109             // but that it is stored as a double.
2110             recordSetLocal(DataFormatDouble);
2111             break;
2112         }
2113             
2114         case FlushedInt32: {
2115             SpeculateInt32Operand value(this, node->child1());
2116             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2117             noResult(node);
2118             recordSetLocal(DataFormatInt32);
2119             break;
2120         }
2121             
2122         case FlushedInt52: {
2123             SpeculateInt52Operand value(this, node->child1());
2124             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2125             noResult(node);
2126             recordSetLocal(DataFormatInt52);
2127             break;
2128         }
2129             
2130         case FlushedCell: {
2131             SpeculateCellOperand cell(this, node->child1());
2132             GPRReg cellGPR = cell.gpr();
2133             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2134             noResult(node);
2135             recordSetLocal(DataFormatCell);
2136             break;
2137         }
2138             
2139         case FlushedBoolean: {
2140             SpeculateBooleanOperand boolean(this, node->child1());
2141             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2142             noResult(node);
2143             recordSetLocal(DataFormatBoolean);
2144             break;
2145         }
2146             
2147         case FlushedJSValue: {
2148             JSValueOperand value(this, node->child1());
2149             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2150             noResult(node);
2151             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2152             break;
2153         }
2154             
2155         default:
2156             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2157             break;
2158         }
2159
2160         break;
2161     }
2162
2163     case SetArgument:
2164         // This is a no-op; it just marks the fact that the argument is being used.
2165         // But it may be profitable to use this as a hook to run speculation checks
2166         // on arguments, thereby allowing us to trivially eliminate such checks if
2167         // the argument is not used.
2168         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2169         break;
2170
2171     case BitAnd:
2172     case BitOr:
2173     case BitXor:
2174         compileBitwiseOp(node);
2175         break;
2176
2177     case BitRShift:
2178     case BitLShift:
2179     case BitURShift:
2180         compileShiftOp(node);
2181         break;
2182
2183     case UInt32ToNumber: {
2184         compileUInt32ToNumber(node);
2185         break;
2186     }
2187
2188     case DoubleAsInt32: {
2189         compileDoubleAsInt32(node);
2190         break;
2191     }
2192
2193     case ValueToInt32: {
2194         compileValueToInt32(node);
2195         break;
2196     }
2197         
2198     case DoubleRep: {
2199         compileDoubleRep(node);
2200         break;
2201     }
2202         
2203     case ValueRep: {
2204         compileValueRep(node);
2205         break;
2206     }
2207         
2208     case Int52Rep: {
2209         switch (node->child1().useKind()) {
2210         case Int32Use: {
2211             SpeculateInt32Operand operand(this, node->child1());
2212             GPRTemporary result(this, Reuse, operand);
2213             
2214             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2215             
2216             strictInt52Result(result.gpr(), node);
2217             break;
2218         }
2219             
2220         case MachineIntUse: {
2221             GPRTemporary result(this);
2222             GPRReg resultGPR = result.gpr();
2223             
2224             convertMachineInt(node->child1(), resultGPR);
2225             
2226             strictInt52Result(resultGPR, node);
2227             break;
2228         }
2229             
2230         case DoubleRepMachineIntUse: {
2231             SpeculateDoubleOperand value(this, node->child1());
2232             FPRReg valueFPR = value.fpr();
2233             
2234             GPRFlushedCallResult result(this);
2235             GPRReg resultGPR = result.gpr();
2236             
2237             flushRegisters();
2238             
2239             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2240             
2241             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2242                 JSValueRegs(), node->child1(), SpecInt52AsDouble,
2243                 m_jit.branch64(
2244                     JITCompiler::Equal, resultGPR,
2245                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2246             
2247             strictInt52Result(resultGPR, node);
2248             break;
2249         }
2250             
2251         default:
2252             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2253         }
2254         break;
2255     }
2256
2257     case ValueAdd:
2258         compileValueAdd(node);
2259         break;
2260
2261     case StrCat: {
2262         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2263         JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
2264         JSValueOperand op3(this, node->child3(), ManualOperandSpeculation);
2265         
2266         GPRReg op1GPR = op1.gpr();
2267         GPRReg op2GPR = op2.gpr();
2268         GPRReg op3GPR;
2269         if (node->child3())
2270             op3GPR = op3.gpr();
2271         else
2272             op3GPR = InvalidGPRReg;
2273         
2274         flushRegisters();
2275
2276         GPRFlushedCallResult result(this);
2277         if (node->child3())
2278             callOperation(operationStrCat3, result.gpr(), op1GPR, op2GPR, op3GPR);
2279         else
2280             callOperation(operationStrCat2, result.gpr(), op1GPR, op2GPR);
2281         m_jit.exceptionCheck();
2282         
2283         cellResult(result.gpr(), node);
2284         break;
2285     }
2286
2287     case ArithAdd:
2288         compileArithAdd(node);
2289         break;
2290
2291     case ArithClz32:
2292         compileArithClz32(node);
2293         break;
2294         
2295     case MakeRope:
2296         compileMakeRope(node);
2297         break;
2298
2299     case ArithSub:
2300         compileArithSub(node);
2301         break;
2302
2303     case ArithNegate:
2304         compileArithNegate(node);
2305         break;
2306
2307     case ArithMul:
2308         compileArithMul(node);
2309         break;
2310
2311     case ArithDiv: {
2312         compileArithDiv(node);
2313         break;
2314     }
2315
2316     case ArithMod: {
2317         compileArithMod(node);
2318         break;
2319     }
2320
2321     case ArithAbs: {
2322         switch (node->child1().useKind()) {
2323         case Int32Use: {
2324             SpeculateStrictInt32Operand op1(this, node->child1());
2325             GPRTemporary result(this);
2326             GPRTemporary scratch(this);
2327             
2328             m_jit.move(op1.gpr(), result.gpr());
2329             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2330             m_jit.add32(scratch.gpr(), result.gpr());
2331             m_jit.xor32(scratch.gpr(), result.gpr());
2332             if (shouldCheckOverflow(node->arithMode()))
2333                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, result.gpr()));
2334             int32Result(result.gpr(), node);
2335             break;
2336         }
2337         
2338         case DoubleRepUse: {
2339             SpeculateDoubleOperand op1(this, node->child1());
2340             FPRTemporary result(this);
2341             
2342             m_jit.absDouble(op1.fpr(), result.fpr());
2343             doubleResult(result.fpr(), node);
2344             break;
2345         }
2346             
2347         default:
2348             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2349             break;
2350         }
2351         break;
2352     }
2353         
2354     case ArithMin:
2355     case ArithMax: {
2356         switch (node->binaryUseKind()) {
2357         case Int32Use: {
2358             SpeculateStrictInt32Operand op1(this, node->child1());
2359             SpeculateStrictInt32Operand op2(this, node->child2());
2360             GPRTemporary result(this, Reuse, op1);
2361             
2362             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2363             m_jit.move(op2.gpr(), result.gpr());
2364             if (op1.gpr() != result.gpr()) {
2365                 MacroAssembler::Jump done = m_jit.jump();
2366                 op1Less.link(&m_jit);
2367                 m_jit.move(op1.gpr(), result.gpr());
2368                 done.link(&m_jit);
2369             } else
2370                 op1Less.link(&m_jit);
2371             
2372             int32Result(result.gpr(), node);
2373             break;
2374         }
2375         
2376         case DoubleRepUse: {
2377             SpeculateDoubleOperand op1(this, node->child1());
2378             SpeculateDoubleOperand op2(this, node->child2());
2379             FPRTemporary result(this, op1);
2380             
2381             FPRReg op1FPR = op1.fpr();
2382             FPRReg op2FPR = op2.fpr();
2383             FPRReg resultFPR = result.fpr();
2384         
2385             MacroAssembler::JumpList done;
2386         
2387             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2388         
2389             // op2 is eather the lesser one or one of then is NaN
2390             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2391         
2392             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2393             // op1 + op2 and putting it into result.
2394             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2395             done.append(m_jit.jump());
2396         
2397             op2Less.link(&m_jit);
2398             m_jit.moveDouble(op2FPR, resultFPR);
2399         
2400             if (op1FPR != resultFPR) {
2401                 done.append(m_jit.jump());
2402             
2403                 op1Less.link(&m_jit);
2404                 m_jit.moveDouble(op1FPR, resultFPR);
2405             } else
2406                 op1Less.link(&m_jit);
2407         
2408             done.link(&m_jit);
2409         
2410             doubleResult(resultFPR, node);
2411             break;
2412         }
2413             
2414         default:
2415             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2416             break;
2417         }
2418         break;
2419     }
2420
2421     case ArithPow:
2422         compileArithPow(node);
2423         break;
2424
2425     case ArithSqrt:
2426         compileArithSqrt(node);
2427         break;
2428
2429     case ArithFRound: {
2430         SpeculateDoubleOperand op1(this, node->child1());
2431         FPRTemporary result(this, op1);
2432         
2433         m_jit.convertDoubleToFloat(op1.fpr(), result.fpr());
2434         m_jit.convertFloatToDouble(result.fpr(), result.fpr());
2435         
2436         doubleResult(result.fpr(), node);
2437         break;
2438     }
2439
2440     case ArithRandom:
2441         compileArithRandom(node);
2442         break;
2443
2444     case ArithRound:
2445     case ArithFloor:
2446     case ArithCeil:
2447     case ArithTrunc:
2448         compileArithRounding(node);
2449         break;
2450
2451     case ArithSin: {
2452         SpeculateDoubleOperand op1(this, node->child1());
2453         FPRReg op1FPR = op1.fpr();
2454
2455         flushRegisters();
2456         
2457         FPRResult result(this);
2458         callOperation(sin, result.fpr(), op1FPR);
2459         doubleResult(result.fpr(), node);
2460         break;
2461     }
2462
2463     case ArithCos: {
2464         SpeculateDoubleOperand op1(this, node->child1());
2465         FPRReg op1FPR = op1.fpr();
2466
2467         flushRegisters();
2468         
2469         FPRResult result(this);
2470         callOperation(cos, result.fpr(), op1FPR);
2471         doubleResult(result.fpr(), node);
2472         break;
2473     }
2474
2475     case ArithLog:
2476         compileArithLog(node);
2477         break;
2478
2479     case LogicalNot:
2480         compileLogicalNot(node);
2481         break;
2482
2483     case CompareLess:
2484         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2485             return;
2486         break;
2487
2488     case CompareLessEq:
2489         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2490             return;
2491         break;
2492
2493     case CompareGreater:
2494         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2495             return;
2496         break;
2497
2498     case CompareGreaterEq:
2499         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2500             return;
2501         break;
2502
2503     case CompareEq:
2504         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2505             return;
2506         break;
2507
2508     case CompareStrictEq:
2509         if (compileStrictEq(node))
2510             return;
2511         break;
2512
2513     case StringCharCodeAt: {
2514         compileGetCharCodeAt(node);
2515         break;
2516     }
2517
2518     case StringCharAt: {
2519         // Relies on StringCharAt node having same basic layout as GetByVal
2520         compileGetByValOnString(node);
2521         break;
2522     }
2523
2524     case StringFromCharCode: {
2525         compileFromCharCode(node);
2526         break;
2527     }
2528         
2529     case CheckArray: {
2530         checkArray(node);
2531         break;
2532     }
2533         
2534     case Arrayify:
2535     case ArrayifyToStructure: {
2536         arrayify(node);
2537         break;
2538     }
2539
2540     case GetByVal: {
2541         switch (node->arrayMode().type()) {
2542         case Array::SelectUsingPredictions:
2543         case Array::ForceExit:
2544             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2545             break;
2546         case Array::Undecided: {
2547             SpeculateStrictInt32Operand index(this, node->child2());
2548             GPRTemporary result(this, Reuse, index);
2549             GPRReg indexGPR = index.gpr();
2550             GPRReg resultGPR = result.gpr();
2551
2552             use(node->child1());
2553             index.use();
2554
2555             speculationCheck(OutOfBounds, JSValueRegs(), node,
2556                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2557
2558             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2559             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2560             break;
2561         }
2562         case Array::Generic: {
2563             JSValueOperand base(this, node->child1());
2564             JSValueOperand property(this, node->child2());
2565             GPRReg baseGPR = base.gpr();
2566             GPRReg propertyGPR = property.gpr();
2567             
2568             flushRegisters();
2569             GPRFlushedCallResult result(this);
2570             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2571             m_jit.exceptionCheck();
2572             
2573             jsValueResult(result.gpr(), node);
2574             break;
2575         }
2576         case Array::Int32:
2577         case Array::Contiguous: {
2578             if (node->arrayMode().isInBounds()) {
2579                 SpeculateStrictInt32Operand property(this, node->child2());
2580                 StorageOperand storage(this, node->child3());
2581                 
2582                 GPRReg propertyReg = property.gpr();
2583                 GPRReg storageReg = storage.gpr();
2584                 
2585                 if (!m_compileOkay)
2586                     return;
2587                 
2588                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2589                 
2590                 GPRTemporary result(this);
2591                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2592                 if (node->arrayMode().isSaneChain()) {
2593                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2594                     JITCompiler::Jump notHole = m_jit.branchTest64(
2595                         MacroAssembler::NonZero, result.gpr());
2596                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2597                     notHole.link(&m_jit);
2598                 } else {
2599                     speculationCheck(
2600                         LoadFromHole, JSValueRegs(), 0,
2601                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2602                 }
2603                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2604                 break;
2605             }
2606             
2607             SpeculateCellOperand base(this, node->child1());
2608             SpeculateStrictInt32Operand property(this, node->child2());
2609             StorageOperand storage(this, node->child3());
2610             
2611             GPRReg baseReg = base.gpr();
2612             GPRReg propertyReg = property.gpr();
2613             GPRReg storageReg = storage.gpr();
2614             
2615             if (!m_compileOkay)
2616                 return;
2617             
2618             GPRTemporary result(this);
2619             GPRReg resultReg = result.gpr();
2620             
2621             MacroAssembler::JumpList slowCases;
2622             
2623             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2624             
2625             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2626             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2627             
2628             addSlowPathGenerator(
2629                 slowPathCall(
2630                     slowCases, this, operationGetByValArrayInt,
2631                     result.gpr(), baseReg, propertyReg));
2632             
2633             jsValueResult(resultReg, node);
2634             break;
2635         }
2636
2637         case Array::Double: {
2638             if (node->arrayMode().isInBounds()) {
2639                 SpeculateStrictInt32Operand property(this, node->child2());
2640                 StorageOperand storage(this, node->child3());
2641             
2642                 GPRReg propertyReg = property.gpr();
2643                 GPRReg storageReg = storage.gpr();
2644             
2645                 if (!m_compileOkay)
2646                     return;
2647             
2648                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2649             
2650                 FPRTemporary result(this);
2651                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2652                 if (!node->arrayMode().isSaneChain())
2653                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2654                 doubleResult(result.fpr(), node);
2655                 break;
2656             }
2657
2658             SpeculateCellOperand base(this, node->child1());
2659             SpeculateStrictInt32Operand property(this, node->child2());
2660             StorageOperand storage(this, node->child3());
2661             
2662             GPRReg baseReg = base.gpr();
2663             GPRReg propertyReg = property.gpr();
2664             GPRReg storageReg = storage.gpr();
2665             
2666             if (!m_compileOkay)
2667                 return;
2668             
2669             GPRTemporary result(this);
2670             FPRTemporary temp(this);
2671             GPRReg resultReg = result.gpr();
2672             FPRReg tempReg = temp.fpr();
2673             
2674             MacroAssembler::JumpList slowCases;
2675             
2676             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2677             
2678             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2679             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2680             boxDouble(tempReg, resultReg);
2681             
2682             addSlowPathGenerator(
2683                 slowPathCall(
2684                     slowCases, this, operationGetByValArrayInt,
2685                     result.gpr(), baseReg, propertyReg));
2686             
2687             jsValueResult(resultReg, node);
2688             break;
2689         }
2690
2691         case Array::ArrayStorage:
2692         case Array::SlowPutArrayStorage: {
2693             if (node->arrayMode().isInBounds()) {
2694                 SpeculateStrictInt32Operand property(this, node->child2());
2695                 StorageOperand storage(this, node->child3());
2696             
2697                 GPRReg propertyReg = property.gpr();
2698                 GPRReg storageReg = storage.gpr();
2699             
2700                 if (!m_compileOkay)
2701                     return;
2702             
2703                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2704             
2705                 GPRTemporary result(this);
2706                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2707                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2708             
2709                 jsValueResult(result.gpr(), node);
2710                 break;
2711             }
2712
2713             SpeculateCellOperand base(this, node->child1());
2714             SpeculateStrictInt32Operand property(this, node->child2());
2715             StorageOperand storage(this, node->child3());
2716             
2717             GPRReg baseReg = base.gpr();
2718             GPRReg propertyReg = property.gpr();
2719             GPRReg storageReg = storage.gpr();
2720             
2721             if (!m_compileOkay)
2722                 return;
2723             
2724             GPRTemporary result(this);
2725             GPRReg resultReg = result.gpr();
2726             
2727             MacroAssembler::JumpList slowCases;
2728             
2729             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2730     
2731             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2732             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2733     
2734             addSlowPathGenerator(
2735                 slowPathCall(
2736                     slowCases, this, operationGetByValArrayInt,
2737                     result.gpr(), baseReg, propertyReg));
2738             
2739             jsValueResult(resultReg, node);
2740             break;
2741         }
2742         case Array::String:
2743             compileGetByValOnString(node);
2744             break;
2745         case Array::DirectArguments:
2746             compileGetByValOnDirectArguments(node);
2747             break;
2748         case Array::ScopedArguments:
2749             compileGetByValOnScopedArguments(node);
2750             break;
2751         default: {
2752             TypedArrayType type = node->arrayMode().typedArrayType();
2753             if (isInt(type))
2754                 compileGetByValOnIntTypedArray(node, type);
2755             else
2756                 compileGetByValOnFloatTypedArray(node, type);
2757         } }
2758         break;
2759     }
2760
2761     case PutByValDirect:
2762     case PutByVal:
2763     case PutByValAlias: {
2764         Edge child1 = m_jit.graph().varArgChild(node, 0);
2765         Edge child2 = m_jit.graph().varArgChild(node, 1);
2766         Edge child3 = m_jit.graph().varArgChild(node, 2);
2767         Edge child4 = m_jit.graph().varArgChild(node, 3);
2768         
2769         ArrayMode arrayMode = node->arrayMode().modeForPut();
2770         bool alreadyHandled = false;
2771         
2772         switch (arrayMode.type()) {
2773         case Array::SelectUsingPredictions:
2774         case Array::ForceExit:
2775             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2776             break;
2777         case Array::Generic: {
2778             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2779             
2780             JSValueOperand arg1(this, child1);
2781             JSValueOperand arg2(this, child2);
2782             JSValueOperand arg3(this, child3);
2783             GPRReg arg1GPR = arg1.gpr();
2784             GPRReg arg2GPR = arg2.gpr();
2785             GPRReg arg3GPR = arg3.gpr();
2786             flushRegisters();
2787             if (node->op() == PutByValDirect)
2788                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2789             else
2790                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2791             m_jit.exceptionCheck();
2792             
2793             noResult(node);
2794             alreadyHandled = true;
2795             break;
2796         }
2797         default:
2798             break;
2799         }
2800         
2801         if (alreadyHandled)
2802             break;
2803         
2804         // FIXME: the base may not be necessary for some array access modes. But we have to
2805         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2806         // no harm in locking it here.
2807         SpeculateCellOperand base(this, child1);
2808         SpeculateStrictInt32Operand property(this, child2);
2809         
2810         GPRReg baseReg = base.gpr();
2811         GPRReg propertyReg = property.gpr();
2812
2813         switch (arrayMode.type()) {
2814         case Array::Int32:
2815         case Array::Contiguous: {
2816             JSValueOperand value(this, child3, ManualOperandSpeculation);
2817
2818             GPRReg valueReg = value.gpr();
2819         
2820             if (!m_compileOkay)
2821                 return;
2822             
2823             if (arrayMode.type() == Array::Int32) {
2824                 DFG_TYPE_CHECK(
2825                     JSValueRegs(valueReg), child3, SpecInt32,
2826                     m_jit.branch64(
2827                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2828             }
2829
2830             StorageOperand storage(this, child4);
2831             GPRReg storageReg = storage.gpr();
2832
2833             if (node->op() == PutByValAlias) {
2834                 // Store the value to the array.
2835                 GPRReg propertyReg = property.gpr();
2836                 GPRReg valueReg = value.gpr();
2837                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2838                 
2839                 noResult(node);
2840                 break;
2841             }
2842             
2843             GPRTemporary temporary;
2844             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2845
2846             MacroAssembler::Jump slowCase;
2847             
2848             if (arrayMode.isInBounds()) {
2849                 speculationCheck(
2850                     OutOfBounds, JSValueRegs(), 0,
2851                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2852             } else {
2853                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2854                 
2855                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2856                 
2857                 if (!arrayMode.isOutOfBounds())
2858                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2859                 
2860                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2861                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2862                 
2863                 inBounds.link(&m_jit);
2864             }
2865             
2866             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2867
2868             base.use();
2869             property.use();
2870             value.use();
2871             storage.use();
2872             
2873             if (arrayMode.isOutOfBounds()) {
2874                 if (node->op() == PutByValDirect) {
2875                     addSlowPathGenerator(slowPathCall(
2876                         slowCase, this,
2877                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2878                         NoResult, baseReg, propertyReg, valueReg));
2879                 } else {
2880                     addSlowPathGenerator(slowPathCall(
2881                         slowCase, this,
2882                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2883                         NoResult, baseReg, propertyReg, valueReg));
2884                 }
2885             }
2886
2887             noResult(node, UseChildrenCalledExplicitly);
2888             break;
2889         }
2890             
2891         case Array::Double: {
2892             compileDoublePutByVal(node, base, property);
2893             break;
2894         }
2895             
2896         case Array::ArrayStorage:
2897         case Array::SlowPutArrayStorage: {
2898             JSValueOperand value(this, child3);
2899
2900             GPRReg valueReg = value.gpr();
2901         
2902             if (!m_compileOkay)
2903                 return;
2904
2905             StorageOperand storage(this, child4);
2906             GPRReg storageReg = storage.gpr();
2907
2908             if (node->op() == PutByValAlias) {
2909                 // Store the value to the array.
2910                 GPRReg propertyReg = property.gpr();
2911                 GPRReg valueReg = value.gpr();
2912                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2913                 
2914                 noResult(node);
2915                 break;
2916             }
2917             
2918             GPRTemporary temporary;
2919             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2920
2921             MacroAssembler::JumpList slowCases;
2922
2923             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2924             if (!arrayMode.isOutOfBounds())
2925                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2926             else
2927                 slowCases.append(beyondArrayBounds);
2928
2929             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2930             if (arrayMode.isInBounds()) {
2931                 speculationCheck(
2932                     StoreToHole, JSValueRegs(), 0,
2933                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
2934             } else {
2935                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2936                 if (arrayMode.isSlowPut()) {
2937                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2938                     // the above branch. But it's simply not worth it since this only happens if we're
2939                     // already having a bad time.
2940                     slowCases.append(m_jit.jump());
2941                 } else {
2942                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2943                 
2944                     // If we're writing to a hole we might be growing the array; 
2945                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2946                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2947                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2948                 
2949                     lengthDoesNotNeedUpdate.link(&m_jit);
2950                 }
2951                 notHoleValue.link(&m_jit);
2952             }
2953     
2954             // Store the value to the array.
2955             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2956
2957             base.use();
2958             property.use();
2959             value.use();
2960             storage.use();
2961             
2962             if (!slowCases.empty()) {
2963                 if (node->op() == PutByValDirect) {
2964                     addSlowPathGenerator(slowPathCall(
2965                         slowCases, this,
2966                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2967                         NoResult, baseReg, propertyReg, valueReg));
2968                 } else {
2969                     addSlowPathGenerator(slowPathCall(
2970                         slowCases, this,
2971                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2972                         NoResult, baseReg, propertyReg, valueReg));
2973                 }
2974             }
2975
2976             noResult(node, UseChildrenCalledExplicitly);
2977             break;
2978         }
2979             
2980         default: {
2981             TypedArrayType type = arrayMode.typedArrayType();
2982             if (isInt(type))
2983                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2984             else
2985                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2986         } }
2987
2988         break;
2989     }
2990
2991     case RegExpExec: {
2992         bool sample = false;
2993
2994         if (sample)
2995             m_jit.incrementSuperSamplerCount();
2996         
2997         SpeculateCellOperand globalObject(this, node->child1());
2998         GPRReg globalObjectGPR = globalObject.gpr();
2999         
3000         if (node->child2().useKind() == RegExpObjectUse) {
3001             if (node->child3().useKind() == StringUse) {
3002                 SpeculateCellOperand base(this, node->child2());
3003                 SpeculateCellOperand argument(this, node->child3());
3004                 GPRReg baseGPR = base.gpr();
3005                 GPRReg argumentGPR = argument.gpr();
3006                 speculateRegExpObject(node->child2(), baseGPR);
3007                 speculateString(node->child3(), argumentGPR);
3008                 
3009                 flushRegisters();
3010                 GPRFlushedCallResult result(this);
3011                 callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3012                 m_jit.exceptionCheck();
3013                 
3014                 jsValueResult(result.gpr(), node);
3015
3016                 if (sample)
3017                     m_jit.decrementSuperSamplerCount();
3018                 break;
3019             }
3020             
3021             SpeculateCellOperand base(this, node->child2());
3022             JSValueOperand argument(this, node->child3());
3023             GPRReg baseGPR = base.gpr();
3024             GPRReg argumentGPR = argument.gpr();
3025             speculateRegExpObject(node->child2(), baseGPR);
3026         
3027             flushRegisters();
3028             GPRFlushedCallResult result(this);
3029             callOperation(operationRegExpExec, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3030             m_jit.exceptionCheck();
3031         
3032             jsValueResult(result.gpr(), node);
3033
3034             if (sample)
3035                 m_jit.decrementSuperSamplerCount();
3036             break;
3037         }
3038         
3039         JSValueOperand base(this, node->child2());
3040         JSValueOperand argument(this, node->child3());
3041         GPRReg baseGPR = base.gpr();
3042         GPRReg argumentGPR = argument.gpr();
3043         
3044         flushRegisters();
3045         GPRFlushedCallResult result(this);
3046         callOperation(operationRegExpExecGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3047         m_jit.exceptionCheck();
3048         
3049         jsValueResult(result.gpr(), node);
3050
3051         if (sample)
3052             m_jit.decrementSuperSamplerCount();
3053         break;
3054     }
3055
3056     case RegExpTest: {
3057         SpeculateCellOperand globalObject(this, node->child1());
3058         GPRReg globalObjectGPR = globalObject.gpr();
3059         
3060         if (node->child2().useKind() == RegExpObjectUse) {
3061             if (node->child3().useKind() == StringUse) {
3062                 SpeculateCellOperand base(this, node->child2());
3063                 SpeculateCellOperand argument(this, node->child3());
3064                 GPRReg baseGPR = base.gpr();
3065                 GPRReg argumentGPR = argument.gpr();
3066                 speculateRegExpObject(node->child2(), baseGPR);
3067                 speculateString(node->child3(), argumentGPR);
3068                 
3069                 flushRegisters();
3070                 GPRFlushedCallResult result(this);
3071                 callOperation(operationRegExpTestString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3072                 m_jit.exceptionCheck();
3073                 
3074                 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3075                 jsValueResult(result.gpr(), node);
3076                 break;
3077             }
3078             
3079             SpeculateCellOperand base(this, node->child2());
3080             JSValueOperand argument(this, node->child3());
3081             GPRReg baseGPR = base.gpr();
3082             GPRReg argumentGPR = argument.gpr();
3083             speculateRegExpObject(node->child2(), baseGPR);
3084         
3085             flushRegisters();
3086             GPRFlushedCallResult result(this);
3087             callOperation(operationRegExpTest, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3088             m_jit.exceptionCheck();
3089         
3090             m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3091             jsValueResult(result.gpr(), node);
3092             break;
3093         }
3094         
3095         JSValueOperand base(this, node->child2());
3096         JSValueOperand argument(this, node->child3());
3097         GPRReg baseGPR = base.gpr();
3098         GPRReg argumentGPR = argument.gpr();
3099         
3100         flushRegisters();
3101         GPRFlushedCallResult result(this);
3102         callOperation(operationRegExpTestGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3103         m_jit.exceptionCheck();
3104         
3105         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3106         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3107         break;
3108     }
3109
3110     case StringReplace: {
3111         bool sample = false;
3112
3113         if (sample)
3114             m_jit.incrementSuperSamplerCount();
3115         
3116         if (node->child1().useKind() == StringUse
3117             && node->child2().useKind() == RegExpObjectUse
3118             && node->child3().useKind() == StringUse) {
3119             if (JSString* replace = node->child3()->dynamicCastConstant<JSString*>()) {
3120                 if (!replace->length()) {
3121                     SpeculateCellOperand string(this, node->child1());
3122                     SpeculateCellOperand regExp(this, node->child2());
3123                     GPRReg stringGPR = string.gpr();
3124                     GPRReg regExpGPR = regExp.gpr();
3125                     speculateString(node->child1(), stringGPR);
3126                     speculateRegExpObject(node->child2(), regExpGPR);
3127
3128                     flushRegisters();
3129                     GPRFlushedCallResult result(this);
3130                     callOperation(
3131                         operationStringProtoFuncReplaceRegExpEmptyStr, result.gpr(), stringGPR,
3132                         regExpGPR);
3133                     m_jit.exceptionCheck();
3134                     cellResult(result.gpr(), node);
3135                     if (sample)
3136                         m_jit.decrementSuperSamplerCount();
3137                     break;
3138                 }
3139             }
3140             
3141             SpeculateCellOperand string(this, node->child1());
3142             SpeculateCellOperand regExp(this, node->child2());
3143             SpeculateCellOperand replace(this, node->child3());
3144             GPRReg stringGPR = string.gpr();
3145             GPRReg regExpGPR = regExp.gpr();
3146             GPRReg replaceGPR = replace.gpr();
3147             speculateString(node->child1(), stringGPR);
3148             speculateRegExpObject(node->child2(), regExpGPR);
3149             speculateString(node->child3(), replaceGPR);
3150             
3151             flushRegisters();
3152             GPRFlushedCallResult result(this);
3153             callOperation(
3154                 operationStringProtoFuncReplaceRegExpString, result.gpr(), stringGPR, regExpGPR,
3155                 replaceGPR);
3156             m_jit.exceptionCheck();
3157             cellResult(result.gpr(), node);
3158             if (sample)
3159                 m_jit.decrementSuperSamplerCount();
3160             break;
3161         }
3162         
3163         JSValueOperand string(this, node->child1());
3164         JSValueOperand regExp(this, node->child2());
3165         JSValueOperand replace(this, node->child3());
3166         GPRReg stringGPR = string.gpr();
3167         GPRReg regExpGPR = regExp.gpr();
3168         GPRReg replaceGPR = replace.gpr();
3169         
3170         flushRegisters();
3171         GPRFlushedCallResult result(this);
3172         callOperation(
3173             operationStringProtoFuncReplaceGeneric, result.gpr(), stringGPR, regExpGPR,
3174             replaceGPR);
3175         m_jit.exceptionCheck();
3176         cellResult(result.gpr(), node);
3177         if (sample)
3178             m_jit.decrementSuperSamplerCount();
3179         break;
3180     }
3181         
3182     case GetRegExpObjectLastIndex: {
3183         compileGetRegExpObjectLastIndex(node);
3184         break;
3185     }
3186         
3187     case SetRegExpObjectLastIndex: {