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