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