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