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