1/*
2 * Copyright (C) 2011, 2012, 2013, 2014 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 "DFGAbstractInterpreterInlines.h"
34#include "DFGCallArrayAllocatorSlowPathGenerator.h"
35#include "DFGOperations.h"
36#include "DFGSlowPathGenerator.h"
37#include "Debugger.h"
38#include "JSActivation.h"
39#include "ObjectPrototype.h"
40#include "JSCInlines.h"
41
42namespace JSC { namespace DFG {
43
44#if USE(JSVALUE32_64)
45
46bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr)
47{
48    // FIXME: For double we could fill with a FPR.
49    UNUSED_PARAM(fpr);
50
51    VirtualRegister virtualRegister = edge->virtualRegister();
52    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
53
54    switch (info.registerFormat()) {
55    case DataFormatNone: {
56
57        if (edge->hasConstant()) {
58            tagGPR = allocate();
59            payloadGPR = allocate();
60            m_jit.move(Imm32(valueOfJSConstant(edge.node()).tag()), tagGPR);
61            m_jit.move(Imm32(valueOfJSConstant(edge.node()).payload()), payloadGPR);
62            m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant);
63            m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant);
64            info.fillJSValue(*m_stream, tagGPR, payloadGPR, isInt32Constant(edge.node()) ? DataFormatJSInt32 : DataFormatJS);
65        } else {
66            DataFormat spillFormat = info.spillFormat();
67            ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage);
68            tagGPR = allocate();
69            payloadGPR = allocate();
70            switch (spillFormat) {
71            case DataFormatInt32:
72                m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR);
73                spillFormat = DataFormatJSInt32; // This will be used as the new register format.
74                break;
75            case DataFormatCell:
76                m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR);
77                spillFormat = DataFormatJSCell; // This will be used as the new register format.
78                break;
79            case DataFormatBoolean:
80                m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR);
81                spillFormat = DataFormatJSBoolean; // This will be used as the new register format.
82                break;
83            default:
84                m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
85                break;
86            }
87            m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR);
88            m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
89            m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
90            info.fillJSValue(*m_stream, tagGPR, payloadGPR, spillFormat == DataFormatJSDouble ? DataFormatJS : spillFormat);
91        }
92
93        return true;
94    }
95
96    case DataFormatInt32:
97    case DataFormatCell:
98    case DataFormatBoolean: {
99        GPRReg gpr = info.gpr();
100        // If the register has already been locked we need to take a copy.
101        if (m_gprs.isLocked(gpr)) {
102            payloadGPR = allocate();
103            m_jit.move(gpr, payloadGPR);
104        } else {
105            payloadGPR = gpr;
106            m_gprs.lock(gpr);
107        }
108        tagGPR = allocate();
109        uint32_t tag = JSValue::EmptyValueTag;
110        DataFormat fillFormat = DataFormatJS;
111        switch (info.registerFormat()) {
112        case DataFormatInt32:
113            tag = JSValue::Int32Tag;
114            fillFormat = DataFormatJSInt32;
115            break;
116        case DataFormatCell:
117            tag = JSValue::CellTag;
118            fillFormat = DataFormatJSCell;
119            break;
120        case DataFormatBoolean:
121            tag = JSValue::BooleanTag;
122            fillFormat = DataFormatJSBoolean;
123            break;
124        default:
125            RELEASE_ASSERT_NOT_REACHED();
126            break;
127        }
128        m_jit.move(TrustedImm32(tag), tagGPR);
129        m_gprs.release(gpr);
130        m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
131        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
132        info.fillJSValue(*m_stream, tagGPR, payloadGPR, fillFormat);
133        return true;
134    }
135
136    case DataFormatJSDouble:
137    case DataFormatJS:
138    case DataFormatJSInt32:
139    case DataFormatJSCell:
140    case DataFormatJSBoolean: {
141        tagGPR = info.tagGPR();
142        payloadGPR = info.payloadGPR();
143        m_gprs.lock(tagGPR);
144        m_gprs.lock(payloadGPR);
145        return true;
146    }
147
148    case DataFormatStorage:
149    case DataFormatDouble:
150        // this type currently never occurs
151        RELEASE_ASSERT_NOT_REACHED();
152
153    default:
154        RELEASE_ASSERT_NOT_REACHED();
155        return true;
156    }
157}
158
159void SpeculativeJIT::cachedGetById(
160    CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
161    unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
162{
163    // This is a hacky fix for when the register allocator decides to alias the base payload with the result tag. This only happens
164    // in the case of GetByIdFlush, which has a relatively expensive register allocation story already so we probably don't need to
165    // trip over one move instruction.
166    if (basePayloadGPR == resultTagGPR) {
167        RELEASE_ASSERT(basePayloadGPR != resultPayloadGPR);
168
169        if (baseTagGPROrNone == resultPayloadGPR) {
170            m_jit.swap(basePayloadGPR, baseTagGPROrNone);
171            baseTagGPROrNone = resultTagGPR;
172        } else
173            m_jit.move(basePayloadGPR, resultPayloadGPR);
174        basePayloadGPR = resultPayloadGPR;
175    }
176
177    JITGetByIdGenerator gen(
178        m_jit.codeBlock(), codeOrigin, usedRegisters(),
179        JSValueRegs(baseTagGPROrNone, basePayloadGPR),
180        JSValueRegs(resultTagGPR, resultPayloadGPR), spillMode);
181
182    gen.generateFastPath(m_jit);
183
184    JITCompiler::JumpList slowCases;
185    if (slowPathTarget.isSet())
186        slowCases.append(slowPathTarget);
187    slowCases.append(gen.slowPathJump());
188
189    OwnPtr<SlowPathGenerator> slowPath;
190    if (baseTagGPROrNone == InvalidGPRReg) {
191        slowPath = slowPathCall(
192            slowCases, this, operationGetByIdOptimize,
193            JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
194            static_cast<int32_t>(JSValue::CellTag), basePayloadGPR,
195            identifierUID(identifierNumber));
196    } else {
197        slowPath = slowPathCall(
198            slowCases, this, operationGetByIdOptimize,
199            JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), baseTagGPROrNone,
200            basePayloadGPR, identifierUID(identifierNumber));
201    }
202
203    m_jit.addGetById(gen, slowPath.get());
204    addSlowPathGenerator(slowPath.release());
205}
206
207void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
208{
209    JITPutByIdGenerator gen(
210        m_jit.codeBlock(), codeOrigin, usedRegisters(),
211        JSValueRegs::payloadOnly(basePayloadGPR), JSValueRegs(valueTagGPR, valuePayloadGPR),
212        scratchGPR, spillMode, m_jit.ecmaModeFor(codeOrigin), putKind);
213
214    gen.generateFastPath(m_jit);
215
216    JITCompiler::JumpList slowCases;
217    if (slowPathTarget.isSet())
218        slowCases.append(slowPathTarget);
219    slowCases.append(gen.slowPathJump());
220
221    OwnPtr<SlowPathGenerator> slowPath = slowPathCall(
222        slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), valueTagGPR,
223        valuePayloadGPR, basePayloadGPR, identifierUID(identifierNumber));
224
225    m_jit.addPutById(gen, slowPath.get());
226    addSlowPathGenerator(slowPath.release());
227}
228
229void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert)
230{
231    JSValueOperand arg(this, operand);
232    GPRReg argTagGPR = arg.tagGPR();
233    GPRReg argPayloadGPR = arg.payloadGPR();
234
235    GPRTemporary resultPayload(this, Reuse, arg, PayloadWord);
236    GPRReg resultPayloadGPR = resultPayload.gpr();
237
238    JITCompiler::Jump notCell;
239    JITCompiler::Jump notMasqueradesAsUndefined;
240    if (masqueradesAsUndefinedWatchpointIsStillValid()) {
241        if (!isKnownCell(operand.node()))
242            notCell = branchNotCell(arg.jsValueRegs());
243
244        m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR);
245        notMasqueradesAsUndefined = m_jit.jump();
246    } else {
247        GPRTemporary localGlobalObject(this);
248        GPRTemporary remoteGlobalObject(this);
249
250        if (!isKnownCell(operand.node()))
251            notCell = branchNotCell(arg.jsValueRegs());
252
253        JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
254            JITCompiler::NonZero,
255            JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()),
256            JITCompiler::TrustedImm32(MasqueradesAsUndefined));
257
258        m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR);
259        notMasqueradesAsUndefined = m_jit.jump();
260
261        isMasqueradesAsUndefined.link(&m_jit);
262        GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
263        GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
264        m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
265        m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultPayloadGPR);
266        m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
267        m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR);
268    }
269
270    if (!isKnownCell(operand.node())) {
271        JITCompiler::Jump done = m_jit.jump();
272
273        notCell.link(&m_jit);
274        // null or undefined?
275        COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
276        m_jit.move(argTagGPR, resultPayloadGPR);
277        m_jit.or32(TrustedImm32(1), resultPayloadGPR);
278        m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultPayloadGPR, TrustedImm32(JSValue::NullTag), resultPayloadGPR);
279
280        done.link(&m_jit);
281    }
282
283    notMasqueradesAsUndefined.link(&m_jit);
284
285    booleanResult(resultPayloadGPR, m_currentNode);
286}
287
288void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, Node* branchNode, bool invert)
289{
290    BasicBlock* taken = branchNode->branchData()->taken.block;
291    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
292
293    if (taken == nextBlock()) {
294        invert = !invert;
295        BasicBlock* tmp = taken;
296        taken = notTaken;
297        notTaken = tmp;
298    }
299
300    JSValueOperand arg(this, operand);
301    GPRReg argTagGPR = arg.tagGPR();
302    GPRReg argPayloadGPR = arg.payloadGPR();
303
304    GPRTemporary result(this, Reuse, arg, TagWord);
305    GPRReg resultGPR = result.gpr();
306
307    JITCompiler::Jump notCell;
308
309    if (masqueradesAsUndefinedWatchpointIsStillValid()) {
310        if (!isKnownCell(operand.node()))
311            notCell = branchNotCell(arg.jsValueRegs());
312
313        jump(invert ? taken : notTaken, ForceJump);
314    } else {
315        GPRTemporary localGlobalObject(this);
316        GPRTemporary remoteGlobalObject(this);
317
318        if (!isKnownCell(operand.node()))
319            notCell = branchNotCell(arg.jsValueRegs());
320
321        branchTest8(JITCompiler::Zero,
322            JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()),
323            JITCompiler::TrustedImm32(MasqueradesAsUndefined),
324            invert ? taken : notTaken);
325
326        GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
327        GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
328        m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
329        m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultGPR);
330        m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
331        branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
332    }
333
334    if (!isKnownCell(operand.node())) {
335        jump(notTaken, ForceJump);
336
337        notCell.link(&m_jit);
338        // null or undefined?
339        COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
340        m_jit.move(argTagGPR, resultGPR);
341        m_jit.or32(TrustedImm32(1), resultGPR);
342        branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(JSValue::NullTag), taken);
343    }
344
345    jump(notTaken);
346}
347
348bool SpeculativeJIT::nonSpeculativeCompareNull(Node* node, Edge operand, bool invert)
349{
350    unsigned branchIndexInBlock = detectPeepHoleBranch();
351    if (branchIndexInBlock != UINT_MAX) {
352        Node* branchNode = m_block->at(branchIndexInBlock);
353
354        ASSERT(node->adjustedRefCount() == 1);
355
356        nonSpeculativePeepholeBranchNull(operand, branchNode, invert);
357
358        use(node->child1());
359        use(node->child2());
360        m_indexInBlock = branchIndexInBlock;
361        m_currentNode = branchNode;
362
363        return true;
364    }
365
366    nonSpeculativeNonPeepholeCompareNull(operand, invert);
367
368    return false;
369}
370
371void 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        GPRResult 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
407        branchTest32(callResultCondition, resultGPR, taken);
408    } else {
409        GPRTemporary result(this);
410        GPRReg resultGPR = result.gpr();
411
412        arg1.use();
413        arg2.use();
414
415        if (!isKnownInteger(node->child1().node()))
416            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
417        if (!isKnownInteger(node->child2().node()))
418            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
419
420        branch32(cond, arg1PayloadGPR, arg2PayloadGPR, taken);
421
422        if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
423            jump(notTaken, ForceJump);
424
425            slowPath.link(&m_jit);
426
427            silentSpillAllRegisters(resultGPR);
428            callOperation(helperFunction, resultGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
429            silentFillAllRegisters(resultGPR);
430
431            branchTest32(callResultCondition, resultGPR, taken);
432        }
433    }
434
435    jump(notTaken);
436
437    m_indexInBlock = m_block->size() - 1;
438    m_currentNode = branchNode;
439}
440
441template<typename JumpType>
442class CompareAndBoxBooleanSlowPathGenerator
443    : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> {
444public:
445    CompareAndBoxBooleanSlowPathGenerator(
446        JumpType from, SpeculativeJIT* jit,
447        S_JITOperation_EJJ function, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload,
448        GPRReg arg2Tag, GPRReg arg2Payload)
449        : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>(
450            from, jit, function, NeedToSpill, result)
451        , m_arg1Tag(arg1Tag)
452        , m_arg1Payload(arg1Payload)
453        , m_arg2Tag(arg2Tag)
454        , m_arg2Payload(arg2Payload)
455    {
456    }
457
458protected:
459    virtual void generateInternal(SpeculativeJIT* jit)
460    {
461        this->setUp(jit);
462        this->recordCall(
463            jit->callOperation(
464                this->m_function, this->m_result, m_arg1Tag, m_arg1Payload, m_arg2Tag,
465                m_arg2Payload));
466        jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
467        this->tearDown(jit);
468    }
469
470private:
471    GPRReg m_arg1Tag;
472    GPRReg m_arg1Payload;
473    GPRReg m_arg2Tag;
474    GPRReg m_arg2Payload;
475};
476
477void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
478{
479    JSValueOperand arg1(this, node->child1());
480    JSValueOperand arg2(this, node->child2());
481    GPRReg arg1TagGPR = arg1.tagGPR();
482    GPRReg arg1PayloadGPR = arg1.payloadGPR();
483    GPRReg arg2TagGPR = arg2.tagGPR();
484    GPRReg arg2PayloadGPR = arg2.payloadGPR();
485
486    JITCompiler::JumpList slowPath;
487
488    if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
489        GPRResult result(this);
490        GPRReg resultPayloadGPR = result.gpr();
491
492        arg1.use();
493        arg2.use();
494
495        flushRegisters();
496        callOperation(helperFunction, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
497
498        booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
499    } else {
500        GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
501        GPRReg resultPayloadGPR = resultPayload.gpr();
502
503        arg1.use();
504        arg2.use();
505
506        if (!isKnownInteger(node->child1().node()))
507            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
508        if (!isKnownInteger(node->child2().node()))
509            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
510
511        m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR);
512
513        if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
514            addSlowPathGenerator(adoptPtr(
515                new CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>(
516                    slowPath, this, helperFunction, resultPayloadGPR, arg1TagGPR,
517                    arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR)));
518        }
519
520        booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
521    }
522}
523
524void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
525{
526    BasicBlock* taken = branchNode->branchData()->taken.block;
527    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
528
529    // The branch instruction will branch to the taken block.
530    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
531    if (taken == nextBlock()) {
532        invert = !invert;
533        BasicBlock* tmp = taken;
534        taken = notTaken;
535        notTaken = tmp;
536    }
537
538    JSValueOperand arg1(this, node->child1());
539    JSValueOperand arg2(this, node->child2());
540    GPRReg arg1TagGPR = arg1.tagGPR();
541    GPRReg arg1PayloadGPR = arg1.payloadGPR();
542    GPRReg arg2TagGPR = arg2.tagGPR();
543    GPRReg arg2PayloadGPR = arg2.payloadGPR();
544
545    GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
546    GPRReg resultPayloadGPR = resultPayload.gpr();
547
548    arg1.use();
549    arg2.use();
550
551    if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
552        // see if we get lucky: if the arguments are cells and they reference the same
553        // cell, then they must be strictly equal.
554        branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR, invert ? notTaken : taken);
555
556        silentSpillAllRegisters(resultPayloadGPR);
557        callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
558        silentFillAllRegisters(resultPayloadGPR);
559
560        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
561    } else {
562        // FIXME: Add fast paths for twoCells, number etc.
563
564        silentSpillAllRegisters(resultPayloadGPR);
565        callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
566        silentFillAllRegisters(resultPayloadGPR);
567
568        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
569    }
570
571    jump(notTaken);
572}
573
574void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
575{
576    JSValueOperand arg1(this, node->child1());
577    JSValueOperand arg2(this, node->child2());
578    GPRReg arg1TagGPR = arg1.tagGPR();
579    GPRReg arg1PayloadGPR = arg1.payloadGPR();
580    GPRReg arg2TagGPR = arg2.tagGPR();
581    GPRReg arg2PayloadGPR = arg2.payloadGPR();
582
583    GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
584    GPRReg resultPayloadGPR = resultPayload.gpr();
585
586    arg1.use();
587    arg2.use();
588
589    if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
590        // see if we get lucky: if the arguments are cells and they reference the same
591        // cell, then they must be strictly equal.
592        // FIXME: this should flush registers instead of silent spill/fill.
593        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR);
594
595        m_jit.move(JITCompiler::TrustedImm32(!invert), resultPayloadGPR);
596        JITCompiler::Jump done = m_jit.jump();
597
598        notEqualCase.link(&m_jit);
599
600        silentSpillAllRegisters(resultPayloadGPR);
601        callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
602        silentFillAllRegisters(resultPayloadGPR);
603
604        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
605
606        done.link(&m_jit);
607    } else {
608        // FIXME: Add fast paths.
609
610        silentSpillAllRegisters(resultPayloadGPR);
611        callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
612        silentFillAllRegisters(resultPayloadGPR);
613
614        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
615    }
616
617    booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
618}
619
620void SpeculativeJIT::compileMiscStrictEq(Node* node)
621{
622    JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
623    JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
624    GPRTemporary result(this);
625
626    if (node->child1().useKind() == MiscUse)
627        speculateMisc(node->child1(), op1.jsValueRegs());
628    if (node->child2().useKind() == MiscUse)
629        speculateMisc(node->child2(), op2.jsValueRegs());
630
631    m_jit.move(TrustedImm32(0), result.gpr());
632    JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR());
633    m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr());
634    notEqual.link(&m_jit);
635    booleanResult(result.gpr(), node);
636}
637
638void SpeculativeJIT::emitCall(Node* node)
639{
640    if (node->op() != Call)
641        ASSERT(node->op() == Construct);
642
643    // For constructors, the this argument is not passed but we have to make space
644    // for it.
645    int dummyThisArgument = node->op() == Call ? 0 : 1;
646
647    CallLinkInfo::CallType callType = node->op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
648
649    Edge calleeEdge = m_jit.graph().m_varArgChildren[node->firstChild()];
650    JSValueOperand callee(this, calleeEdge);
651    GPRReg calleeTagGPR = callee.tagGPR();
652    GPRReg calleePayloadGPR = callee.payloadGPR();
653    use(calleeEdge);
654
655    // The call instruction's first child is either the function (normal call) or the
656    // receiver (method call). subsequent children are the arguments.
657    int numPassedArgs = node->numChildren() - 1;
658
659    int numArgs = numPassedArgs + dummyThisArgument;
660
661    m_jit.store32(MacroAssembler::TrustedImm32(numArgs), calleeFramePayloadSlot(JSStack::ArgumentCount));
662    m_jit.store32(calleePayloadGPR, calleeFramePayloadSlot(JSStack::Callee));
663    m_jit.store32(calleeTagGPR, calleeFrameTagSlot(JSStack::Callee));
664
665    for (int i = 0; i < numPassedArgs; i++) {
666        Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
667        JSValueOperand arg(this, argEdge);
668        GPRReg argTagGPR = arg.tagGPR();
669        GPRReg argPayloadGPR = arg.payloadGPR();
670        use(argEdge);
671
672        m_jit.store32(argTagGPR, calleeArgumentTagSlot(i + dummyThisArgument));
673        m_jit.store32(argPayloadGPR, calleeArgumentPayloadSlot(i + dummyThisArgument));
674    }
675
676    flushRegisters();
677
678    GPRResult resultPayload(this);
679    GPRResult2 resultTag(this);
680    GPRReg resultPayloadGPR = resultPayload.gpr();
681    GPRReg resultTagGPR = resultTag.gpr();
682
683    JITCompiler::DataLabelPtr targetToCheck;
684    JITCompiler::JumpList slowPath;
685
686    m_jit.emitStoreCodeOrigin(node->origin.semantic);
687
688    slowPath.append(branchNotCell(callee.jsValueRegs()));
689    slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
690    m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultPayloadGPR);
691    m_jit.storePtr(resultPayloadGPR, calleeFramePayloadSlot(JSStack::ScopeChain));
692    m_jit.storePtr(MacroAssembler::TrustedImm32(JSValue::CellTag), calleeFrameTagSlot(JSStack::ScopeChain));
693
694    JITCompiler::Call fastCall = m_jit.nearCall();
695
696    JITCompiler::Jump done = m_jit.jump();
697
698    slowPath.link(&m_jit);
699
700    // Callee payload needs to be in regT0, tag in regT1
701    if (calleeTagGPR == GPRInfo::regT0) {
702        if (calleePayloadGPR == GPRInfo::regT1)
703            m_jit.swap(GPRInfo::regT1, GPRInfo::regT0);
704        else {
705            m_jit.move(calleeTagGPR, GPRInfo::regT1);
706            m_jit.move(calleePayloadGPR, GPRInfo::regT0);
707        }
708    } else {
709        m_jit.move(calleePayloadGPR, GPRInfo::regT0);
710        m_jit.move(calleeTagGPR, GPRInfo::regT1);
711    }
712    CallLinkInfo* info = m_jit.codeBlock()->addCallLinkInfo();
713    m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::regT2);
714    JITCompiler::Call slowCall = m_jit.nearCall();
715
716    done.link(&m_jit);
717
718    m_jit.setupResults(resultPayloadGPR, resultTagGPR);
719
720    jsValueResult(resultTagGPR, resultPayloadGPR, node, DataFormatJS, UseChildrenCalledExplicitly);
721
722    info->callType = callType;
723    info->codeOrigin = node->origin.semantic;
724    info->calleeGPR = calleePayloadGPR;
725    m_jit.addJSCall(fastCall, slowCall, targetToCheck, info);
726}
727
728template<bool strict>
729GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
730{
731    AbstractValue& value = m_state.forNode(edge);
732    SpeculatedType type = value.m_type;
733    ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32));
734    m_interpreter.filter(value, SpecInt32);
735    VirtualRegister virtualRegister = edge->virtualRegister();
736    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
737
738    if (edge->hasConstant() && !isInt32Constant(edge.node())) {
739        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
740        returnFormat = DataFormatInt32;
741        return allocate();
742    }
743
744    switch (info.registerFormat()) {
745    case DataFormatNone: {
746        if (edge->hasConstant()) {
747            ASSERT(isInt32Constant(edge.node()));
748            GPRReg gpr = allocate();
749            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr);
750            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
751            info.fillInt32(*m_stream, gpr);
752            returnFormat = DataFormatInt32;
753            return gpr;
754        }
755
756        DataFormat spillFormat = info.spillFormat();
757        ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
758
759        // If we know this was spilled as an integer we can fill without checking.
760        if (type & ~SpecInt32)
761            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
762
763        GPRReg gpr = allocate();
764        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
765        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
766        info.fillInt32(*m_stream, gpr);
767        returnFormat = DataFormatInt32;
768        return gpr;
769    }
770
771    case DataFormatJSInt32:
772    case DataFormatJS: {
773        // Check the value is an integer.
774        GPRReg tagGPR = info.tagGPR();
775        GPRReg payloadGPR = info.payloadGPR();
776        m_gprs.lock(tagGPR);
777        m_gprs.lock(payloadGPR);
778        if (type & ~SpecInt32)
779            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)));
780        m_gprs.unlock(tagGPR);
781        m_gprs.release(tagGPR);
782        m_gprs.release(payloadGPR);
783        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger);
784        info.fillInt32(*m_stream, payloadGPR);
785        // If !strict we're done, return.
786        returnFormat = DataFormatInt32;
787        return payloadGPR;
788    }
789
790    case DataFormatInt32: {
791        GPRReg gpr = info.gpr();
792        m_gprs.lock(gpr);
793        returnFormat = DataFormatInt32;
794        return gpr;
795    }
796
797    case DataFormatCell:
798    case DataFormatBoolean:
799    case DataFormatJSDouble:
800    case DataFormatJSCell:
801    case DataFormatJSBoolean:
802        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
803        returnFormat = DataFormatInt32;
804        return allocate();
805
806    case DataFormatDouble:
807    case DataFormatStorage:
808    default:
809        RELEASE_ASSERT_NOT_REACHED();
810        return InvalidGPRReg;
811    }
812}
813
814GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
815{
816    return fillSpeculateInt32Internal<false>(edge, returnFormat);
817}
818
819GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
820{
821    DataFormat mustBeDataFormatInt32;
822    GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
823    ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
824    return result;
825}
826
827FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
828{
829    ASSERT(isDouble(edge.useKind()));
830    ASSERT(edge->hasDoubleResult());
831    VirtualRegister virtualRegister = edge->virtualRegister();
832    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
833
834    if (info.registerFormat() == DataFormatNone) {
835
836        if (edge->hasConstant()) {
837            RELEASE_ASSERT(isNumberConstant(edge.node()));
838            FPRReg fpr = fprAllocate();
839            m_jit.loadDouble(TrustedImmPtr(addressOfDoubleConstant(edge.node())), fpr);
840            m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
841            info.fillDouble(*m_stream, fpr);
842            return fpr;
843        }
844
845        RELEASE_ASSERT(info.spillFormat() == DataFormatDouble);
846        FPRReg fpr = fprAllocate();
847        m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
848        m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
849        info.fillDouble(*m_stream, fpr);
850        return fpr;
851    }
852
853    RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
854    FPRReg fpr = info.fpr();
855    m_fprs.lock(fpr);
856    return fpr;
857}
858
859GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
860{
861    AbstractValue& value = m_state.forNode(edge);
862    SpeculatedType type = value.m_type;
863    ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
864    m_interpreter.filter(value, SpecCell);
865    VirtualRegister virtualRegister = edge->virtualRegister();
866    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
867
868    switch (info.registerFormat()) {
869    case DataFormatNone: {
870        if (info.spillFormat() == DataFormatInt32) {
871            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
872            return allocate();
873        }
874
875        if (edge->hasConstant()) {
876            JSValue jsValue = valueOfJSConstant(edge.node());
877            GPRReg gpr = allocate();
878            if (jsValue.isCell()) {
879                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
880                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
881                info.fillCell(*m_stream, gpr);
882                return gpr;
883            }
884            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
885            return gpr;
886        }
887
888        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
889        if (type & ~SpecCell) {
890            speculationCheck(
891                BadType,
892                JSValueSource(JITCompiler::addressFor(virtualRegister)),
893                edge,
894                m_jit.branch32(
895                    MacroAssembler::NotEqual,
896                    JITCompiler::tagFor(virtualRegister),
897                    TrustedImm32(JSValue::CellTag)));
898        }
899        GPRReg gpr = allocate();
900        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
901        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
902        info.fillCell(*m_stream, gpr);
903        return gpr;
904    }
905
906    case DataFormatCell: {
907        GPRReg gpr = info.gpr();
908        m_gprs.lock(gpr);
909        return gpr;
910    }
911
912    case DataFormatJSCell:
913    case DataFormatJS: {
914        GPRReg tagGPR = info.tagGPR();
915        GPRReg payloadGPR = info.payloadGPR();
916        m_gprs.lock(tagGPR);
917        m_gprs.lock(payloadGPR);
918        if (type & ~SpecCell) {
919            speculationCheck(
920                BadType, JSValueRegs(tagGPR, payloadGPR), edge,
921                branchNotCell(info.jsValueRegs()));
922        }
923        m_gprs.unlock(tagGPR);
924        m_gprs.release(tagGPR);
925        m_gprs.release(payloadGPR);
926        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell);
927        info.fillCell(*m_stream, payloadGPR);
928        return payloadGPR;
929    }
930
931    case DataFormatJSInt32:
932    case DataFormatInt32:
933    case DataFormatJSDouble:
934    case DataFormatJSBoolean:
935    case DataFormatBoolean:
936        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
937        return allocate();
938
939    case DataFormatDouble:
940    case DataFormatStorage:
941        RELEASE_ASSERT_NOT_REACHED();
942
943    default:
944        RELEASE_ASSERT_NOT_REACHED();
945        return InvalidGPRReg;
946    }
947}
948
949GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
950{
951    AbstractValue& value = m_state.forNode(edge);
952    SpeculatedType type = value.m_type;
953    m_interpreter.filter(value, SpecBoolean);
954    VirtualRegister virtualRegister = edge->virtualRegister();
955    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
956
957    switch (info.registerFormat()) {
958    case DataFormatNone: {
959        if (info.spillFormat() == DataFormatInt32) {
960            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
961            return allocate();
962        }
963
964        if (edge->hasConstant()) {
965            JSValue jsValue = valueOfJSConstant(edge.node());
966            GPRReg gpr = allocate();
967            if (jsValue.isBoolean()) {
968                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
969                m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
970                info.fillBoolean(*m_stream, gpr);
971                return gpr;
972            }
973            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
974            return gpr;
975        }
976
977        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
978
979        if (type & ~SpecBoolean)
980            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
981
982        GPRReg gpr = allocate();
983        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
984        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
985        info.fillBoolean(*m_stream, gpr);
986        return gpr;
987    }
988
989    case DataFormatBoolean: {
990        GPRReg gpr = info.gpr();
991        m_gprs.lock(gpr);
992        return gpr;
993    }
994
995    case DataFormatJSBoolean:
996    case DataFormatJS: {
997        GPRReg tagGPR = info.tagGPR();
998        GPRReg payloadGPR = info.payloadGPR();
999        m_gprs.lock(tagGPR);
1000        m_gprs.lock(payloadGPR);
1001        if (type & ~SpecBoolean)
1002            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)));
1003
1004        m_gprs.unlock(tagGPR);
1005        m_gprs.release(tagGPR);
1006        m_gprs.release(payloadGPR);
1007        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean);
1008        info.fillBoolean(*m_stream, payloadGPR);
1009        return payloadGPR;
1010    }
1011
1012    case DataFormatJSInt32:
1013    case DataFormatInt32:
1014    case DataFormatJSDouble:
1015    case DataFormatJSCell:
1016    case DataFormatCell:
1017        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1018        return allocate();
1019
1020    case DataFormatDouble:
1021    case DataFormatStorage:
1022        RELEASE_ASSERT_NOT_REACHED();
1023
1024    default:
1025        RELEASE_ASSERT_NOT_REACHED();
1026        return InvalidGPRReg;
1027    }
1028}
1029
1030void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge)
1031{
1032#if ENABLE(GGC)
1033    ASSERT(!isKnownNotCell(valueEdge.node()));
1034
1035    SpeculateCellOperand base(this, baseEdge);
1036    JSValueOperand value(this, valueEdge);
1037    GPRTemporary scratch1(this);
1038    GPRTemporary scratch2(this);
1039
1040    writeBarrier(base.gpr(), value.tagGPR(), valueEdge, scratch1.gpr(), scratch2.gpr());
1041#else
1042    UNUSED_PARAM(baseEdge);
1043    UNUSED_PARAM(valueEdge);
1044#endif
1045}
1046
1047void SpeculativeJIT::compileObjectEquality(Node* node)
1048{
1049    SpeculateCellOperand op1(this, node->child1());
1050    SpeculateCellOperand op2(this, node->child2());
1051    GPRReg op1GPR = op1.gpr();
1052    GPRReg op2GPR = op2.gpr();
1053
1054    if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1055        DFG_TYPE_CHECK(
1056            JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1057                MacroAssembler::Equal,
1058                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1059                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1060        DFG_TYPE_CHECK(
1061            JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1062                MacroAssembler::Equal,
1063                MacroAssembler::Address(op2GPR, JSCell::structureIDOffset()),
1064                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1065    } else {
1066        DFG_TYPE_CHECK(
1067            JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1068                MacroAssembler::Equal,
1069                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1070                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1071        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1072            m_jit.branchTest8(
1073                MacroAssembler::NonZero,
1074                MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1075                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1076
1077        DFG_TYPE_CHECK(
1078            JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1079                MacroAssembler::Equal,
1080                MacroAssembler::Address(op2GPR, JSCell::structureIDOffset()),
1081                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1082        speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1083            m_jit.branchTest8(
1084                MacroAssembler::NonZero,
1085                MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()),
1086                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1087    }
1088
1089    GPRTemporary resultPayload(this, Reuse, op2);
1090    GPRReg resultPayloadGPR = resultPayload.gpr();
1091
1092    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
1093    m_jit.move(TrustedImm32(1), resultPayloadGPR);
1094    MacroAssembler::Jump done = m_jit.jump();
1095    falseCase.link(&m_jit);
1096    m_jit.move(TrustedImm32(0), resultPayloadGPR);
1097    done.link(&m_jit);
1098
1099    booleanResult(resultPayloadGPR, node);
1100}
1101
1102void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1103{
1104    SpeculateCellOperand op1(this, leftChild);
1105    JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1106    GPRTemporary result(this);
1107
1108    GPRReg op1GPR = op1.gpr();
1109    GPRReg op2TagGPR = op2.tagGPR();
1110    GPRReg op2PayloadGPR = op2.payloadGPR();
1111    GPRReg resultGPR = result.gpr();
1112
1113    bool masqueradesAsUndefinedWatchpointValid =
1114        masqueradesAsUndefinedWatchpointIsStillValid();
1115
1116    if (masqueradesAsUndefinedWatchpointValid) {
1117        DFG_TYPE_CHECK(
1118            JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1119                MacroAssembler::Equal,
1120                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1121                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1122    } else {
1123        DFG_TYPE_CHECK(
1124            JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1125                MacroAssembler::Equal,
1126                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1127                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1128        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1129            m_jit.branchTest8(
1130                MacroAssembler::NonZero,
1131                MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1132                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1133    }
1134
1135
1136    // It seems that most of the time when programs do a == b where b may be either null/undefined
1137    // or an object, b is usually an object. Balance the branches to make that case fast.
1138    MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs());
1139
1140    // We know that within this branch, rightChild must be a cell.
1141    if (masqueradesAsUndefinedWatchpointValid) {
1142        DFG_TYPE_CHECK(
1143            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1144            m_jit.branchPtr(
1145                MacroAssembler::Equal,
1146                MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()),
1147                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1148    } else {
1149        DFG_TYPE_CHECK(
1150            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1151            m_jit.branchPtr(
1152                MacroAssembler::Equal,
1153                MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()),
1154                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1155        speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1156            m_jit.branchTest8(
1157                MacroAssembler::NonZero,
1158                MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()),
1159                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1160    }
1161
1162    // At this point we know that we can perform a straight-forward equality comparison on pointer
1163    // values because both left and right are pointers to objects that have no special equality
1164    // protocols.
1165    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR);
1166    MacroAssembler::Jump trueCase = m_jit.jump();
1167
1168    rightNotCell.link(&m_jit);
1169
1170    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1171    // prove that it is either null or undefined.
1172    if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1173        m_jit.move(op2TagGPR, resultGPR);
1174        m_jit.or32(TrustedImm32(1), resultGPR);
1175
1176        typeCheck(
1177            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1178            m_jit.branch32(
1179                MacroAssembler::NotEqual, resultGPR,
1180                MacroAssembler::TrustedImm32(JSValue::NullTag)));
1181    }
1182
1183    falseCase.link(&m_jit);
1184    m_jit.move(TrustedImm32(0), resultGPR);
1185    MacroAssembler::Jump done = m_jit.jump();
1186    trueCase.link(&m_jit);
1187    m_jit.move(TrustedImm32(1), resultGPR);
1188    done.link(&m_jit);
1189
1190    booleanResult(resultGPR, m_currentNode);
1191}
1192
1193void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1194{
1195    BasicBlock* taken = branchNode->branchData()->taken.block;
1196    BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1197
1198    SpeculateCellOperand op1(this, leftChild);
1199    JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1200    GPRTemporary result(this);
1201
1202    GPRReg op1GPR = op1.gpr();
1203    GPRReg op2TagGPR = op2.tagGPR();
1204    GPRReg op2PayloadGPR = op2.payloadGPR();
1205    GPRReg resultGPR = result.gpr();
1206
1207    bool masqueradesAsUndefinedWatchpointValid =
1208        masqueradesAsUndefinedWatchpointIsStillValid();
1209
1210    if (masqueradesAsUndefinedWatchpointValid) {
1211        DFG_TYPE_CHECK(
1212            JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1213                MacroAssembler::Equal,
1214                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1215                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1216    } else {
1217        DFG_TYPE_CHECK(
1218            JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1219                MacroAssembler::Equal,
1220                MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()),
1221                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1222        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1223            m_jit.branchTest8(
1224                MacroAssembler::NonZero,
1225                MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1226                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1227    }
1228
1229    // It seems that most of the time when programs do a == b where b may be either null/undefined
1230    // or an object, b is usually an object. Balance the branches to make that case fast.
1231    MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs());
1232
1233    // We know that within this branch, rightChild must be a cell.
1234    if (masqueradesAsUndefinedWatchpointValid) {
1235        DFG_TYPE_CHECK(
1236            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1237            m_jit.branchPtr(
1238                MacroAssembler::Equal,
1239                MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()),
1240                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1241    } else {
1242        DFG_TYPE_CHECK(
1243            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1244            m_jit.branchPtr(
1245                MacroAssembler::Equal,
1246                MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()),
1247                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1248        speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1249            m_jit.branchTest8(
1250                MacroAssembler::NonZero,
1251                MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()),
1252                MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1253    }
1254
1255    // At this point we know that we can perform a straight-forward equality comparison on pointer
1256    // values because both left and right are pointers to objects that have no special equality
1257    // protocols.
1258    branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken);
1259
1260    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1261    // prove that it is either null or undefined.
1262    if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1263        rightNotCell.link(&m_jit);
1264    else {
1265        jump(notTaken, ForceJump);
1266
1267        rightNotCell.link(&m_jit);
1268        m_jit.move(op2TagGPR, resultGPR);
1269        m_jit.or32(TrustedImm32(1), resultGPR);
1270
1271        typeCheck(
1272            JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1273            m_jit.branch32(
1274                MacroAssembler::NotEqual, resultGPR,
1275                MacroAssembler::TrustedImm32(JSValue::NullTag)));
1276    }
1277
1278    jump(notTaken);
1279}
1280
1281void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1282{
1283    SpeculateInt32Operand op1(this, node->child1());
1284    SpeculateInt32Operand op2(this, node->child2());
1285    GPRTemporary resultPayload(this);
1286
1287    m_jit.compare32(condition, op1.gpr(), op2.gpr(), resultPayload.gpr());
1288
1289    // If we add a DataFormatBool, we should use it here.
1290    booleanResult(resultPayload.gpr(), node);
1291}
1292
1293void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1294{
1295    SpeculateDoubleOperand op1(this, node->child1());
1296    SpeculateDoubleOperand op2(this, node->child2());
1297    GPRTemporary resultPayload(this);
1298
1299    m_jit.move(TrustedImm32(1), resultPayload.gpr());
1300    MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1301    m_jit.move(TrustedImm32(0), resultPayload.gpr());
1302    trueCase.link(&m_jit);
1303
1304    booleanResult(resultPayload.gpr(), node);
1305}
1306
1307void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1308{
1309    JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1310    GPRTemporary resultPayload(this);
1311    GPRReg valueTagGPR = value.tagGPR();
1312    GPRReg valuePayloadGPR = value.payloadGPR();
1313    GPRReg resultPayloadGPR = resultPayload.gpr();
1314    GPRTemporary structure;
1315    GPRReg structureGPR = InvalidGPRReg;
1316
1317    bool masqueradesAsUndefinedWatchpointValid =
1318        masqueradesAsUndefinedWatchpointIsStillValid();
1319
1320    if (!masqueradesAsUndefinedWatchpointValid) {
1321        // The masquerades as undefined case will use the structure register, so allocate it here.
1322        // Do this at the top of the function to avoid branching around a register allocation.
1323        GPRTemporary realStructure(this);
1324        structure.adopt(realStructure);
1325        structureGPR = structure.gpr();
1326    }
1327
1328    MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs());
1329    if (masqueradesAsUndefinedWatchpointValid) {
1330        DFG_TYPE_CHECK(
1331            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1332            m_jit.branchPtr(
1333                MacroAssembler::Equal,
1334                MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()),
1335                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1336    } else {
1337        m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), structureGPR);
1338
1339        DFG_TYPE_CHECK(
1340            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1341            m_jit.branchPtr(
1342                MacroAssembler::Equal,
1343                structureGPR,
1344                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1345
1346        MacroAssembler::Jump isNotMasqueradesAsUndefined =
1347            m_jit.branchTest8(
1348                MacroAssembler::Zero,
1349                MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()),
1350                MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1351
1352        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1353            m_jit.branchPtr(
1354                MacroAssembler::Equal,
1355                MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()),
1356                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1357
1358        isNotMasqueradesAsUndefined.link(&m_jit);
1359    }
1360    m_jit.move(TrustedImm32(0), resultPayloadGPR);
1361    MacroAssembler::Jump done = m_jit.jump();
1362
1363    notCell.link(&m_jit);
1364
1365    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1366    if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1367        m_jit.move(valueTagGPR, resultPayloadGPR);
1368        m_jit.or32(TrustedImm32(1), resultPayloadGPR);
1369        typeCheck(
1370            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1371            m_jit.branch32(
1372                MacroAssembler::NotEqual,
1373                resultPayloadGPR,
1374                TrustedImm32(JSValue::NullTag)));
1375    }
1376    m_jit.move(TrustedImm32(1), resultPayloadGPR);
1377
1378    done.link(&m_jit);
1379
1380    booleanResult(resultPayloadGPR, m_currentNode);
1381}
1382
1383void SpeculativeJIT::compileLogicalNot(Node* node)
1384{
1385    switch (node->child1().useKind()) {
1386    case BooleanUse: {
1387        SpeculateBooleanOperand value(this, node->child1());
1388        GPRTemporary result(this, Reuse, value);
1389        m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
1390        booleanResult(result.gpr(), node);
1391        return;
1392    }
1393
1394    case ObjectOrOtherUse: {
1395        compileObjectOrOtherLogicalNot(node->child1());
1396        return;
1397    }
1398
1399    case Int32Use: {
1400        SpeculateInt32Operand value(this, node->child1());
1401        GPRTemporary resultPayload(this, Reuse, value);
1402        m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr());
1403        booleanResult(resultPayload.gpr(), node);
1404        return;
1405    }
1406
1407    case DoubleRepUse: {
1408        SpeculateDoubleOperand value(this, node->child1());
1409        FPRTemporary scratch(this);
1410        GPRTemporary resultPayload(this);
1411        m_jit.move(TrustedImm32(0), resultPayload.gpr());
1412        MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1413        m_jit.move(TrustedImm32(1), resultPayload.gpr());
1414        nonZero.link(&m_jit);
1415        booleanResult(resultPayload.gpr(), node);
1416        return;
1417    }
1418
1419    case UntypedUse: {
1420        JSValueOperand arg1(this, node->child1());
1421        GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
1422        GPRReg arg1TagGPR = arg1.tagGPR();
1423        GPRReg arg1PayloadGPR = arg1.payloadGPR();
1424        GPRReg resultPayloadGPR = resultPayload.gpr();
1425
1426        arg1.use();
1427
1428        JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
1429
1430        m_jit.move(arg1PayloadGPR, resultPayloadGPR);
1431
1432        addSlowPathGenerator(
1433            slowPathCall(
1434                slowCase, this, operationConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR,
1435                arg1PayloadGPR));
1436
1437        m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
1438        booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
1439        return;
1440    }
1441    case StringUse:
1442        return compileStringZeroLength(node);
1443
1444    default:
1445        RELEASE_ASSERT_NOT_REACHED();
1446        break;
1447    }
1448}
1449
1450void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1451{
1452    JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1453    GPRTemporary scratch(this);
1454    GPRReg valueTagGPR = value.tagGPR();
1455    GPRReg valuePayloadGPR = value.payloadGPR();
1456    GPRReg scratchGPR = scratch.gpr();
1457
1458    MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs());
1459    if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1460        DFG_TYPE_CHECK(
1461            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1462            m_jit.branchPtr(
1463                MacroAssembler::Equal,
1464                MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()),
1465                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1466    } else {
1467        m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), scratchGPR);
1468
1469        DFG_TYPE_CHECK(
1470            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1471            m_jit.branchPtr(
1472                MacroAssembler::Equal,
1473                scratchGPR,
1474                MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1475
1476        JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1477            JITCompiler::Zero,
1478            MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()),
1479            TrustedImm32(MasqueradesAsUndefined));
1480
1481        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1482            m_jit.branchPtr(
1483                MacroAssembler::Equal,
1484                MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()),
1485                MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1486
1487        isNotMasqueradesAsUndefined.link(&m_jit);
1488    }
1489    jump(taken, ForceJump);
1490
1491    notCell.link(&m_jit);
1492
1493    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1494    if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1495        m_jit.move(valueTagGPR, scratchGPR);
1496        m_jit.or32(TrustedImm32(1), scratchGPR);
1497        typeCheck(
1498            JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1499            m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
1500    }
1501
1502    jump(notTaken);
1503
1504    noResult(m_currentNode);
1505}
1506
1507void SpeculativeJIT::emitBranch(Node* node)
1508{
1509    BasicBlock* taken = node->branchData()->taken.block;
1510    BasicBlock* notTaken = node->branchData()->notTaken.block;
1511
1512    switch (node->child1().useKind()) {
1513    case BooleanUse: {
1514        SpeculateBooleanOperand value(this, node->child1());
1515        MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1516
1517        if (taken == nextBlock()) {
1518            condition = MacroAssembler::Zero;
1519            BasicBlock* tmp = taken;
1520            taken = notTaken;
1521            notTaken = tmp;
1522        }
1523
1524        branchTest32(condition, value.gpr(), TrustedImm32(1), taken);
1525        jump(notTaken);
1526
1527        noResult(node);
1528        return;
1529    }
1530
1531    case ObjectOrOtherUse: {
1532        emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1533        return;
1534    }
1535
1536    case DoubleRepUse:
1537    case Int32Use: {
1538        if (node->child1().useKind() == Int32Use) {
1539            bool invert = false;
1540
1541            if (taken == nextBlock()) {
1542                invert = true;
1543                BasicBlock* tmp = taken;
1544                taken = notTaken;
1545                notTaken = tmp;
1546            }
1547
1548            SpeculateInt32Operand value(this, node->child1());
1549            branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1550        } else {
1551            SpeculateDoubleOperand value(this, node->child1());
1552            FPRTemporary scratch(this);
1553            branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1554        }
1555
1556        jump(notTaken);
1557
1558        noResult(node);
1559        return;
1560    }
1561
1562    case UntypedUse: {
1563        JSValueOperand value(this, node->child1());
1564        value.fill();
1565        GPRReg valueTagGPR = value.tagGPR();
1566        GPRReg valuePayloadGPR = value.payloadGPR();
1567
1568        GPRTemporary result(this);
1569        GPRReg resultGPR = result.gpr();
1570
1571        use(node->child1());
1572
1573        JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
1574        JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
1575
1576        fastPath.link(&m_jit);
1577        branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken);
1578        jump(taken, ForceJump);
1579
1580        slowPath.link(&m_jit);
1581        silentSpillAllRegisters(resultGPR);
1582        callOperation(operationConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR);
1583        silentFillAllRegisters(resultGPR);
1584
1585        branchTest32(JITCompiler::NonZero, resultGPR, taken);
1586        jump(notTaken);
1587
1588        noResult(node, UseChildrenCalledExplicitly);
1589        return;
1590    }
1591
1592    default:
1593        RELEASE_ASSERT_NOT_REACHED();
1594        break;
1595    }
1596}
1597
1598template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1599void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag)
1600{
1601    Edge child4 = m_jit.graph().varArgChild(node, 3);
1602
1603    ArrayMode arrayMode = node->arrayMode();
1604
1605    GPRReg baseReg = base.gpr();
1606    GPRReg propertyReg = property.gpr();
1607
1608    StorageOperand storage(this, child4);
1609    GPRReg storageReg = storage.gpr();
1610
1611    if (node->op() == PutByValAlias) {
1612        // Store the value to the array.
1613        GPRReg propertyReg = property.gpr();
1614        m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1615        m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1616
1617        noResult(node);
1618        return;
1619    }
1620
1621    MacroAssembler::Jump slowCase;
1622
1623    if (arrayMode.isInBounds()) {
1624        speculationCheck(
1625            OutOfBounds, JSValueRegs(), 0,
1626            m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1627    } else {
1628        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1629
1630        slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1631
1632        if (!arrayMode.isOutOfBounds())
1633            speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1634
1635        m_jit.add32(TrustedImm32(1), propertyReg);
1636        m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1637        m_jit.sub32(TrustedImm32(1), propertyReg);
1638
1639        inBounds.link(&m_jit);
1640    }
1641
1642    m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1643    m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1644
1645    base.use();
1646    property.use();
1647    value.use();
1648    storage.use();
1649
1650    if (arrayMode.isOutOfBounds()) {
1651        if (node->op() == PutByValDirect) {
1652            addSlowPathGenerator(slowPathCall(
1653                slowCase, this,
1654                m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
1655                NoResult, baseReg, propertyReg, valueTag, valuePayloadReg));
1656        } else {
1657            addSlowPathGenerator(slowPathCall(
1658                slowCase, this,
1659                m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
1660                NoResult, baseReg, propertyReg, valueTag, valuePayloadReg));
1661        }
1662    }
1663
1664    noResult(node, UseChildrenCalledExplicitly);
1665}
1666
1667void SpeculativeJIT::compile(Node* node)
1668{
1669    NodeType op = node->op();
1670
1671#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1672    m_jit.clearRegisterAllocationOffsets();
1673#endif
1674
1675    switch (op) {
1676    case JSConstant:
1677    case DoubleConstant:
1678        initConstantInfo(node);
1679        break;
1680
1681    case PhantomArguments:
1682        initConstantInfo(node);
1683        break;
1684
1685    case WeakJSConstant:
1686        m_jit.addWeakReference(node->weakConstant());
1687        initConstantInfo(node);
1688        break;
1689
1690    case Identity: {
1691        RELEASE_ASSERT_NOT_REACHED();
1692        break;
1693    }
1694
1695    case GetLocal: {
1696        AbstractValue& value = m_state.variables().operand(node->local());
1697
1698        // If the CFA is tracking this variable and it found that the variable
1699        // cannot have been assigned, then don't attempt to proceed.
1700        if (value.isClear()) {
1701            // FIXME: We should trap instead.
1702            // https://bugs.webkit.org/show_bug.cgi?id=110383
1703            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
1704            break;
1705        }
1706
1707        switch (node->variableAccessData()->flushFormat()) {
1708        case FlushedDouble: {
1709            FPRTemporary result(this);
1710            m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
1711            VirtualRegister virtualRegister = node->virtualRegister();
1712            m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
1713            generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
1714            break;
1715        }
1716
1717        case FlushedInt32: {
1718            GPRTemporary result(this);
1719            m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1720
1721            // Like int32Result, but don't useChildren - our children are phi nodes,
1722            // and don't represent values within this dataflow with virtual registers.
1723            VirtualRegister virtualRegister = node->virtualRegister();
1724            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
1725            generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
1726            break;
1727        }
1728
1729        case FlushedCell: {
1730            GPRTemporary result(this);
1731            m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1732
1733            // Like cellResult, but don't useChildren - our children are phi nodes,
1734            // and don't represent values within this dataflow with virtual registers.
1735            VirtualRegister virtualRegister = node->virtualRegister();
1736            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
1737            generationInfoFromVirtualRegister(virtualRegister).initCell(node, node->refCount(), result.gpr());
1738            break;
1739        }
1740
1741        case FlushedBoolean: {
1742            GPRTemporary result(this);
1743            m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1744
1745            // Like booleanResult, but don't useChildren - our children are phi nodes,
1746            // and don't represent values within this dataflow with virtual registers.
1747            VirtualRegister virtualRegister = node->virtualRegister();
1748            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
1749            generationInfoFromVirtualRegister(virtualRegister).initBoolean(node, node->refCount(), result.gpr());
1750            break;
1751        }
1752
1753        case FlushedJSValue:
1754        case FlushedArguments: {
1755            GPRTemporary result(this);
1756            GPRTemporary tag(this);
1757            m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1758            m_jit.load32(JITCompiler::tagFor(node->machineLocal()), tag.gpr());
1759
1760            // Like jsValueResult, but don't useChildren - our children are phi nodes,
1761            // and don't represent values within this dataflow with virtual registers.
1762            VirtualRegister virtualRegister = node->virtualRegister();
1763            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1764            m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
1765
1766            generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS);
1767            break;
1768        }
1769
1770        default:
1771            RELEASE_ASSERT_NOT_REACHED();
1772        }
1773        break;
1774    }
1775
1776    case GetLocalUnlinked: {
1777        GPRTemporary payload(this);
1778        GPRTemporary tag(this);
1779        m_jit.load32(JITCompiler::payloadFor(node->unlinkedMachineLocal()), payload.gpr());
1780        m_jit.load32(JITCompiler::tagFor(node->unlinkedMachineLocal()), tag.gpr());
1781        jsValueResult(tag.gpr(), payload.gpr(), node);
1782        break;
1783    }
1784
1785    case MovHint:
1786    case ZombieHint:
1787    case Check: {
1788        RELEASE_ASSERT_NOT_REACHED();
1789        break;
1790    }
1791
1792    case SetLocal: {
1793        switch (node->variableAccessData()->flushFormat()) {
1794        case FlushedDouble: {
1795            SpeculateDoubleOperand value(this, node->child1());
1796            m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
1797            noResult(node);
1798            // Indicate that it's no longer necessary to retrieve the value of
1799            // this bytecode variable from registers or other locations in the stack,
1800            // but that it is stored as a double.
1801            recordSetLocal(DataFormatDouble);
1802            break;
1803        }
1804
1805        case FlushedInt32: {
1806            SpeculateInt32Operand value(this, node->child1());
1807            m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1808            noResult(node);
1809            recordSetLocal(DataFormatInt32);
1810            break;
1811        }
1812
1813        case FlushedCell: {
1814            SpeculateCellOperand cell(this, node->child1());
1815            GPRReg cellGPR = cell.gpr();
1816            m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->machineLocal()));
1817            noResult(node);
1818            recordSetLocal(DataFormatCell);
1819            break;
1820        }
1821
1822        case FlushedBoolean: {
1823            SpeculateBooleanOperand value(this, node->child1());
1824            m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1825            noResult(node);
1826            recordSetLocal(DataFormatBoolean);
1827            break;
1828        }
1829
1830        case FlushedJSValue:
1831        case FlushedArguments: {
1832            JSValueOperand value(this, node->child1());
1833            m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal()));
1834            m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal()));
1835            noResult(node);
1836            recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1837            break;
1838        }
1839
1840        default:
1841            RELEASE_ASSERT_NOT_REACHED();
1842            break;
1843        }
1844        break;
1845    }
1846
1847    case SetArgument:
1848        // This is a no-op; it just marks the fact that the argument is being used.
1849        // But it may be profitable to use this as a hook to run speculation checks
1850        // on arguments, thereby allowing us to trivially eliminate such checks if
1851        // the argument is not used.
1852        recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1853        break;
1854
1855    case BitAnd:
1856    case BitOr:
1857    case BitXor:
1858        if (isInt32Constant(node->child1().node())) {
1859            SpeculateInt32Operand op2(this, node->child2());
1860            GPRTemporary result(this, Reuse, op2);
1861
1862            bitOp(op, valueOfInt32Constant(node->child1().node()), op2.gpr(), result.gpr());
1863
1864            int32Result(result.gpr(), node);
1865        } else if (isInt32Constant(node->child2().node())) {
1866            SpeculateInt32Operand op1(this, node->child1());
1867            GPRTemporary result(this, Reuse, op1);
1868
1869            bitOp(op, valueOfInt32Constant(node->child2().node()), op1.gpr(), result.gpr());
1870
1871            int32Result(result.gpr(), node);
1872        } else {
1873            SpeculateInt32Operand op1(this, node->child1());
1874            SpeculateInt32Operand op2(this, node->child2());
1875            GPRTemporary result(this, Reuse, op1, op2);
1876
1877            GPRReg reg1 = op1.gpr();
1878            GPRReg reg2 = op2.gpr();
1879            bitOp(op, reg1, reg2, result.gpr());
1880
1881            int32Result(result.gpr(), node);
1882        }
1883        break;
1884
1885    case BitRShift:
1886    case BitLShift:
1887    case BitURShift:
1888        if (isInt32Constant(node->child2().node())) {
1889            SpeculateInt32Operand op1(this, node->child1());
1890            GPRTemporary result(this, Reuse, op1);
1891
1892            shiftOp(op, op1.gpr(), valueOfInt32Constant(node->child2().node()) & 0x1f, result.gpr());
1893
1894            int32Result(result.gpr(), node);
1895        } else {
1896            // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
1897            SpeculateInt32Operand op1(this, node->child1());
1898            SpeculateInt32Operand op2(this, node->child2());
1899            GPRTemporary result(this, Reuse, op1);
1900
1901            GPRReg reg1 = op1.gpr();
1902            GPRReg reg2 = op2.gpr();
1903            shiftOp(op, reg1, reg2, result.gpr());
1904
1905            int32Result(result.gpr(), node);
1906        }
1907        break;
1908
1909    case UInt32ToNumber: {
1910        compileUInt32ToNumber(node);
1911        break;
1912    }
1913
1914    case DoubleAsInt32: {
1915        compileDoubleAsInt32(node);
1916        break;
1917    }
1918
1919    case ValueToInt32: {
1920        compileValueToInt32(node);
1921        break;
1922    }
1923
1924    case DoubleRep: {
1925        compileDoubleRep(node);
1926        break;
1927    }
1928
1929    case ValueRep: {
1930        compileValueRep(node);
1931        break;
1932    }
1933
1934    case ValueAdd: {
1935        JSValueOperand op1(this, node->child1());
1936        JSValueOperand op2(this, node->child2());
1937
1938        GPRReg op1TagGPR = op1.tagGPR();
1939        GPRReg op1PayloadGPR = op1.payloadGPR();
1940        GPRReg op2TagGPR = op2.tagGPR();
1941        GPRReg op2PayloadGPR = op2.payloadGPR();
1942
1943        flushRegisters();
1944
1945        GPRResult2 resultTag(this);
1946        GPRResult resultPayload(this);
1947        if (isKnownNotNumber(node->child1().node()) || isKnownNotNumber(node->child2().node()))
1948            callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
1949        else
1950            callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
1951
1952        jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
1953        break;
1954    }
1955
1956    case ArithAdd:
1957        compileAdd(node);
1958        break;
1959
1960    case MakeRope:
1961        compileMakeRope(node);
1962        break;
1963
1964    case ArithSub:
1965        compileArithSub(node);
1966        break;
1967
1968    case ArithNegate:
1969        compileArithNegate(node);
1970        break;
1971
1972    case ArithMul:
1973        compileArithMul(node);
1974        break;
1975
1976    case ArithDiv: {
1977        compileArithDiv(node);
1978        break;
1979    }
1980
1981    case ArithMod: {
1982        compileArithMod(node);
1983        break;
1984    }
1985
1986    case ArithAbs: {
1987        switch (node->child1().useKind()) {
1988        case Int32Use: {
1989            SpeculateStrictInt32Operand op1(this, node->child1());
1990            GPRTemporary result(this, Reuse, op1);
1991            GPRTemporary scratch(this);
1992
1993            m_jit.move(op1.gpr(), result.gpr());
1994            m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
1995            m_jit.add32(scratch.gpr(), result.gpr());
1996            m_jit.xor32(scratch.gpr(), result.gpr());
1997            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
1998            int32Result(result.gpr(), node);
1999            break;
2000        }
2001
2002
2003        case DoubleRepUse: {
2004            SpeculateDoubleOperand op1(this, node->child1());
2005            FPRTemporary result(this);
2006
2007            m_jit.absDouble(op1.fpr(), result.fpr());
2008            doubleResult(result.fpr(), node);
2009            break;
2010        }
2011
2012        default:
2013            RELEASE_ASSERT_NOT_REACHED();
2014            break;
2015        }
2016        break;
2017    }
2018
2019    case ArithMin:
2020    case ArithMax: {
2021        switch (node->binaryUseKind()) {
2022        case Int32Use: {
2023            SpeculateStrictInt32Operand op1(this, node->child1());
2024            SpeculateStrictInt32Operand op2(this, node->child2());
2025            GPRTemporary result(this, Reuse, op1);
2026
2027            GPRReg op1GPR = op1.gpr();
2028            GPRReg op2GPR = op2.gpr();
2029            GPRReg resultGPR = result.gpr();
2030
2031            MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1GPR, op2GPR);
2032            m_jit.move(op2GPR, resultGPR);
2033            if (op1GPR != resultGPR) {
2034                MacroAssembler::Jump done = m_jit.jump();
2035                op1Less.link(&m_jit);
2036                m_jit.move(op1GPR, resultGPR);
2037                done.link(&m_jit);
2038            } else
2039                op1Less.link(&m_jit);
2040
2041            int32Result(resultGPR, node);
2042            break;
2043        }
2044
2045        case DoubleRepUse: {
2046            SpeculateDoubleOperand op1(this, node->child1());
2047            SpeculateDoubleOperand op2(this, node->child2());
2048            FPRTemporary result(this, op1);
2049
2050            FPRReg op1FPR = op1.fpr();
2051            FPRReg op2FPR = op2.fpr();
2052            FPRReg resultFPR = result.fpr();
2053
2054            MacroAssembler::JumpList done;
2055
2056            MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2057
2058            // op2 is eather the lesser one or one of then is NaN
2059            MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2060
2061            // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding
2062            // op1 + op2 and putting it into result.
2063            m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2064            done.append(m_jit.jump());
2065
2066            op2Less.link(&m_jit);
2067            m_jit.moveDouble(op2FPR, resultFPR);
2068
2069            if (op1FPR != resultFPR) {
2070                done.append(m_jit.jump());
2071
2072                op1Less.link(&m_jit);
2073                m_jit.moveDouble(op1FPR, resultFPR);
2074            } else
2075                op1Less.link(&m_jit);
2076
2077            done.link(&m_jit);
2078
2079            doubleResult(resultFPR, node);
2080            break;
2081        }
2082
2083        default:
2084            RELEASE_ASSERT_NOT_REACHED();
2085            break;
2086        }
2087        break;
2088    }
2089
2090    case ArithSqrt: {
2091        SpeculateDoubleOperand op1(this, node->child1());
2092        FPRTemporary result(this, op1);
2093
2094        m_jit.sqrtDouble(op1.fpr(), result.fpr());
2095
2096        doubleResult(result.fpr(), node);
2097        break;
2098    }
2099
2100    case ArithFRound: {
2101        SpeculateDoubleOperand op1(this, node->child1());
2102        FPRTemporary result(this, op1);
2103
2104        m_jit.convertDoubleToFloat(op1.fpr(), result.fpr());
2105        m_jit.convertFloatToDouble(result.fpr(), result.fpr());
2106
2107        doubleResult(result.fpr(), node);
2108        break;
2109    }
2110
2111    case ArithSin: {
2112        SpeculateDoubleOperand op1(this, node->child1());
2113        FPRReg op1FPR = op1.fpr();
2114
2115        flushRegisters();
2116
2117        FPRResult result(this);
2118        callOperation(sin, result.fpr(), op1FPR);
2119        doubleResult(result.fpr(), node);
2120        break;
2121    }
2122
2123    case ArithCos: {
2124        SpeculateDoubleOperand op1(this, node->child1());
2125        FPRReg op1FPR = op1.fpr();
2126
2127        flushRegisters();
2128
2129        FPRResult result(this);
2130        callOperation(cos, result.fpr(), op1FPR);
2131        doubleResult(result.fpr(), node);
2132        break;
2133    }
2134
2135    case LogicalNot:
2136        compileLogicalNot(node);
2137        break;
2138
2139    case CompareLess:
2140        if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2141            return;
2142        break;
2143
2144    case CompareLessEq:
2145        if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2146            return;
2147        break;
2148
2149    case CompareGreater:
2150        if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2151            return;
2152        break;
2153
2154    case CompareGreaterEq:
2155        if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2156            return;
2157        break;
2158
2159    case CompareEqConstant:
2160        ASSERT(isNullConstant(node->child2().node()));
2161        if (nonSpeculativeCompareNull(node, node->child1()))
2162            return;
2163        break;
2164
2165    case CompareEq:
2166        if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2167            return;
2168        break;
2169
2170    case CompareStrictEq:
2171        if (compileStrictEq(node))
2172            return;
2173        break;
2174
2175    case StringCharCodeAt: {
2176        compileGetCharCodeAt(node);
2177        break;
2178    }
2179
2180    case StringCharAt: {
2181        // Relies on StringCharAt node having same basic layout as GetByVal
2182        compileGetByValOnString(node);
2183        break;
2184    }
2185
2186    case StringFromCharCode: {
2187        compileFromCharCode(node);
2188        break;
2189    }
2190
2191    case CheckArray: {
2192        checkArray(node);
2193        break;
2194    }
2195
2196    case Arrayify:
2197    case ArrayifyToStructure: {
2198        arrayify(node);
2199        break;
2200    }
2201
2202    case GetByVal: {
2203        switch (node->arrayMode().type()) {
2204        case Array::SelectUsingPredictions:
2205        case Array::ForceExit:
2206            RELEASE_ASSERT_NOT_REACHED();
2207            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2208            break;
2209        case Array::Generic: {
2210            SpeculateCellOperand base(this, node->child1()); // Save a register, speculate cell. We'll probably be right.
2211            JSValueOperand property(this, node->child2());
2212            GPRReg baseGPR = base.gpr();
2213            GPRReg propertyTagGPR = property.tagGPR();
2214            GPRReg propertyPayloadGPR = property.payloadGPR();
2215
2216            flushRegisters();
2217            GPRResult2 resultTag(this);
2218            GPRResult resultPayload(this);
2219            callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR);
2220
2221            jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2222            break;
2223        }
2224        case Array::Int32:
2225        case Array::Contiguous: {
2226            if (node->arrayMode().isInBounds()) {
2227                SpeculateStrictInt32Operand property(this, node->child2());
2228                StorageOperand storage(this, node->child3());
2229
2230                GPRReg propertyReg = property.gpr();
2231                GPRReg storageReg = storage.gpr();
2232
2233                if (!m_compileOkay)
2234                    return;
2235
2236                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2237
2238                GPRTemporary resultPayload(this);
2239                if (node->arrayMode().type() == Array::Int32) {
2240                    speculationCheck(
2241                        OutOfBounds, JSValueRegs(), 0,
2242                        m_jit.branch32(
2243                            MacroAssembler::Equal,
2244                            MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2245                            TrustedImm32(JSValue::EmptyValueTag)));
2246                    m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2247                    int32Result(resultPayload.gpr(), node);
2248                    break;
2249                }
2250
2251                GPRTemporary resultTag(this);
2252                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2253                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2254                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2255                jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2256                break;
2257            }
2258
2259            SpeculateCellOperand base(this, node->child1());
2260            SpeculateStrictInt32Operand property(this, node->child2());
2261            StorageOperand storage(this, node->child3());
2262
2263            GPRReg baseReg = base.gpr();
2264            GPRReg propertyReg = property.gpr();
2265            GPRReg storageReg = storage.gpr();
2266
2267            if (!m_compileOkay)
2268                return;
2269
2270            GPRTemporary resultTag(this);
2271            GPRTemporary resultPayload(this);
2272            GPRReg resultTagReg = resultTag.gpr();
2273            GPRReg resultPayloadReg = resultPayload.gpr();
2274
2275            MacroAssembler::JumpList slowCases;
2276
2277            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2278
2279            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2280            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2281            slowCases.append(m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag)));
2282
2283            addSlowPathGenerator(
2284                slowPathCall(
2285                    slowCases, this, operationGetByValArrayInt,
2286                    JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2287
2288            jsValueResult(resultTagReg, resultPayloadReg, node);
2289            break;
2290        }
2291        case Array::Double: {
2292            if (node->arrayMode().isInBounds()) {
2293                SpeculateStrictInt32Operand property(this, node->child2());
2294                StorageOperand storage(this, node->child3());
2295
2296                GPRReg propertyReg = property.gpr();
2297                GPRReg storageReg = storage.gpr();
2298
2299                if (!m_compileOkay)
2300                    return;
2301
2302                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2303
2304                FPRTemporary result(this);
2305                m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2306                if (!node->arrayMode().isSaneChain())
2307                    speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2308                doubleResult(result.fpr(), node);
2309                break;
2310            }
2311
2312            SpeculateCellOperand base(this, node->child1());
2313            SpeculateStrictInt32Operand property(this, node->child2());
2314            StorageOperand storage(this, node->child3());
2315
2316            GPRReg baseReg = base.gpr();
2317            GPRReg propertyReg = property.gpr();
2318            GPRReg storageReg = storage.gpr();
2319
2320            if (!m_compileOkay)
2321                return;
2322
2323            GPRTemporary resultTag(this);
2324            GPRTemporary resultPayload(this);
2325            FPRTemporary temp(this);
2326            GPRReg resultTagReg = resultTag.gpr();
2327            GPRReg resultPayloadReg = resultPayload.gpr();
2328            FPRReg tempReg = temp.fpr();
2329
2330            MacroAssembler::JumpList slowCases;
2331
2332            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2333
2334            m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2335            slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2336            boxDouble(tempReg, resultTagReg, resultPayloadReg);
2337
2338            addSlowPathGenerator(
2339                slowPathCall(
2340                    slowCases, this, operationGetByValArrayInt,
2341                    JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2342
2343            jsValueResult(resultTagReg, resultPayloadReg, node);
2344            break;
2345        }
2346        case Array::ArrayStorage:
2347        case Array::SlowPutArrayStorage: {
2348            if (node->arrayMode().isInBounds()) {
2349                SpeculateStrictInt32Operand property(this, node->child2());
2350                StorageOperand storage(this, node->child3());
2351                GPRReg propertyReg = property.gpr();
2352                GPRReg storageReg = storage.gpr();
2353
2354                if (!m_compileOkay)
2355                    return;
2356
2357                speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2358
2359                GPRTemporary resultTag(this);
2360                GPRTemporary resultPayload(this);
2361
2362                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2363                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2364                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2365
2366                jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2367                break;
2368            }
2369
2370            SpeculateCellOperand base(this, node->child1());
2371            SpeculateStrictInt32Operand property(this, node->child2());
2372            StorageOperand storage(this, node->child3());
2373            GPRReg propertyReg = property.gpr();
2374            GPRReg storageReg = storage.gpr();
2375            GPRReg baseReg = base.gpr();
2376
2377            if (!m_compileOkay)
2378                return;
2379
2380            GPRTemporary resultTag(this);
2381            GPRTemporary resultPayload(this);
2382            GPRReg resultTagReg = resultTag.gpr();
2383            GPRReg resultPayloadReg = resultPayload.gpr();
2384
2385            JITCompiler::Jump outOfBounds = m_jit.branch32(
2386                MacroAssembler::AboveOrEqual, propertyReg,
2387                MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2388
2389            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2390            JITCompiler::Jump hole = m_jit.branch32(
2391                MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag));
2392            m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2393
2394            JITCompiler::JumpList slowCases;
2395            slowCases.append(outOfBounds);
2396            slowCases.append(hole);
2397            addSlowPathGenerator(
2398                slowPathCall(
2399                    slowCases, this, operationGetByValArrayInt,
2400                    JSValueRegs(resultTagReg, resultPayloadReg),
2401                    baseReg, propertyReg));
2402
2403            jsValueResult(resultTagReg, resultPayloadReg, node);
2404            break;
2405        }
2406        case Array::String:
2407            compileGetByValOnString(node);
2408            break;
2409        case Array::Arguments:
2410            compileGetByValOnArguments(node);
2411            break;
2412        default: {
2413            TypedArrayType type = node->arrayMode().typedArrayType();
2414            if (isInt(type))
2415                compileGetByValOnIntTypedArray(node, type);
2416            else
2417                compileGetByValOnFloatTypedArray(node, type);
2418        } }
2419        break;
2420    }
2421
2422    case PutByValDirect:
2423    case PutByVal:
2424    case PutByValAlias: {
2425        Edge child1 = m_jit.graph().varArgChild(node, 0);
2426        Edge child2 = m_jit.graph().varArgChild(node, 1);
2427        Edge child3 = m_jit.graph().varArgChild(node, 2);
2428        Edge child4 = m_jit.graph().varArgChild(node, 3);
2429
2430        ArrayMode arrayMode = node->arrayMode().modeForPut();
2431        bool alreadyHandled = false;
2432
2433        switch (arrayMode.type()) {
2434        case Array::SelectUsingPredictions:
2435        case Array::ForceExit:
2436            RELEASE_ASSERT_NOT_REACHED();
2437            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2438            alreadyHandled = true;
2439            break;
2440        case Array::Generic: {
2441            ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
2442
2443            SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2444            JSValueOperand property(this, child2);
2445            JSValueOperand value(this, child3);
2446            GPRReg baseGPR = base.gpr();
2447            GPRReg propertyTagGPR = property.tagGPR();
2448            GPRReg propertyPayloadGPR = property.payloadGPR();
2449            GPRReg valueTagGPR = value.tagGPR();
2450            GPRReg valuePayloadGPR = value.payloadGPR();
2451
2452            flushRegisters();
2453            if (node->op() == PutByValDirect)
2454                callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
2455            else
2456                callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
2457
2458            noResult(node);
2459            alreadyHandled = true;
2460            break;
2461        }
2462        default:
2463            break;
2464        }
2465
2466        if (alreadyHandled)
2467            break;
2468
2469        SpeculateCellOperand base(this, child1);
2470        SpeculateStrictInt32Operand property(this, child2);
2471
2472        GPRReg baseReg = base.gpr();
2473        GPRReg propertyReg = property.gpr();
2474
2475        switch (arrayMode.type()) {
2476        case Array::Int32: {
2477            SpeculateInt32Operand value(this, child3);
2478
2479            GPRReg valuePayloadReg = value.gpr();
2480
2481            if (!m_compileOkay)
2482                return;
2483
2484            compileContiguousPutByVal(node, base, property, value, valuePayloadReg, TrustedImm32(JSValue::Int32Tag));
2485            break;
2486        }
2487        case Array::Contiguous: {
2488            JSValueOperand value(this, child3);
2489
2490            GPRReg valueTagReg = value.tagGPR();
2491            GPRReg valuePayloadReg = value.payloadGPR();
2492
2493            if (!m_compileOkay)
2494                return;
2495
2496            compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2497            break;
2498        }
2499        case Array::Double: {
2500            compileDoublePutByVal(node, base, property);
2501            break;
2502        }
2503        case Array::ArrayStorage:
2504        case Array::SlowPutArrayStorage: {
2505            JSValueOperand value(this, child3);
2506
2507            GPRReg valueTagReg = value.tagGPR();
2508            GPRReg valuePayloadReg = value.payloadGPR();
2509
2510            if (!m_compileOkay)
2511                return;
2512
2513            StorageOperand storage(this, child4);
2514            GPRReg storageReg = storage.gpr();
2515
2516            if (node->op() == PutByValAlias) {
2517                // Store the value to the array.
2518                GPRReg propertyReg = property.gpr();
2519                m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2520                m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2521
2522                noResult(node);
2523                break;
2524            }
2525
2526            MacroAssembler::JumpList slowCases;
2527
2528            MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2529            if (!arrayMode.isOutOfBounds())
2530                speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2531            else
2532                slowCases.append(beyondArrayBounds);
2533
2534            // Check if we're writing to a hole; if so increment m_numValuesInVector.
2535            if (arrayMode.isInBounds()) {
2536                speculationCheck(
2537                    StoreToHole, JSValueRegs(), 0,
2538                    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)));
2539            } else {
2540                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));
2541                if (arrayMode.isSlowPut()) {
2542                    // This is sort of strange. If we wanted to optimize this code path, we would invert
2543                    // the above branch. But it's simply not worth it since this only happens if we're
2544                    // already having a bad time.
2545                    slowCases.append(m_jit.jump());
2546                } else {
2547                    m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2548
2549                    // If we're writing to a hole we might be growing the array;
2550                    MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2551                    m_jit.add32(TrustedImm32(1), propertyReg);
2552                    m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2553                    m_jit.sub32(TrustedImm32(1), propertyReg);
2554
2555                    lengthDoesNotNeedUpdate.link(&m_jit);
2556                }
2557                notHoleValue.link(&m_jit);
2558            }
2559
2560            // Store the value to the array.
2561            m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2562            m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2563
2564            base.use();
2565            property.use();
2566            value.use();
2567            storage.use();
2568
2569            if (!slowCases.empty()) {
2570                if (node->op() == PutByValDirect) {
2571                    addSlowPathGenerator(slowPathCall(
2572                        slowCases, this,
2573                        m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2574                        NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
2575                } else {
2576                    addSlowPathGenerator(slowPathCall(
2577                        slowCases, this,
2578                        m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2579                        NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
2580                }
2581            }
2582
2583            noResult(node, UseChildrenCalledExplicitly);
2584            break;
2585        }
2586
2587        case Array::Arguments:
2588            // FIXME: we could at some point make this work. Right now we're assuming that the register
2589            // pressure would be too great.
2590            RELEASE_ASSERT_NOT_REACHED();
2591            break;
2592
2593        default: {
2594            TypedArrayType type = arrayMode.typedArrayType();
2595            if (isInt(type))
2596                compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2597            else
2598                compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2599        } }
2600        break;
2601    }
2602
2603    case RegExpExec: {
2604        if (compileRegExpExec(node))
2605            return;
2606
2607        if (!node->adjustedRefCount()) {
2608            SpeculateCellOperand base(this, node->child1());
2609            SpeculateCellOperand argument(this, node->child2());
2610            GPRReg baseGPR = base.gpr();
2611            GPRReg argumentGPR = argument.gpr();
2612
2613            flushRegisters();
2614            GPRResult result(this);
2615            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2616
2617            // Must use jsValueResult because otherwise we screw up register
2618            // allocation, which thinks that this node has a result.
2619            booleanResult(result.gpr(), node);
2620            break;
2621        }
2622
2623        SpeculateCellOperand base(this, node->child1());
2624        SpeculateCellOperand argument(this, node->child2());
2625        GPRReg baseGPR = base.gpr();
2626        GPRReg argumentGPR = argument.gpr();
2627
2628        flushRegisters();
2629        GPRResult2 resultTag(this);
2630        GPRResult resultPayload(this);
2631        callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR);
2632
2633        jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2634        break;
2635    }
2636
2637    case RegExpTest: {
2638        SpeculateCellOperand base(this, node->child1());
2639        SpeculateCellOperand argument(this, node->child2());
2640        GPRReg baseGPR = base.gpr();
2641        GPRReg argumentGPR = argument.gpr();
2642
2643        flushRegisters();
2644        GPRResult result(this);
2645        callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2646
2647        // If we add a DataFormatBool, we should use it here.
2648        booleanResult(result.gpr(), node);
2649        break;
2650    }
2651
2652    case ArrayPush: {
2653        ASSERT(node->arrayMode().isJSArray());
2654
2655        SpeculateCellOperand base(this, node->child1());
2656        GPRTemporary storageLength(this);
2657
2658        GPRReg baseGPR = base.gpr();
2659        GPRReg storageLengthGPR = storageLength.gpr();
2660
2661        StorageOperand storage(this, node->child3());
2662        GPRReg storageGPR = storage.gpr();
2663
2664        switch (node->arrayMode().type()) {
2665        case Array::Int32: {
2666            SpeculateInt32Operand value(this, node->child2());
2667            GPRReg valuePayloadGPR = value.gpr();
2668
2669            m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
2670            MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
2671            m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2672            m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2673            m_jit.add32(TrustedImm32(1), storageLengthGPR);
2674            m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2675            m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
2676
2677            addSlowPathGenerator(
2678                slowPathCall(
2679                    slowPath, this, operationArrayPush,
2680                    JSValueRegs(storageGPR, storageLengthGPR),
2681                    TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR));
2682
2683            jsValueResult(storageGPR, storageLengthGPR, node);
2684            break;
2685        }
2686
2687        case Array::Contiguous: {
2688            JSValueOperand value(this, node->child2());
2689            GPRReg valueTagGPR = value.tagGPR();
2690            GPRReg valuePayloadGPR = value.payloadGPR();
2691
2692            m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
2693            MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
2694            m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2695            m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2696            m_jit.add32(TrustedImm32(1), storageLengthGPR);
2697            m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2698            m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
2699
2700            addSlowPathGenerator(
2701                slowPathCall(
2702                    slowPath, this, operationArrayPush,
2703                    JSValueRegs(storageGPR, storageLengthGPR),
2704                    valueTagGPR, valuePayloadGPR, baseGPR));
2705
2706            jsValueResult(storageGPR, storageLengthGPR, node);
2707            break;
2708        }
2709
2710        case Array::Double: {
2711            SpeculateDoubleOperand value(this, node->child2());
2712            FPRReg valueFPR = value.fpr();
2713
2714            DFG_TYPE_CHECK(
2715                JSValueRegs(), node->child2(), SpecDoubleReal,
2716                m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
2717
2718            m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
2719            MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
2720            m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
2721            m_jit.add32(TrustedImm32(1), storageLengthGPR);
2722            m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2723            m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
2724
2725            addSlowPathGenerator(
2726                slowPathCall(
2727                    slowPath, this, operationArrayPushDouble,
2728                    JSValueRegs(storageGPR, storageLengthGPR),
2729                    valueFPR, baseGPR));
2730
2731            jsValueResult(storageGPR, storageLengthGPR, node);
2732            break;
2733        }
2734
2735        case Array::ArrayStorage: {
2736            JSValueOperand value(this, node->child2());
2737            GPRReg valueTagGPR = value.tagGPR();
2738            GPRReg valuePayloadGPR = value.payloadGPR();
2739
2740            m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2741
2742            // Refuse to handle bizarre lengths.
2743            speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
2744
2745            MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2746
2747            m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2748            m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2749
2750            m_jit.add32(TrustedImm32(1), storageLengthGPR);
2751            m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2752            m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2753            m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
2754
2755            addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR));
2756
2757            jsValueResult(storageGPR, storageLengthGPR, node);
2758            break;
2759        }
2760
2761        default:
2762            CRASH();
2763            break;
2764        }
2765        break;
2766    }
2767
2768    case ArrayPop: {
2769        ASSERT(node->arrayMode().isJSArray());
2770
2771        SpeculateCellOperand base(this, node->child1());
2772        StorageOperand storage(this, node->child2());
2773        GPRTemporary valueTag(this);
2774        GPRTemporary valuePayload(this);
2775
2776        GPRReg baseGPR = base.gpr();
2777        GPRReg valueTagGPR = valueTag.gpr();
2778        GPRReg valuePayloadGPR = valuePayload.gpr();
2779        GPRReg storageGPR = storage.gpr();
2780
2781        switch (node->arrayMode().type()) {
2782        case Array::Int32:
2783        case Array::Contiguous: {
2784            m_jit.load32(
2785                MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2786            MacroAssembler::Jump undefinedCase =
2787                m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2788            m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2789            m_jit.store32(
2790                valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2791            m_jit.load32(
2792                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2793                valueTagGPR);
2794            MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
2795            m_jit.store32(
2796                MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
2797                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2798            m_jit.load32(
2799                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
2800                valuePayloadGPR);
2801
2802            addSlowPathGenerator(
2803                slowPathMove(
2804                    undefinedCase, this,
2805                    MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2806                    MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2807            addSlowPathGenerator(
2808                slowPathCall(
2809                    slowCase, this, operationArrayPopAndRecoverLength,
2810                    JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2811
2812            jsValueResult(valueTagGPR, valuePayloadGPR, node);
2813            break;
2814        }
2815
2816        case Array::Double: {
2817            FPRTemporary temp(this);
2818            FPRReg tempFPR = temp.fpr();
2819
2820            m_jit.load32(
2821                MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2822            MacroAssembler::Jump undefinedCase =
2823                m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2824            m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2825            m_jit.store32(
2826                valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2827            m_jit.loadDouble(
2828                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
2829                tempFPR);
2830            MacroAssembler::Jump slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
2831            JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
2832            m_jit.store32(
2833                MacroAssembler::TrustedImm32(nan.u.asBits.tag),
2834                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2835            m_jit.store32(
2836                MacroAssembler::TrustedImm32(nan.u.asBits.payload),
2837                MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2838            boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
2839
2840            addSlowPathGenerator(
2841                slowPathMove(
2842                    undefinedCase, this,
2843                    MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2844                    MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2845            addSlowPathGenerator(
2846                slowPathCall(
2847                    slowCase, this, operationArrayPopAndRecoverLength,
2848                    JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2849
2850            jsValueResult(valueTagGPR, valuePayloadGPR, node);
2851            break;
2852        }
2853
2854        case Array::ArrayStorage: {
2855            GPRTemporary storageLength(this);
2856            GPRReg storageLengthGPR = storageLength.gpr();
2857
2858            m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2859
2860            JITCompiler::JumpList setUndefinedCases;
2861            setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
2862
2863            m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2864
2865            MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2866
2867            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
2868            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
2869
2870            m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2871
2872            setUndefinedCases.append(m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR));
2873
2874            m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2875
2876            m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2877
2878            addSlowPathGenerator(
2879                slowPathMove(
2880                    setUndefinedCases, this,
2881                    MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2882                    MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2883
2884            addSlowPathGenerator(
2885                slowPathCall(
2886                    slowCase, this, operationArrayPop,
2887                    JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2888
2889            jsValueResult(valueTagGPR, valuePayloadGPR, node);
2890            break;
2891        }
2892
2893        default:
2894            CRASH();
2895            break;
2896        }
2897        break;
2898    }
2899
2900    case DFG::Jump: {
2901        jump(node->targetBlock());
2902        noResult(node);
2903        break;
2904    }
2905
2906    case Branch:
2907        emitBranch(node);
2908        break;
2909
2910    case Switch:
2911        emitSwitch(node);
2912        break;
2913
2914    case Return: {
2915        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
2916        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2917        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2918
2919        // Return the result in returnValueGPR.
2920        JSValueOperand op1(this, node->child1());
2921        op1.fill();
2922        if (op1.isDouble())
2923            boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
2924        else {
2925            if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
2926                m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
2927            else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
2928                m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2929                m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2930            } else {
2931                m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2932                m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2933            }
2934        }
2935
2936        m_jit.emitFunctionEpilogue();
2937        m_jit.ret();
2938
2939        noResult(node);
2940        break;
2941    }
2942
2943    case Throw:
2944    case ThrowReferenceError: {
2945        // We expect that throw statements are rare and are intended to exit the code block
2946        // anyway, so we just OSR back to the old JIT for now.
2947        terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2948        break;
2949    }
2950
2951    case BooleanToNumber: {
2952        switch (node->child1().useKind()) {
2953        case BooleanUse: {
2954            SpeculateBooleanOperand value(this, node->child1());
2955            GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
2956
2957            m_jit.move(value.gpr(), result.gpr());
2958
2959            int32Result(result.gpr(), node);
2960            break;
2961        }
2962
2963        case UntypedUse: {
2964            JSValueOperand value(this, node->child1());
2965            GPRTemporary resultTag(this);
2966            GPRTemporary resultPayload(this);
2967
2968            GPRReg valueTagGPR = value.tagGPR();
2969            GPRReg valuePayloadGPR = value.payloadGPR();
2970            GPRReg resultTagGPR = resultTag.gpr();
2971            GPRReg resultPayloadGPR = resultPayload.gpr();
2972
2973            m_jit.move(valuePayloadGPR, resultPayloadGPR);
2974            JITCompiler::Jump isBoolean = m_jit.branch32(
2975                JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::BooleanTag));
2976            m_jit.move(valueTagGPR, resultTagGPR);
2977            JITCompiler::Jump done = m_jit.jump();
2978            isBoolean.link(&m_jit);
2979            m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
2980            done.link(&m_jit);
2981
2982            jsValueResult(resultTagGPR, resultPayloadGPR, node);
2983            break;
2984        }
2985
2986        default:
2987            RELEASE_ASSERT_NOT_REACHED();
2988            break;
2989        }
2990        break;
2991    }
2992
2993    case ToPrimitive: {
2994        RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
2995        JSValueOperand op1(this, node->child1());
2996        GPRTemporary resultTag(this, Reuse, op1, TagWord);
2997        GPRTemporary resultPayload(this, Reuse, op1, PayloadWord);
2998
2999        GPRReg op1TagGPR = op1.tagGPR();
3000        GPRReg op1PayloadGPR = op1.payloadGPR();
3001        GPRReg resultTagGPR = resultTag.gpr();
3002        GPRReg resultPayloadGPR = resultPayload.gpr();
3003
3004        op1.use();
3005
3006        if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean))) {
3007            m_jit.move(op1TagGPR, resultTagGPR);
3008            m_jit.move(op1PayloadGPR, resultPayloadGPR);
3009        } else {
3010            MacroAssembler::Jump alreadyPrimitive = branchNotCell(op1.jsValueRegs());
3011            MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureIDOffset()), MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()));
3012
3013            alreadyPrimitive.link(&m_jit);
3014            m_jit.move(op1TagGPR, resultTagGPR);
3015            m_jit.move(op1PayloadGPR, resultPayloadGPR);
3016
3017            addSlowPathGenerator(
3018                slowPathCall(
3019                    notPrimitive, this, operationToPrimitive,
3020                    JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR));
3021        }
3022
3023        jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
3024        break;
3025    }
3026
3027    case ToString: {
3028        if (node->child1().useKind() == UntypedUse) {
3029            JSValueOperand op1(this, node->child1());
3030            GPRReg op1PayloadGPR = op1.payloadGPR();
3031            GPRReg op1TagGPR = op1.tagGPR();
3032
3033            GPRResult result(this);
3034            GPRReg resultGPR = result.gpr();
3035
3036            flushRegisters();
3037
3038            JITCompiler::Jump done;
3039            if (node->child1()->prediction() & SpecString) {
3040                JITCompiler::Jump slowPath1 = branchNotCell(op1.jsValueRegs());
3041                JITCompiler::Jump slowPath2 = m_jit.branchPtr(
3042                    JITCompiler::NotEqual,
3043                    JITCompiler::Address(op1PayloadGPR, JSCell::structureIDOffset()),
3044                    TrustedImmPtr(m_jit.vm()->stringStructure.get()));
3045                m_jit.move(op1PayloadGPR, resultGPR);
3046                done = m_jit.jump();
3047                slowPath1.link(&m_jit);
3048                slowPath2.link(&m_jit);
3049            }
3050            callOperation(operationToString, resultGPR, op1TagGPR, op1PayloadGPR);
3051            if (done.isSet())
3052                done.link(&m_jit);
3053            cellResult(resultGPR, node);
3054            break;
3055        }
3056
3057        compileToStringOnCell(node);
3058        break;
3059    }
3060
3061    case NewStringObject: {
3062        compileNewStringObject(node);
3063        break;
3064    }
3065
3066    case NewArray: {
3067        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
3068        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
3069            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
3070            ASSERT(structure->indexingType() == node->indexingType());
3071            ASSERT(
3072                hasUndecided(structure->indexingType())
3073                || hasInt32(structure->indexingType())
3074                || hasDouble(structure->indexingType())
3075                || hasContiguous(structure->indexingType()));
3076
3077            unsigned numElements = node->numChildren();
3078
3079            GPRTemporary result(this);
3080            GPRTemporary storage(this);
3081
3082            GPRReg resultGPR = result.gpr();
3083            GPRReg storageGPR = storage.gpr();
3084
3085            emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
3086
3087            // At this point, one way or another, resultGPR and storageGPR have pointers to
3088            // the JSArray and the Butterfly, respectively.
3089
3090            ASSERT(!hasUndecided(structure->indexingType()) || !node->numChildren());
3091
3092            for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) {
3093                Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx];
3094                switch (node->indexingType()) {
3095                case ALL_BLANK_INDEXING_TYPES:
3096                case ALL_UNDECIDED_INDEXING_TYPES:
3097                    CRASH();
3098                    break;
3099                case ALL_DOUBLE_INDEXING_TYPES: {
3100                    SpeculateDoubleOperand operand(this, use);
3101                    FPRReg opFPR = operand.fpr();
3102                    DFG_TYPE_CHECK(
3103                        JSValueRegs(), use, SpecDoubleReal,
3104                        m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3105
3106                    m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
3107                    break;
3108                }
3109                case ALL_INT32_INDEXING_TYPES: {
3110                    SpeculateInt32Operand operand(this, use);
3111                    m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3112                    m_jit.store32(operand.gpr(), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3113                    break;
3114                }
3115                case ALL_CONTIGUOUS_INDEXING_TYPES: {
3116                    JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]);
3117                    GPRReg opTagGPR = operand.tagGPR();
3118                    GPRReg opPayloadGPR = operand.payloadGPR();
3119                    m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3120                    m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3121                    break;
3122                }
3123                default:
3124                    CRASH();
3125                    break;
3126                }
3127            }
3128
3129            // Yuck, we should *really* have a way of also returning the storageGPR. But
3130            // that's the least of what's wrong with this code. We really shouldn't be
3131            // allocating the array after having computed - and probably spilled to the
3132            // stack - all of the things that will go into the array. The solution to that
3133            // bigger problem will also likely fix the redundancy in reloading the storage
3134            // pointer that we currently have.
3135
3136            cellResult(resultGPR, node);
3137            break;
3138        }
3139
3140        if (!node->numChildren()) {
3141            flushRegisters();
3142            GPRResult result(this);
3143            callOperation(
3144                operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
3145            cellResult(result.gpr(), node);
3146            break;
3147        }
3148
3149        size_t scratchSize = sizeof(EncodedJSValue) * node->numChildren();
3150        ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize);
3151        EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
3152
3153        for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) {
3154            // Need to perform the speculations that this node promises to perform. If we're
3155            // emitting code here and the indexing type is not array storage then there is
3156            // probably something hilarious going on and we're already failing at all the
3157            // things, but at least we're going to be sound.
3158            Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx];
3159            switch (node->indexingType()) {
3160            case ALL_BLANK_INDEXING_TYPES:
3161            case ALL_UNDECIDED_INDEXING_TYPES:
3162                CRASH();
3163                break;
3164            case ALL_DOUBLE_INDEXING_TYPES: {
3165                SpeculateDoubleOperand operand(this, use);
3166                FPRReg opFPR = operand.fpr();
3167                DFG_TYPE_CHECK(
3168                    JSValueRegs(), use, SpecFullRealNumber,
3169                    m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3170
3171                m_jit.storeDouble(opFPR, TrustedImmPtr(reinterpret_cast<char*>(buffer + operandIdx)));
3172                break;
3173            }
3174            case ALL_INT32_INDEXING_TYPES: {
3175                SpeculateInt32Operand operand(this, use);
3176                GPRReg opGPR = operand.gpr();
3177                m_jit.store32(TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
3178                m_jit.store32(opGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
3179                break;
3180            }
3181            case ALL_CONTIGUOUS_INDEXING_TYPES:
3182            case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
3183                JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]);
3184                GPRReg opTagGPR = operand.tagGPR();
3185                GPRReg opPayloadGPR = operand.payloadGPR();
3186
3187                m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
3188                m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
3189                operand.use();
3190                break;
3191            }
3192            default:
3193                CRASH();
3194                break;
3195            }
3196        }
3197
3198        switch (node->indexingType()) {
3199        case ALL_DOUBLE_INDEXING_TYPES:
3200        case ALL_INT32_INDEXING_TYPES:
3201            useChildren(node);
3202            break;
3203        default:
3204            break;
3205        }
3206
3207        flushRegisters();
3208
3209        if (scratchSize) {
3210            GPRTemporary scratch(this);
3211
3212            // Tell GC mark phase how much of the scratch buffer is active during call.
3213            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3214            m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
3215        }
3216
3217        GPRResult result(this);
3218
3219        callOperation(
3220            operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
3221            static_cast<void*>(buffer), node->numChildren());
3222
3223        if (scratchSize) {
3224            GPRTemporary scratch(this);
3225
3226            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3227            m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
3228        }
3229
3230        cellResult(result.gpr(), node, UseChildrenCalledExplicitly);
3231        break;
3232    }
3233
3234    case NewArrayWithSize: {
3235        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
3236        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
3237            SpeculateStrictInt32Operand size(this, node->child1());
3238            GPRTemporary result(this);
3239            GPRTemporary storage(this);
3240            GPRTemporary scratch(this);
3241            GPRTemporary scratch2(this);
3242
3243            GPRReg sizeGPR = size.gpr();
3244            GPRReg resultGPR = result.gpr();
3245            GPRReg storageGPR = storage.gpr();
3246            GPRReg scratchGPR = scratch.gpr();
3247            GPRReg scratch2GPR = scratch2.gpr();
3248
3249            MacroAssembler::JumpList slowCases;
3250            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
3251
3252            ASSERT((1 << 3) == sizeof(JSValue));
3253            m_jit.move(sizeGPR, scratchGPR);
3254            m_jit.lshift32(TrustedImm32(3), scratchGPR);
3255            m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
3256            slowCases.append(
3257                emitAllocateBasicStorage(resultGPR, storageGPR));
3258            m_jit.subPtr(scratchGPR, storageGPR);
3259            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
3260            emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
3261
3262            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3263            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3264
3265            if (hasDouble(node->indexingType())) {
3266                JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
3267
3268                m_jit.move(sizeGPR, scratchGPR);
3269                MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
3270                MacroAssembler::Label loop = m_jit.label();
3271                m_jit.sub32(TrustedImm32(1), scratchGPR);
3272                m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3273                m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3274                m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit);
3275                done.link(&m_jit);
3276            }
3277
3278            addSlowPathGenerator(adoptPtr(
3279                new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
3280                    slowCases, this, operationNewArrayWithSize, resultGPR,
3281                    globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
3282                    globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
3283                    sizeGPR)));
3284
3285            cellResult(resultGPR, node);
3286            break;
3287        }
3288
3289        SpeculateStrictInt32Operand size(this, node->child1());
3290        GPRReg sizeGPR = size.gpr();
3291        flushRegisters();
3292        GPRResult result(this);
3293        GPRReg resultGPR = result.gpr();
3294        GPRReg structureGPR = selectScratchGPR(sizeGPR);
3295        MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX));
3296        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), structureGPR);
3297        MacroAssembler::Jump done = m_jit.jump();
3298        bigLength.link(&m_jit);
3299        m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR);
3300        done.link(&m_jit);
3301        callOperation(
3302            operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR);
3303        cellResult(resultGPR, node);
3304        break;
3305    }
3306
3307    case NewArrayBuffer: {
3308        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
3309        IndexingType indexingType = node->indexingType();
3310        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(indexingType)) {
3311            unsigned numElements = node->numConstants();
3312
3313            GPRTemporary result(this);
3314            GPRTemporary storage(this);
3315
3316            GPRReg resultGPR = result.gpr();
3317            GPRReg storageGPR = storage.gpr();
3318
3319            emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
3320
3321            if (node->indexingType() == ArrayWithDouble) {
3322                JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
3323                for (unsigned index = 0; index < node->numConstants(); ++index) {
3324                    union {
3325                        int32_t halves[2];
3326                        double value;
3327                    } u;
3328                    u.value = data[index].asNumber();
3329                    m_jit.store32(Imm32(u.halves[0]), MacroAssembler::Address(storageGPR, sizeof(double) * index));
3330                    m_jit.store32(Imm32(u.halves[1]), MacroAssembler::Address(storageGPR, sizeof(double) * index + sizeof(int32_t)));
3331                }
3332            } else {
3333                int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node->startConstant()));
3334                for (unsigned index = 0; index < node->numConstants() * 2; ++index) {
3335                    m_jit.store32(
3336                        Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index));
3337                }
3338            }
3339
3340            cellResult(resultGPR, node);
3341            break;
3342        }
3343
3344        flushRegisters();
3345        GPRResult result(this);
3346
3347        callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), node->startConstant(), node->numConstants());
3348
3349        cellResult(result.gpr(), node);
3350        break;
3351    }
3352
3353    case NewTypedArray: {
3354        switch (node->child1().useKind()) {
3355        case Int32Use:
3356            compileNewTypedArray(node);
3357            break;
3358        case UntypedUse: {
3359            JSValueOperand argument(this, node->child1());
3360            GPRReg argumentTagGPR = argument.tagGPR();
3361            GPRReg argumentPayloadGPR = argument.payloadGPR();
3362
3363            flushRegisters();
3364
3365            GPRResult result(this);
3366            GPRReg resultGPR = result.gpr();
3367
3368            JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
3369            callOperation(
3370                operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()),
3371                resultGPR, globalObject->typedArrayStructure(node->typedArrayType()),
3372                argumentTagGPR, argumentPayloadGPR);
3373
3374            cellResult(resultGPR, node);
3375            break;
3376        }
3377        default:
3378            RELEASE_ASSERT_NOT_REACHED();
3379            break;
3380        }
3381        break;
3382    }
3383
3384    case NewRegexp: {
3385        flushRegisters();
3386        GPRResult resultPayload(this);
3387        GPRResult2 resultTag(this);
3388
3389        callOperation(operationNewRegexp, resultTag.gpr(), resultPayload.gpr(), m_jit.codeBlock()->regexp(node->regexpIndex()));
3390
3391        // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
3392        cellResult(resultPayload.gpr(), node);
3393        break;
3394    }
3395
3396    case ToThis: {
3397        ASSERT(node->child1().useKind() == UntypedUse);
3398        JSValueOperand thisValue(this, node->child1());
3399        GPRTemporary temp(this);
3400        GPRTemporary tempTag(this);
3401        GPRReg thisValuePayloadGPR = thisValue.payloadGPR();
3402        GPRReg thisValueTagGPR = thisValue.tagGPR();
3403        GPRReg tempGPR = temp.gpr();
3404        GPRReg tempTagGPR = tempTag.gpr();
3405
3406        MacroAssembler::JumpList slowCases;
3407        slowCases.append(branchNotCell(thisValue.jsValueRegs()));
3408        slowCases.append(m_jit.branch8(
3409            MacroAssembler::NotEqual,
3410            MacroAssembler::Address(thisValuePayloadGPR, JSCell::typeInfoTypeOffset()),
3411            TrustedImm32(FinalObjectType)));
3412        m_jit.move(thisValuePayloadGPR, tempGPR);
3413        m_jit.move(thisValueTagGPR, tempTagGPR);
3414        J_JITOperation_EJ function;
3415        if (m_jit.graph().executableFor(node->origin.semantic)->isStrictMode())
3416            function = operationToThisStrict;
3417        else
3418            function = operationToThis;
3419        addSlowPathGenerator(
3420            slowPathCall(
3421                slowCases, this, function,
3422                JSValueRegs(tempTagGPR, tempGPR), thisValueTagGPR, thisValuePayloadGPR));
3423
3424        jsValueResult(tempTagGPR, tempGPR, node);
3425        break;
3426    }
3427
3428    case CreateThis: {
3429        // Note that there is not so much profit to speculate here. The only things we
3430        // speculate on are (1) that it's a cell, since that eliminates cell checks
3431        // later if the proto is reused, and (2) if we have a FinalObject prediction
3432        // then we speculate because we want to get recompiled if it isn't (since
3433        // otherwise we'd start taking slow path a lot).
3434
3435        SpeculateCellOperand callee(this, node->child1());
3436        GPRTemporary result(this);
3437        GPRTemporary allocator(this);
3438        GPRTemporary structure(this);
3439        GPRTemporary scratch(this);
3440
3441        GPRReg calleeGPR = callee.gpr();
3442        GPRReg resultGPR = result.gpr();
3443        GPRReg allocatorGPR = allocator.gpr();
3444        GPRReg structureGPR = structure.gpr();
3445        GPRReg scratchGPR = scratch.gpr();
3446
3447        MacroAssembler::JumpList slowPath;
3448
3449        m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR);
3450        m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR);
3451        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, allocatorGPR));
3452        emitAllocateJSObject(resultGPR, allocatorGPR, structureGPR, TrustedImmPtr(0), scratchGPR, slowPath);
3453
3454        addSlowPathGenerator(slowPathCall(slowPath, this, operationCreateThis, resultGPR, calleeGPR, node->inlineCapacity()));
3455
3456        cellResult(resultGPR, node);
3457        break;
3458    }
3459
3460    case AllocationProfileWatchpoint:
3461    case TypedArrayWatchpoint: {
3462        noResult(node);
3463        break;
3464    }
3465
3466    case NewObject: {
3467        GPRTemporary result(this);
3468        GPRTemporary allocator(this);
3469        GPRTemporary scratch(this);
3470
3471        GPRReg resultGPR = result.gpr();
3472        GPRReg allocatorGPR = allocator.gpr();
3473        GPRReg scratchGPR = scratch.gpr();
3474
3475        MacroAssembler::JumpList slowPath;
3476
3477        Structure* structure = node->structure();
3478        size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
3479        MarkedAllocator* allocatorPtr = &m_jit.vm()->heap.allocatorForObjectWithoutDestructor(allocationSize);
3480
3481        m_jit.move(TrustedImmPtr(allocatorPtr), allocatorGPR);
3482        emitAllocateJSObject(resultGPR, allocatorGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR, slowPath);
3483
3484        addSlowPathGenerator(slowPathCall(slowPath, this, operationNewObject, resultGPR, structure));
3485
3486        cellResult(resultGPR, node);
3487        break;
3488    }
3489
3490    case GetCallee: {
3491        GPRTemporary result(this);
3492        m_jit.loadPtr(JITCompiler::payloadFor(JSStack::Callee), result.gpr());
3493        cellResult(result.gpr(), node);
3494        break;
3495    }
3496
3497    case GetScope: {
3498        SpeculateCellOperand function(this, node->child1());
3499        GPRTemporary result(this, Reuse, function);
3500        m_jit.loadPtr(JITCompiler::Address(function.gpr(), JSFunction::offsetOfScopeChain()), result.gpr());
3501        cellResult(result.gpr(), node);
3502        break;
3503    }
3504
3505    case GetMyScope: {
3506        GPRTemporary result(this);
3507        GPRReg resultGPR = result.gpr();
3508
3509        m_jit.loadPtr(JITCompiler::payloadFor(JSStack::ScopeChain), resultGPR);
3510        cellResult(resultGPR, node);
3511        break;
3512    }
3513
3514    case SkipTopScope: {
3515        SpeculateCellOperand scope(this, node->child1());
3516        GPRTemporary result(this, Reuse, scope);
3517        GPRReg resultGPR = result.gpr();
3518        m_jit.move(scope.gpr(), resultGPR);
3519        JITCompiler::Jump activationNotCreated =
3520            m_jit.branchTestPtr(
3521                JITCompiler::Zero,
3522                JITCompiler::payloadFor(
3523                    static_cast<VirtualRegister>(m_jit.graph().machineActivationRegister())));
3524        m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
3525        activationNotCreated.link(&m_jit);
3526        cellResult(resultGPR, node);
3527        break;
3528    }
3529
3530    case SkipScope: {
3531        SpeculateCellOperand scope(this, node->child1());
3532        GPRTemporary result(this, Reuse, scope);
3533        m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSScope::offsetOfNext()), result.gpr());
3534        cellResult(result.gpr(), node);
3535        break;
3536    }
3537
3538    case GetClosureRegisters: {
3539        if (WriteBarrierBase<Unknown>* registers = m_jit.graph().tryGetRegisters(node->child1().node())) {
3540            GPRTemporary result(this);
3541            GPRReg resultGPR = result.gpr();
3542            m_jit.move(TrustedImmPtr(registers), resultGPR);
3543            storageResult(resultGPR, node);
3544            break;
3545        }
3546
3547        SpeculateCellOperand scope(this, node->child1());
3548        GPRTemporary result(this);
3549        GPRReg scopeGPR = scope.gpr();
3550        GPRReg resultGPR = result.gpr();
3551
3552        m_jit.loadPtr(JITCompiler::Address(scopeGPR, JSVariableObject::offsetOfRegisters()), resultGPR);
3553        storageResult(resultGPR, node);
3554        break;
3555    }
3556    case GetClosureVar: {
3557        StorageOperand registers(this, node->child1());
3558        GPRTemporary resultTag(this);
3559        GPRTemporary resultPayload(this);
3560        GPRReg registersGPR = registers.gpr();
3561        GPRReg resultTagGPR = resultTag.gpr();
3562        GPRReg resultPayloadGPR = resultPayload.gpr();
3563        m_jit.load32(JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
3564        m_jit.load32(JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3565        jsValueResult(resultTagGPR, resultPayloadGPR, node);
3566        break;
3567    }
3568    case PutClosureVar: {
3569        StorageOperand registers(this, node->child2());
3570        JSValueOperand value(this, node->child3());
3571        GPRTemporary scratchRegister(this);
3572
3573        GPRReg registersGPR = registers.gpr();
3574        GPRReg valueTagGPR = value.tagGPR();
3575        GPRReg valuePayloadGPR = value.payloadGPR();
3576
3577        speculate(node, node->child1());
3578
3579        m_jit.store32(valueTagGPR, JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
3580        m_jit.store32(valuePayloadGPR, JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
3581        noResult(node);
3582        break;
3583    }
3584
3585    case GetById: {
3586        ASSERT(node->prediction());
3587
3588        switch (node->child1().useKind()) {
3589        case CellUse: {
3590            SpeculateCellOperand base(this, node->child1());
3591            GPRTemporary resultTag(this);
3592            GPRTemporary resultPayload(this, Reuse, base);
3593
3594            GPRReg baseGPR = base.gpr();
3595            GPRReg resultTagGPR = resultTag.gpr();
3596            GPRReg resultPayloadGPR = resultPayload.gpr();
3597
3598            base.use();
3599
3600            cachedGetById(node->origin.semantic, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber());
3601
3602            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
3603            break;
3604        }
3605
3606        case UntypedUse: {
3607            JSValueOperand base(this, node->child1());
3608            GPRTemporary resultTag(this);
3609            GPRTemporary resultPayload(this, Reuse, base, TagWord);
3610
3611            GPRReg baseTagGPR = base.tagGPR();
3612            GPRReg basePayloadGPR = base.payloadGPR();
3613            GPRReg resultTagGPR = resultTag.gpr();
3614            GPRReg resultPayloadGPR = resultPayload.gpr();
3615
3616            base.use();
3617
3618            JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs());
3619
3620            cachedGetById(node->origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell);
3621
3622            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
3623            break;
3624        }
3625
3626        default:
3627            RELEASE_ASSERT_NOT_REACHED();
3628            break;
3629        }
3630        break;
3631    }
3632
3633    case GetByIdFlush: {
3634        if (!node->prediction()) {
3635            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
3636            break;
3637        }
3638
3639        switch (node->child1().useKind()) {
3640        case CellUse: {
3641            SpeculateCellOperand base(this, node->child1());
3642
3643            GPRReg baseGPR = base.gpr();
3644
3645            GPRResult resultPayload(this);
3646            GPRResult2 resultTag(this);
3647            GPRReg resultPayloadGPR = resultPayload.gpr();
3648            GPRReg resultTagGPR = resultTag.gpr();
3649
3650            base.use();
3651
3652            flushRegisters();
3653
3654            cachedGetById(node->origin.semantic, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), JITCompiler::Jump(), DontSpill);
3655
3656            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
3657            break;
3658        }
3659
3660        case UntypedUse: {
3661            JSValueOperand base(this, node->child1());
3662            GPRReg baseTagGPR = base.tagGPR();
3663            GPRReg basePayloadGPR = base.payloadGPR();
3664
3665            GPRResult resultPayload(this);
3666            GPRResult2 resultTag(this);
3667            GPRReg resultPayloadGPR = resultPayload.gpr();
3668            GPRReg resultTagGPR = resultTag.gpr();
3669
3670            base.use();
3671
3672            flushRegisters();
3673
3674            JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs());
3675
3676            cachedGetById(node->origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell, DontSpill);
3677
3678            jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
3679            break;
3680        }
3681
3682        default:
3683            RELEASE_ASSERT_NOT_REACHED();
3684            break;
3685        }
3686        break;
3687    }
3688
3689    case GetArrayLength:
3690        compileGetArrayLength(node);
3691        break;
3692
3693    case CheckFunction: {
3694        SpeculateCellOperand function(this, node->child1());
3695        speculationCheck(BadFunction, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node->function()));
3696        noResult(node);
3697        break;
3698    }
3699
3700    case CheckExecutable: {
3701        SpeculateCellOperand function(this, node->child1());
3702        speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node->executable()));
3703        noResult(node);
3704        break;
3705    }
3706
3707    case CheckStructure: {
3708        SpeculateCellOperand base(this, node->child1());
3709
3710        ASSERT(node->structureSet().size());
3711
3712        if (node->structureSet().size() == 1) {
3713            speculationCheck(
3714                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3715                m_jit.branchWeakPtr(
3716                    JITCompiler::NotEqual,
3717                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
3718                    node->structureSet()[0]));
3719        } else {
3720            GPRTemporary structure(this);
3721
3722            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), structure.gpr());
3723
3724            JITCompiler::JumpList done;
3725
3726            for (size_t i = 0; i < node->structureSet().size() - 1; ++i)
3727                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node->structureSet()[i]));
3728
3729            speculationCheck(
3730                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
3731                m_jit.branchWeakPtr(
3732                    JITCompiler::NotEqual, structure.gpr(), node->structureSet().last()));
3733
3734            done.link(&m_jit);
3735        }
3736
3737        noResult(node);
3738        break;
3739    }
3740
3741    case StructureTransitionWatchpoint: {
3742        // There is a fascinating question here of what to do about array profiling.
3743        // We *could* try to tell the OSR exit about where the base of the access is.
3744        // The DFG will have kept it alive, though it may not be in a register, and
3745        // we shouldn't really load it since that could be a waste. For now though,
3746        // we'll just rely on the fact that when a watchpoint fires then that's
3747        // quite a hint already.
3748
3749        m_jit.addWeakReference(node->structure());
3750
3751#if !ASSERT_DISABLED
3752        SpeculateCellOperand op1(this, node->child1());
3753        JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureIDOffset()), TrustedImmPtr(node->structure()));
3754        m_jit.abortWithReason(DFGIneffectiveWatchpoint);
3755        isOK.link(&m_jit);
3756#else
3757        speculateCell(node->child1());
3758#endif
3759
3760        noResult(node);
3761        break;
3762    }
3763
3764    case PhantomPutStructure: {
3765        ASSERT(isKnownCell(node->child1().node()));
3766        m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3767        noResult(node);
3768        break;
3769    }
3770
3771    case PutStructure: {
3772        m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3773
3774        SpeculateCellOperand base(this, node->child1());
3775        GPRReg baseGPR = base.gpr();
3776
3777        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node->structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3778
3779        noResult(node);
3780        break;
3781    }
3782
3783    case AllocatePropertyStorage:
3784        compileAllocatePropertyStorage(node);
3785        break;
3786
3787    case ReallocatePropertyStorage:
3788        compileReallocatePropertyStorage(node);
3789        break;
3790
3791    case GetButterfly: {
3792        SpeculateCellOperand base(this, node->child1());
3793        GPRTemporary result(this, Reuse, base);
3794
3795        GPRReg baseGPR = base.gpr();
3796        GPRReg resultGPR = result.gpr();
3797
3798        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), resultGPR);
3799
3800        storageResult(resultGPR, node);
3801        break;
3802    }
3803
3804    case GetIndexedPropertyStorage: {
3805        compileGetIndexedPropertyStorage(node);
3806        break;
3807    }
3808
3809    case ConstantStoragePointer: {
3810        compileConstantStoragePointer(node);
3811        break;
3812    }
3813
3814    case GetTypedArrayByteOffset: {
3815        compileGetTypedArrayByteOffset(node);
3816        break;
3817    }
3818
3819    case GetByOffset: {
3820        StorageOperand storage(this, node->child1());
3821        GPRTemporary resultTag(this, Reuse, storage);
3822        GPRTemporary resultPayload(this);
3823
3824        GPRReg storageGPR = storage.gpr();
3825        GPRReg resultTagGPR = resultTag.gpr();
3826        GPRReg resultPayloadGPR = resultPayload.gpr();
3827
3828        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node->storageAccessDataIndex()];
3829
3830        m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3831        m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
3832
3833        jsValueResult(resultTagGPR, resultPayloadGPR, node);
3834        break;
3835    }
3836
3837    case PutByOffset: {
3838        StorageOperand storage(this, node->child1());
3839        JSValueOperand value(this, node->child3());
3840
3841        GPRReg storageGPR = storage.gpr();
3842        GPRReg valueTagGPR = value.tagGPR();
3843        GPRReg valuePayloadGPR = value.payloadGPR();
3844
3845        speculate(node, node->child2());
3846
3847        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node->storageAccessDataIndex()];
3848
3849        m_jit.storePtr(valueTagGPR, JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
3850        m_jit.storePtr(valuePayloadGPR, JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
3851
3852        noResult(node);
3853        break;
3854    }
3855
3856    case PutByIdFlush: {
3857        SpeculateCellOperand base(this, node->child1());
3858        JSValueOperand value(this, node->child2());
3859        GPRTemporary scratch(this);
3860
3861        GPRReg baseGPR = base.gpr();
3862        GPRReg valueTagGPR = value.tagGPR();
3863        GPRReg valuePayloadGPR = value.payloadGPR();
3864        GPRReg scratchGPR = scratch.gpr();
3865        flushRegisters();
3866
3867        cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill);
3868
3869        noResult(node);
3870        break;
3871    }
3872
3873    case PutById: {
3874        SpeculateCellOperand base(this, node->child1());
3875        JSValueOperand value(this, node->child2());
3876        GPRTemporary scratch(this);
3877
3878        GPRReg baseGPR = base.gpr();
3879        GPRReg valueTagGPR = value.tagGPR();
3880        GPRReg valuePayloadGPR = value.payloadGPR();
3881        GPRReg scratchGPR = scratch.gpr();
3882
3883        cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect);
3884
3885        noResult(node);
3886        break;
3887    }
3888
3889    case PutByIdDirect: {
3890        SpeculateCellOperand base(this, node->child1());
3891        JSValueOperand value(this, node->child2());
3892        GPRTemporary scratch(this);
3893
3894        GPRReg baseGPR = base.gpr();
3895        GPRReg valueTagGPR = value.tagGPR();
3896        GPRReg valuePayloadGPR = value.payloadGPR();
3897        GPRReg scratchGPR = scratch.gpr();
3898
3899        cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), Direct);
3900
3901        noResult(node);
3902        break;
3903    }
3904
3905    case GetGlobalVar: {
3906        GPRTemporary resultPayload(this);
3907        GPRTemporary resultTag(this);
3908
3909        m_jit.move(TrustedImmPtr(node->registerPointer()), resultPayload.gpr());
3910        m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTag.gpr());
3911        m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayload.gpr());
3912
3913        jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
3914        break;
3915    }
3916
3917    case PutGlobalVar: {
3918        JSValueOperand value(this, node->child1());
3919
3920        // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have
3921        // a spare register - a good optimization would be to put the register pointer into
3922        // a register and then do a zero offset store followed by a four-offset store (or
3923        // vice-versa depending on endianness).
3924        m_jit.store32(value.tagGPR(), node->registerPointer()->tagPointer());
3925        m_jit.store32(value.payloadGPR(), node->registerPointer()->payloadPointer());
3926
3927        noResult(node);
3928        break;
3929    }
3930
3931    case NotifyWrite: {
3932        VariableWatchpointSet* set = node->variableWatchpointSet();
3933
3934        JSValueOperand value(this, node->child1());
3935        GPRReg valueTagGPR = value.tagGPR();
3936        GPRReg valuePayloadGPR = value.payloadGPR();
3937
3938        GPRTemporary temp(this);
3939        GPRReg tempGPR = temp.gpr();
3940
3941        m_jit.load8(set->addressOfState(), tempGPR);
3942
3943        JITCompiler::Jump isDone = m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated));
3944        JITCompiler::JumpList notifySlow;
3945        notifySlow.append(m_jit.branch32(
3946            JITCompiler::NotEqual,
3947            JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()),
3948            valuePayloadGPR));
3949        notifySlow.append(m_jit.branch32(
3950            JITCompiler::NotEqual,
3951            JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->tagPointer()),
3952            valueTagGPR));
3953        addSlowPathGenerator(
3954            slowPathCall(notifySlow, this, operationNotifyWrite, NoResult, set, valueTagGPR, valuePayloadGPR));
3955        isDone.link(&m_jit);
3956
3957        noResult(node);
3958        break;
3959    }
3960
3961    case VarInjectionWatchpoint:
3962    case VariableWatchpoint: {
3963        noResult(node);
3964        break;
3965    }
3966
3967    case CheckHasInstance: {
3968        SpeculateCellOperand base(this, node->child1());
3969        GPRTemporary structure(this);
3970
3971        // Speculate that base 'ImplementsDefaultHasInstance'.
3972        speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest8(
3973            MacroAssembler::Zero,
3974            MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()),
3975            MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
3976
3977        noResult(node);
3978        break;
3979    }
3980
3981    case InstanceOf: {
3982        compileInstanceOf(node);
3983        break;
3984    }
3985
3986    case IsUndefined: {
3987        JSValueOperand value(this, node->child1());
3988        GPRTemporary result(this);
3989        GPRTemporary localGlobalObject(this);
3990        GPRTemporary remoteGlobalObject(this);
3991
3992        JITCompiler::Jump isCell = branchIsCell(value.jsValueRegs());
3993
3994        m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
3995        JITCompiler::Jump done = m_jit.jump();
3996
3997        isCell.link(&m_jit);
3998        JITCompiler::Jump notMasqueradesAsUndefined;
3999        if (masqueradesAsUndefinedWatchpointIsStillValid()) {
4000            m_jit.move(TrustedImm32(0), result.gpr());
4001            notMasqueradesAsUndefined = m_jit.jump();
4002        } else {
4003            JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
4004                JITCompiler::NonZero,
4005                JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()),
4006                TrustedImm32(MasqueradesAsUndefined));
4007            m_jit.move(TrustedImm32(0), result.gpr());
4008            notMasqueradesAsUndefined = m_jit.jump();
4009
4010            isMasqueradesAsUndefined.link(&m_jit);
4011            GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
4012            GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
4013            m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
4014            m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
4015            m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR);
4016            m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
4017        }
4018
4019        notMasqueradesAsUndefined.link(&m_jit);
4020        done.link(&m_jit);
4021        booleanResult(result.gpr(), node);
4022        break;
4023    }
4024
4025    case IsBoolean: {
4026        JSValueOperand value(this, node->child1());
4027        GPRTemporary result(this, Reuse, value, TagWord);
4028
4029        m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
4030        booleanResult(result.gpr(), node);
4031        break;
4032    }
4033
4034    case IsNumber: {
4035        JSValueOperand value(this, node->child1());
4036        GPRTemporary result(this, Reuse, value, TagWord);
4037
4038        m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
4039        m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
4040        booleanResult(result.gpr(), node);
4041        break;
4042    }
4043
4044    case IsString: {
4045        JSValueOperand value(this, node->child1());
4046        GPRTemporary result(this, Reuse, value, TagWord);
4047
4048        JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs());
4049
4050        m_jit.compare8(JITCompiler::Equal,
4051            JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()),
4052            TrustedImm32(StringType),
4053            result.gpr());
4054        JITCompiler::Jump done = m_jit.jump();
4055
4056        isNotCell.link(&m_jit);
4057        m_jit.move(TrustedImm32(0), result.gpr());
4058
4059        done.link(&m_jit);
4060        booleanResult(result.gpr(), node);
4061        break;
4062    }
4063
4064    case IsObject: {
4065        JSValueOperand value(this, node->child1());
4066        GPRReg valueTagGPR = value.tagGPR();
4067        GPRReg valuePayloadGPR = value.payloadGPR();
4068        GPRResult result(this);
4069        GPRReg resultGPR = result.gpr();
4070        flushRegisters();
4071        callOperation(operationIsObject, resultGPR, valueTagGPR, valuePayloadGPR);
4072        booleanResult(result.gpr(), node);
4073        break;
4074    }
4075
4076    case IsFunction: {
4077        JSValueOperand value(this, node->child1());
4078        GPRReg valueTagGPR = value.tagGPR();
4079        GPRReg valuePayloadGPR = value.payloadGPR();
4080        GPRResult result(this);
4081        GPRReg resultGPR = result.gpr();
4082        flushRegisters();
4083        callOperation(operationIsFunction, resultGPR, valueTagGPR, valuePayloadGPR);
4084        booleanResult(result.gpr(), node);
4085        break;
4086    }
4087    case TypeOf: {
4088        JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
4089        GPRReg tagGPR = value.tagGPR();
4090        GPRReg payloadGPR = value.payloadGPR();
4091        GPRTemporary temp(this);
4092        GPRReg tempGPR = temp.gpr();
4093        GPRResult result(this);
4094        GPRReg resultGPR = result.gpr();
4095        JITCompiler::JumpList doneJumps;
4096
4097        flushRegisters();
4098
4099        ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == CellUse || node->child1().useKind() == StringUse);
4100
4101        JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs());
4102        if (node->child1().useKind() != UntypedUse)
4103            DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecCell, isNotCell);
4104
4105        if (!node->child1()->shouldSpeculateObject() || node->child1().useKind() == StringUse) {
4106            JITCompiler::Jump notString = m_jit.branch8(
4107                JITCompiler::NotEqual,
4108                JITCompiler::Address(payloadGPR, JSCell::typeInfoTypeOffset()),
4109                TrustedImm32(StringType));
4110            if (node->child1().useKind() == StringUse)
4111                DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecString, notString);
4112            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.stringString()), resultGPR);
4113            doneJumps.append(m_jit.jump());
4114            if (node->child1().useKind() != StringUse) {
4115                notString.link(&m_jit);
4116                callOperation(operationTypeOf, resultGPR, payloadGPR);
4117                doneJumps.append(m_jit.jump());
4118            }
4119        } else {
4120            callOperation(operationTypeOf, resultGPR, payloadGPR);
4121            doneJumps.append(m_jit.jump());
4122        }
4123
4124        if (node->child1().useKind() == UntypedUse) {
4125            isNotCell.link(&m_jit);
4126
4127            m_jit.add32(TrustedImm32(1), tagGPR, tempGPR);
4128            JITCompiler::Jump notNumber = m_jit.branch32(JITCompiler::AboveOrEqual, tempGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
4129            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.numberString()), resultGPR);
4130            doneJumps.append(m_jit.jump());
4131            notNumber.link(&m_jit);
4132
4133            JITCompiler::Jump notUndefined = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::UndefinedTag));
4134            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.undefinedString()), resultGPR);
4135            doneJumps.append(m_jit.jump());
4136            notUndefined.link(&m_jit);
4137
4138            JITCompiler::Jump notNull = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::NullTag));
4139            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.objectString()), resultGPR);
4140            doneJumps.append(m_jit.jump());
4141            notNull.link(&m_jit);
4142
4143            // Only boolean left
4144            m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.booleanString()), resultGPR);
4145        }
4146        doneJumps.link(&m_jit);
4147        cellResult(resultGPR, node);
4148        break;
4149    }
4150
4151    case Flush:
4152        break;
4153
4154    case Call:
4155    case Construct:
4156        emitCall(node);
4157        break;
4158
4159    case CreateActivation: {
4160        JSValueOperand value(this, node->child1());
4161        GPRTemporary result(this, Reuse, value, PayloadWord);
4162
4163        GPRReg valueTagGPR = value.tagGPR();
4164        GPRReg valuePayloadGPR = value.payloadGPR();
4165        GPRReg resultGPR = result.gpr();
4166
4167        m_jit.move(valuePayloadGPR, resultGPR);
4168
4169        JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4170
4171        addSlowPathGenerator(
4172            slowPathCall(
4173                notCreated, this, operationCreateActivation, resultGPR,
4174                framePointerOffsetToGetActivationRegisters()));
4175
4176        cellResult(resultGPR, node);
4177        break;
4178    }
4179
4180    case FunctionReentryWatchpoint: {
4181        noResult(node);
4182        break;
4183    }
4184
4185    case CreateArguments: {
4186        JSValueOperand value(this, node->child1());
4187        GPRTemporary scratch1(this);
4188        GPRTemporary scratch2(this);
4189        GPRTemporary result(this, Reuse, value, PayloadWord);
4190
4191        GPRReg valueTagGPR = value.tagGPR();
4192        GPRReg valuePayloadGPR = value.payloadGPR();
4193        GPRReg scratch1GPR = scratch1.gpr();
4194        GPRReg scratch2GPR = scratch2.gpr();
4195        GPRReg resultGPR = result.gpr();
4196
4197        m_jit.move(valuePayloadGPR, resultGPR);
4198
4199        if (node->origin.semantic.inlineCallFrame) {
4200            JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4201            addSlowPathGenerator(
4202                slowPathCall(
4203                    notCreated, this, operationCreateInlinedArguments, resultGPR,
4204                    node->origin.semantic.inlineCallFrame));
4205            cellResult(resultGPR, node);
4206            break;
4207        }
4208
4209        FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic));
4210        if (m_jit.codeBlock()->hasSlowArguments()
4211            || executable->isStrictMode()
4212            || !executable->parameterCount()) {
4213            JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4214            addSlowPathGenerator(
4215                slowPathCall(notCreated, this, operationCreateArguments, resultGPR));
4216            cellResult(resultGPR, node);
4217            break;
4218        }
4219
4220        JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4221
4222        MacroAssembler::JumpList slowPaths;
4223        emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths);
4224            addSlowPathGenerator(
4225                slowPathCall(slowPaths, this, operationCreateArguments, resultGPR));
4226
4227        alreadyCreated.link(&m_jit);
4228        cellResult(resultGPR, node);
4229        break;
4230    }
4231
4232    case TearOffActivation: {
4233        JSValueOperand activationValue(this, node->child1());
4234        GPRTemporary scratch(this);
4235
4236        GPRReg activationValueTagGPR = activationValue.tagGPR();
4237        GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
4238        GPRReg scratchGPR = scratch.gpr();
4239
4240        JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4241
4242        SymbolTable* symbolTable = m_jit.symbolTableFor(node->origin.semantic);
4243        int registersOffset = JSActivation::registersOffset(symbolTable);
4244
4245        int bytecodeCaptureStart = symbolTable->captureStart();
4246        int machineCaptureStart = m_jit.graph().m_machineCaptureStart;
4247        for (int i = symbolTable->captureCount(); i--;) {
4248            m_jit.loadPtr(
4249                JITCompiler::Address(
4250                    GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
4251                scratchGPR);
4252            m_jit.storePtr(
4253                scratchGPR, JITCompiler::Address(
4254                    activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
4255            m_jit.loadPtr(
4256                JITCompiler::Address(
4257                    GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
4258                scratchGPR);
4259            m_jit.storePtr(
4260                scratchGPR, JITCompiler::Address(
4261                    activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
4262        }
4263        m_jit.addPtr(TrustedImm32(registersOffset), activationValuePayloadGPR, scratchGPR);
4264        m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValuePayloadGPR, JSActivation::offsetOfRegisters()));
4265
4266        notCreated.link(&m_jit);
4267        noResult(node);
4268        break;
4269    }
4270
4271    case TearOffArguments: {
4272        JSValueOperand unmodifiedArgumentsValue(this, node->child1());
4273        JSValueOperand activationValue(this, node->child2());
4274        GPRReg unmodifiedArgumentsValuePayloadGPR = unmodifiedArgumentsValue.payloadGPR();
4275        GPRReg activationValuePayloadGPR = activationValue.payloadGPR();
4276
4277        JITCompiler::Jump created = m_jit.branchTest32(
4278            JITCompiler::NonZero, unmodifiedArgumentsValuePayloadGPR);
4279
4280        if (node->origin.semantic.inlineCallFrame) {
4281            addSlowPathGenerator(
4282                slowPathCall(
4283                    created, this, operationTearOffInlinedArguments, NoResult,
4284                    unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR, node->origin.semantic.inlineCallFrame));
4285        } else {
4286            addSlowPathGenerator(
4287                slowPathCall(
4288                    created, this, operationTearOffArguments, NoResult,
4289                    unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR));
4290        }
4291
4292        noResult(node);
4293        break;
4294    }
4295
4296    case CheckArgumentsNotCreated: {
4297        ASSERT(!isEmptySpeculation(
4298            m_state.variables().operand(
4299                m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type));
4300        speculationCheck(
4301            Uncountable, JSValueRegs(), 0,
4302            m_jit.branch32(
4303                JITCompiler::NotEqual,
4304                JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)),
4305                TrustedImm32(JSValue::EmptyValueTag)));
4306        noResult(node);
4307        break;
4308    }
4309
4310    case GetMyArgumentsLength: {
4311        GPRTemporary result(this);
4312        GPRReg resultGPR = result.gpr();
4313
4314        if (!isEmptySpeculation(
4315                m_state.variables().operand(
4316                    m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) {
4317            speculationCheck(
4318                ArgumentsEscaped, JSValueRegs(), 0,
4319                m_jit.branch32(
4320                    JITCompiler::NotEqual,
4321                    JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)),
4322                    TrustedImm32(JSValue::EmptyValueTag)));
4323        }
4324
4325        ASSERT(!node->origin.semantic.inlineCallFrame);
4326        m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
4327        m_jit.sub32(TrustedImm32(1), resultGPR);
4328        int32Result(resultGPR, node);
4329        break;
4330    }
4331
4332    case GetMyArgumentsLengthSafe: {
4333        GPRTemporary resultPayload(this);
4334        GPRTemporary resultTag(this);
4335        GPRReg resultPayloadGPR = resultPayload.gpr();
4336        GPRReg resultTagGPR = resultTag.gpr();
4337
4338        JITCompiler::Jump created = m_jit.branch32(
4339            JITCompiler::NotEqual,
4340            JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)),
4341            TrustedImm32(JSValue::EmptyValueTag));
4342
4343        if (node->origin.semantic.inlineCallFrame) {
4344            m_jit.move(
4345                Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1),
4346                resultPayloadGPR);
4347        } else {
4348            m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultPayloadGPR);
4349            m_jit.sub32(TrustedImm32(1), resultPayloadGPR);
4350        }
4351        m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
4352
4353        // FIXME: the slow path generator should perform a forward speculation that the
4354        // result is an integer. For now we postpone the speculation by having this return
4355        // a JSValue.
4356
4357        addSlowPathGenerator(
4358            slowPathCall(
4359                created, this, operationGetArgumentsLength,
4360                JSValueRegs(resultTagGPR, resultPayloadGPR),
4361                m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset()));
4362
4363        jsValueResult(resultTagGPR, resultPayloadGPR, node);
4364        break;
4365    }
4366
4367    case GetMyArgumentByVal: {
4368        SpeculateStrictInt32Operand index(this, node->child1());
4369        GPRTemporary resultPayload(this);
4370        GPRTemporary resultTag(this);
4371        GPRReg indexGPR = index.gpr();
4372        GPRReg resultPayloadGPR = resultPayload.gpr();
4373        GPRReg resultTagGPR = resultTag.gpr();
4374
4375        if (!isEmptySpeculation(
4376                m_state.variables().operand(
4377                    m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) {
4378            speculationCheck(
4379                ArgumentsEscaped, JSValueRegs(), 0,
4380                m_jit.branch32(
4381                    JITCompiler::NotEqual,
4382                    JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)),
4383                    TrustedImm32(JSValue::EmptyValueTag)));
4384        }
4385
4386        m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR);
4387
4388        if (node->origin.semantic.inlineCallFrame) {
4389            speculationCheck(
4390                Uncountable, JSValueRegs(), 0,
4391                m_jit.branch32(
4392                    JITCompiler::AboveOrEqual,
4393                    resultPayloadGPR,
4394                    Imm32(node->origin.semantic.inlineCallFrame->arguments.size())));
4395        } else {
4396            speculationCheck(
4397                Uncountable, JSValueRegs(), 0,
4398                m_jit.branch32(
4399                    JITCompiler::AboveOrEqual,
4400                    resultPayloadGPR,
4401                    JITCompiler::payloadFor(JSStack::ArgumentCount)));
4402        }
4403
4404        JITCompiler::JumpList slowArgument;
4405        JITCompiler::JumpList slowArgumentOutOfBounds;
4406        if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
4407            RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
4408            const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
4409            slowArgumentOutOfBounds.append(
4410                m_jit.branch32(
4411                    JITCompiler::AboveOrEqual, indexGPR,
4412                    Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount())));
4413
4414            COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes);
4415            m_jit.move(ImmPtr(slowArguments), resultPayloadGPR);
4416            m_jit.load32(
4417                JITCompiler::BaseIndex(
4418                    resultPayloadGPR, indexGPR, JITCompiler::TimesEight,
4419                    OBJECT_OFFSETOF(SlowArgument, index)),
4420                resultPayloadGPR);
4421
4422            m_jit.load32(
4423                JITCompiler::BaseIndex(
4424                    GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4425                    OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
4426                resultTagGPR);
4427            m_jit.load32(
4428                JITCompiler::BaseIndex(
4429                    GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4430                    OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
4431                resultPayloadGPR);
4432            slowArgument.append(m_jit.jump());
4433        }
4434        slowArgumentOutOfBounds.link(&m_jit);
4435
4436        m_jit.load32(
4437            JITCompiler::BaseIndex(
4438                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4439                m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
4440            resultTagGPR);
4441        m_jit.load32(
4442            JITCompiler::BaseIndex(
4443                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4444                m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
4445            resultPayloadGPR);
4446
4447        slowArgument.link(&m_jit);
4448        jsValueResult(resultTagGPR, resultPayloadGPR, node);
4449        break;
4450    }
4451    case GetMyArgumentByValSafe: {
4452        SpeculateStrictInt32Operand index(this, node->child1());
4453        GPRTemporary resultPayload(this);
4454        GPRTemporary resultTag(this);
4455        GPRReg indexGPR = index.gpr();
4456        GPRReg resultPayloadGPR = resultPayload.gpr();
4457        GPRReg resultTagGPR = resultTag.gpr();
4458
4459        JITCompiler::JumpList slowPath;
4460        slowPath.append(
4461            m_jit.branch32(
4462                JITCompiler::NotEqual,
4463                JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)),
4464                TrustedImm32(JSValue::EmptyValueTag)));
4465
4466        m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR);
4467        if (node->origin.semantic.inlineCallFrame) {
4468            slowPath.append(
4469                m_jit.branch32(
4470                    JITCompiler::AboveOrEqual,
4471                    resultPayloadGPR,
4472                    Imm32(node->origin.semantic.inlineCallFrame->arguments.size())));
4473        } else {
4474            slowPath.append(
4475                m_jit.branch32(
4476                    JITCompiler::AboveOrEqual,
4477                    resultPayloadGPR,
4478                    JITCompiler::payloadFor(JSStack::ArgumentCount)));
4479        }
4480
4481        JITCompiler::JumpList slowArgument;
4482        JITCompiler::JumpList slowArgumentOutOfBounds;
4483        if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
4484            RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
4485            const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
4486            slowArgumentOutOfBounds.append(
4487                m_jit.branch32(
4488                    JITCompiler::AboveOrEqual, indexGPR,
4489                    Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount())));
4490
4491            COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes);
4492            m_jit.move(ImmPtr(slowArguments), resultPayloadGPR);
4493            m_jit.load32(
4494                JITCompiler::BaseIndex(
4495                    resultPayloadGPR, indexGPR, JITCompiler::TimesEight,
4496                    OBJECT_OFFSETOF(SlowArgument, index)),
4497                resultPayloadGPR);
4498            m_jit.load32(
4499                JITCompiler::BaseIndex(
4500                    GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4501                    OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
4502                resultTagGPR);
4503            m_jit.load32(
4504                JITCompiler::BaseIndex(
4505                    GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4506                    OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
4507                resultPayloadGPR);
4508            slowArgument.append(m_jit.jump());
4509        }
4510        slowArgumentOutOfBounds.link(&m_jit);
4511
4512        m_jit.load32(
4513            JITCompiler::BaseIndex(
4514                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4515                m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
4516            resultTagGPR);
4517        m_jit.load32(
4518            JITCompiler::BaseIndex(
4519                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
4520                m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
4521            resultPayloadGPR);
4522
4523        if (node->origin.semantic.inlineCallFrame) {
4524            addSlowPathGenerator(
4525                slowPathCall(
4526                    slowPath, this, operationGetInlinedArgumentByVal,
4527                    JSValueRegs(resultTagGPR, resultPayloadGPR),
4528                    m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(),
4529                    node->origin.semantic.inlineCallFrame, indexGPR));
4530        } else {
4531            addSlowPathGenerator(
4532                slowPathCall(
4533                    slowPath, this, operationGetArgumentByVal,
4534                    JSValueRegs(resultTagGPR, resultPayloadGPR),
4535                    m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(),
4536                    indexGPR));
4537        }
4538
4539        slowArgument.link(&m_jit);
4540        jsValueResult(resultTagGPR, resultPayloadGPR, node);
4541        break;
4542    }
4543
4544    case NewFunctionNoCheck:
4545        compileNewFunctionNoCheck(node);
4546        break;
4547
4548    case NewFunction: {
4549        JSValueOperand value(this, node->child1());
4550        GPRTemporary resultTag(this, Reuse, value, TagWord);
4551        GPRTemporary resultPayload(this, Reuse, value, PayloadWord);
4552
4553        GPRReg valueTagGPR = value.tagGPR();
4554        GPRReg valuePayloadGPR = value.payloadGPR();
4555        GPRReg resultTagGPR = resultTag.gpr();
4556        GPRReg resultPayloadGPR = resultPayload.gpr();
4557
4558        m_jit.move(valuePayloadGPR, resultPayloadGPR);
4559        m_jit.move(valueTagGPR, resultTagGPR);
4560
4561        JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
4562
4563        addSlowPathGenerator(
4564            slowPathCall(
4565                notCreated, this, operationNewFunction, JSValueRegs(resultTagGPR, resultPayloadGPR),
4566                m_jit.codeBlock()->functionDecl(node->functionDeclIndex())));
4567
4568        jsValueResult(resultTagGPR, resultPayloadGPR, node);
4569        break;
4570    }
4571
4572    case NewFunctionExpression:
4573        compileNewFunctionExpression(node);
4574        break;
4575
4576    case In:
4577        compileIn(node);
4578        break;
4579
4580    case StoreBarrier:
4581    case StoreBarrierWithNullCheck: {
4582        compileStoreBarrier(node);
4583        break;
4584    }
4585
4586    case ForceOSRExit: {
4587        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
4588        break;
4589    }
4590
4591    case InvalidationPoint:
4592        emitInvalidationPoint(node);
4593        break;
4594
4595    case CheckWatchdogTimer:
4596        ASSERT(m_jit.vm()->watchdog);
4597        speculationCheck(
4598            WatchdogTimerFired, JSValueRegs(), 0,
4599            m_jit.branchTest8(
4600                JITCompiler::NonZero,
4601                JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress())));
4602        break;
4603
4604    case CountExecution:
4605        m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
4606        break;
4607
4608    case Phantom:
4609    case HardPhantom:
4610        DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
4611        noResult(node);
4612        break;
4613
4614    case Breakpoint:
4615    case ProfileWillCall:
4616    case ProfileDidCall:
4617    case PhantomLocal:
4618    case LoopHint:
4619        // This is a no-op.
4620        noResult(node);
4621        break;
4622
4623    case Unreachable:
4624        RELEASE_ASSERT_NOT_REACHED();
4625        break;
4626
4627    case LastNodeType:
4628    case Phi:
4629    case Upsilon:
4630    case GetArgument:
4631    case ExtractOSREntryLocal:
4632    case CheckTierUpInLoop:
4633    case CheckTierUpAtReturn:
4634    case CheckTierUpAndOSREnter:
4635    case Int52Rep:
4636    case FiatInt52:
4637    case Int52Constant:
4638    case CheckInBounds:
4639    case ArithIMul:
4640    case MultiGetByOffset:
4641    case MultiPutByOffset:
4642        RELEASE_ASSERT_NOT_REACHED();
4643        break;
4644    }
4645
4646    if (!m_compileOkay)
4647        return;
4648
4649    if (node->hasResult() && node->mustGenerate())
4650        use(node);
4651}
4652
4653#if ENABLE(GGC)
4654void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueTagGPR, Edge valueUse, GPRReg scratch1, GPRReg scratch2)
4655{
4656    JITCompiler::Jump isNotCell;
4657    if (!isKnownCell(valueUse.node()))
4658        isNotCell = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::CellTag));
4659
4660    JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(ownerGPR);
4661    storeToWriteBarrierBuffer(ownerGPR, scratch1, scratch2);
4662    ownerNotMarkedOrAlreadyRemembered.link(&m_jit);
4663
4664    if (!isKnownCell(valueUse.node()))
4665        isNotCell.link(&m_jit);
4666}
4667
4668void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueTagGPR, Edge valueUse, GPRReg scratch1, GPRReg scratch2)
4669{
4670    JITCompiler::Jump isNotCell;
4671    if (!isKnownCell(valueUse.node()))
4672        isNotCell = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::CellTag));
4673
4674    JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(owner);
4675    storeToWriteBarrierBuffer(owner, scratch1, scratch2);
4676    ownerNotMarkedOrAlreadyRemembered.link(&m_jit);
4677
4678    if (!isKnownCell(valueUse.node()))
4679        isNotCell.link(&m_jit);
4680}
4681#endif // ENABLE(GGC)
4682
4683JITCompiler::Jump SpeculativeJIT::branchIsCell(JSValueRegs regs)
4684{
4685    return m_jit.branch32(MacroAssembler::Equal, regs.tagGPR(), TrustedImm32(JSValue::CellTag));
4686}
4687
4688JITCompiler::Jump SpeculativeJIT::branchNotCell(JSValueRegs regs)
4689{
4690    return m_jit.branch32(MacroAssembler::NotEqual, regs.tagGPR(), TrustedImm32(JSValue::CellTag));
4691}
4692
4693JITCompiler::Jump SpeculativeJIT::branchIsOther(JSValueRegs regs, GPRReg tempGPR)
4694{
4695    m_jit.move(regs.tagGPR(), tempGPR);
4696    m_jit.or32(TrustedImm32(1), tempGPR);
4697    return m_jit.branch32(
4698        MacroAssembler::Equal, tempGPR,
4699        MacroAssembler::TrustedImm32(JSValue::NullTag));
4700}
4701
4702JITCompiler::Jump SpeculativeJIT::branchNotOther(JSValueRegs regs, GPRReg tempGPR)
4703{
4704    m_jit.move(regs.tagGPR(), tempGPR);
4705    m_jit.or32(TrustedImm32(1), tempGPR);
4706    return m_jit.branch32(
4707        MacroAssembler::NotEqual, tempGPR,
4708        MacroAssembler::TrustedImm32(JSValue::NullTag));
4709}
4710
4711void SpeculativeJIT::moveTrueTo(GPRReg gpr)
4712{
4713    m_jit.move(TrustedImm32(1), gpr);
4714}
4715
4716void SpeculativeJIT::moveFalseTo(GPRReg gpr)
4717{
4718    m_jit.move(TrustedImm32(0), gpr);
4719}
4720
4721void SpeculativeJIT::blessBoolean(GPRReg)
4722{
4723}
4724
4725#endif
4726
4727} } // namespace JSC::DFG
4728
4729#endif
4730