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