12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Apple Inc. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met:
72bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1. Redistributions of source code must retain the above copyright
82bde8e466a4451c7319e3a072d118917957d6554Steve Block *    notice, this list of conditions and the following disclaimer.
92bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2. Redistributions in binary form must reproduce the above copyright
102bde8e466a4451c7319e3a072d118917957d6554Steve Block *    notice, this list of conditions and the following disclaimer in the
112bde8e466a4451c7319e3a072d118917957d6554Steve Block *    documentation and/or other materials provided with the distribution.
122bde8e466a4451c7319e3a072d118917957d6554Steve Block *
132bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
142bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
152bde8e466a4451c7319e3a072d118917957d6554Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
162bde8e466a4451c7319e3a072d118917957d6554Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
172bde8e466a4451c7319e3a072d118917957d6554Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
182bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
192bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
202bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
212bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
232bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242bde8e466a4451c7319e3a072d118917957d6554Steve Block */
252bde8e466a4451c7319e3a072d118917957d6554Steve Block
262bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
272bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGByteCodeParser.h"
282bde8e466a4451c7319e3a072d118917957d6554Steve Block
292bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(DFG_JIT)
302bde8e466a4451c7319e3a072d118917957d6554Steve Block
312bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGAliasTracker.h"
322bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGScoreBoard.h"
332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "CodeBlock.h"
342bde8e466a4451c7319e3a072d118917957d6554Steve Block
352bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace JSC { namespace DFG {
362bde8e466a4451c7319e3a072d118917957d6554Steve Block
372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(DFG_JIT_RESTRICTIONS)
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// FIXME: Temporarily disable arithmetic, until we fix associated performance regressions.
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#define ARITHMETIC_OP() m_parseFailed = true
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#else
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#define ARITHMETIC_OP() ((void)0)
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
442bde8e466a4451c7319e3a072d118917957d6554Steve Block// === ByteCodeParser ===
452bde8e466a4451c7319e3a072d118917957d6554Steve Block//
462bde8e466a4451c7319e3a072d118917957d6554Steve Block// This class is used to compile the dataflow graph from a CodeBlock.
472bde8e466a4451c7319e3a072d118917957d6554Steve Blockclass ByteCodeParser {
482bde8e466a4451c7319e3a072d118917957d6554Steve Blockpublic:
492bde8e466a4451c7319e3a072d118917957d6554Steve Block    ByteCodeParser(JSGlobalData* globalData, CodeBlock* codeBlock, Graph& graph)
502bde8e466a4451c7319e3a072d118917957d6554Steve Block        : m_globalData(globalData)
512bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_codeBlock(codeBlock)
522bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_graph(graph)
532bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_currentIndex(0)
542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_parseFailed(false)
552bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_constantUndefined(UINT_MAX)
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_constantNull(UINT_MAX)
572bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_constant1(UINT_MAX)
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_constants(codeBlock->numberOfConstantRegisters())
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_arguments(codeBlock->m_numParameters)
602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_variables(codeBlock->m_numVars)
612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        , m_temporaries(codeBlock->m_numCalleeRegisters - codeBlock->m_numVars)
622bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < m_temporaries.size(); ++i)
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_temporaries[i] = NoNode;
652bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
662bde8e466a4451c7319e3a072d118917957d6554Steve Block
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Parse a full CodeBlock of bytecode.
682bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool parse();
692bde8e466a4451c7319e3a072d118917957d6554Steve Block
702bde8e466a4451c7319e3a072d118917957d6554Steve Blockprivate:
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Parse a single basic block of bytecode instructions.
722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool parseBlock(unsigned limit);
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
742bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Get/Set the operands/result of a bytecode instruction.
752bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex get(int operand)
762bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
772bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Is this a constant?
782bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (operand >= FirstConstantRegisterIndex) {
792bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned constant = operand - FirstConstantRegisterIndex;
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(constant < m_constants.size());
812bde8e466a4451c7319e3a072d118917957d6554Steve Block            return getJSConstant(constant);
822bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
832bde8e466a4451c7319e3a072d118917957d6554Steve Block
842bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Is this an argument?
852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (operand < 0)
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return getArgument(operand);
872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Is this a variable?
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned numVariables = m_variables.size();
902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if ((unsigned)operand < numVariables)
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return getVariable((unsigned)operand);
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Must be a temporary.
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned temporary = (unsigned)operand - numVariables;
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(temporary < m_temporaries.size());
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return getTemporary(temporary);
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
982bde8e466a4451c7319e3a072d118917957d6554Steve Block    void set(int operand, NodeIndex value)
992bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Is this an argument?
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (operand < 0) {
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setArgument(operand, value);
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Is this a variable?
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned numVariables = m_variables.size();
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if ((unsigned)operand < numVariables) {
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setVariable((unsigned)operand, value);
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return;
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Must be a temporary.
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned temporary = (unsigned)operand - numVariables;
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(temporary < m_temporaries.size());
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        setTemporary(temporary, value);
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Used in implementing get/set, above, where the operand is a local variable.
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    NodeIndex getVariable(unsigned operand)
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex setNode = m_variables[operand].set;
1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (setNode != NoNode)
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return m_graph[setNode].child1;
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex getNode = m_variables[operand].get;
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (getNode != NoNode)
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return getNode;
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        getNode = addToGraph(GetLocal, OpInfo(operand));
1312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_variables[operand].get = getNode;
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return getNode;
1332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void setVariable(unsigned operand, NodeIndex value)
1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex priorSet = m_variables[operand].set;
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_variables[operand].set = addToGraph(SetLocal, OpInfo(operand), value);
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (priorSet != NoNode)
1392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_graph.deref(priorSet);
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1412bde8e466a4451c7319e3a072d118917957d6554Steve Block
1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Used in implementing get/set, above, where the operand is a temporary.
1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    NodeIndex getTemporary(unsigned operand)
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex index = m_temporaries[operand];
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (index != NoNode)
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
1482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Detect a read of an temporary that is not a yet defined within this block (e.g. use of ?:).
1502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_parseFailed = true;
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block        return constantUndefined();
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    void setTemporary(unsigned operand, NodeIndex value)
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_temporaries[operand] = value;
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Used in implementing get/set, above, where the operand is an argument.
1592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    NodeIndex getArgument(unsigned operand)
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
1622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(argument < m_arguments.size());
1632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex setNode = m_arguments[argument].set;
1652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (setNode != NoNode)
1662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return m_graph[setNode].child1;
1672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex getNode = m_arguments[argument].get;
1692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (getNode != NoNode)
1702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return getNode;
1712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        getNode = addToGraph(GetLocal, OpInfo(operand));
1732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_arguments[argument].get = getNode;
1742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return getNode;
1752bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1762bde8e466a4451c7319e3a072d118917957d6554Steve Block    void setArgument(int operand, NodeIndex value)
1772bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
1792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(argument < m_arguments.size());
1802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex priorSet = m_arguments[argument].set;
1822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_arguments[argument].set = addToGraph(SetLocal, OpInfo(operand), value);
1832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (priorSet != NoNode)
1842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_graph.deref(priorSet);
1852bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1862bde8e466a4451c7319e3a072d118917957d6554Steve Block
1872bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Get an operand, and perform a ToInt32/ToNumber conversion on it.
1882bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getToInt32(int operand)
1892bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Avoid wastefully adding a JSConstant node to the graph, only to
1912bde8e466a4451c7319e3a072d118917957d6554Steve Block        // replace it with a Int32Constant (which is what would happen if
1922bde8e466a4451c7319e3a072d118917957d6554Steve Block        // we called 'toInt32(get(operand))' in this case).
1932bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (operand >= FirstConstantRegisterIndex) {
1942bde8e466a4451c7319e3a072d118917957d6554Steve Block            JSValue v = m_codeBlock->getConstant(operand);
1952bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (v.isInt32())
1962bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getInt32Constant(v.asInt32(), operand - FirstConstantRegisterIndex);
1972bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1982bde8e466a4451c7319e3a072d118917957d6554Steve Block        return toInt32(get(operand));
1992bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2002bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getToNumber(int operand)
2012bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
2022bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Avoid wastefully adding a JSConstant node to the graph, only to
2032bde8e466a4451c7319e3a072d118917957d6554Steve Block        // replace it with a DoubleConstant (which is what would happen if
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block        // we called 'toNumber(get(operand))' in this case).
2052bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (operand >= FirstConstantRegisterIndex) {
2062bde8e466a4451c7319e3a072d118917957d6554Steve Block            JSValue v = m_codeBlock->getConstant(operand);
2072bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (v.isNumber())
2082bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getDoubleConstant(v.uncheckedGetNumber(), operand - FirstConstantRegisterIndex);
2092bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
2102bde8e466a4451c7319e3a072d118917957d6554Steve Block        return toNumber(get(operand));
2112bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2122bde8e466a4451c7319e3a072d118917957d6554Steve Block
2132bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
2142bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex toInt32(NodeIndex index)
2152bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
2162bde8e466a4451c7319e3a072d118917957d6554Steve Block        Node& node = m_graph[index];
2172bde8e466a4451c7319e3a072d118917957d6554Steve Block
2182bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.hasInt32Result())
2192bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
2202bde8e466a4451c7319e3a072d118917957d6554Steve Block
2212bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.hasDoubleResult()) {
2222bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (node.op == DoubleConstant)
2232bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getInt32Constant(JSC::toInt32(valueOfDoubleConstant(index)), node.constantNumber());
2242bde8e466a4451c7319e3a072d118917957d6554Steve Block            // 'NumberToInt32(Int32ToNumber(X))' == X, and 'NumberToInt32(UInt32ToNumber(X)) == X'
2252bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (node.op == Int32ToNumber || node.op == UInt32ToNumber)
2262bde8e466a4451c7319e3a072d118917957d6554Steve Block                return node.child1;
2272bde8e466a4451c7319e3a072d118917957d6554Steve Block
2282bde8e466a4451c7319e3a072d118917957d6554Steve Block            // We unique NumberToInt32 nodes in a map to prevent duplicate conversions.
2292bde8e466a4451c7319e3a072d118917957d6554Steve Block            pair<UnaryOpMap::iterator, bool> result = m_numberToInt32Nodes.add(index, NoNode);
2302bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Either we added a new value, or the existing value in the map is non-zero.
2312bde8e466a4451c7319e3a072d118917957d6554Steve Block            ASSERT(result.second == (result.first->second == NoNode));
2322bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (result.second)
2332bde8e466a4451c7319e3a072d118917957d6554Steve Block                result.first->second = addToGraph(NumberToInt32, index);
2342bde8e466a4451c7319e3a072d118917957d6554Steve Block            return result.first->second;
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
2362bde8e466a4451c7319e3a072d118917957d6554Steve Block
2372bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Check for numeric constants boxed as JSValues.
2382bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.op == JSConstant) {
2392bde8e466a4451c7319e3a072d118917957d6554Steve Block            JSValue v = valueOfJSConstant(index);
2402bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (v.isInt32())
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getInt32Constant(v.asInt32(), node.constantNumber());
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (v.isNumber())
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber());
2442bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block        return addToGraph(ValueToInt32, index);
2472bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2482bde8e466a4451c7319e3a072d118917957d6554Steve Block
2492bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble.
2502bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex toNumber(NodeIndex index)
2512bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
2522bde8e466a4451c7319e3a072d118917957d6554Steve Block        Node& node = m_graph[index];
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block
2542bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.hasDoubleResult())
2552bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
2562bde8e466a4451c7319e3a072d118917957d6554Steve Block
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.hasInt32Result()) {
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (node.op == Int32Constant)
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getDoubleConstant(valueOfInt32Constant(index), node.constantNumber());
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block            // We unique Int32ToNumber nodes in a map to prevent duplicate conversions.
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block            pair<UnaryOpMap::iterator, bool> result = m_int32ToNumberNodes.add(index, NoNode);
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Either we added a new value, or the existing value in the map is non-zero.
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block            ASSERT(result.second == (result.first->second == NoNode));
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (result.second)
2662bde8e466a4451c7319e3a072d118917957d6554Steve Block                result.first->second = addToGraph(Int32ToNumber, index);
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block            return result.first->second;
2682bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
2692bde8e466a4451c7319e3a072d118917957d6554Steve Block
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.op == JSConstant) {
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block            JSValue v = valueOfJSConstant(index);
2722bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (v.isNumber())
2732bde8e466a4451c7319e3a072d118917957d6554Steve Block                return getDoubleConstant(v.uncheckedGetNumber(), node.constantNumber());
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
2752bde8e466a4451c7319e3a072d118917957d6554Steve Block
2762bde8e466a4451c7319e3a072d118917957d6554Steve Block        return addToGraph(ValueToNumber, index);
2772bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block
2792bde8e466a4451c7319e3a072d118917957d6554Steve Block
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Used in implementing get, above, where the operand is a constant.
2812bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getInt32Constant(int32_t value, unsigned constant)
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex index = m_constants[constant].asInt32;
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (index != NoNode)
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex resultIndex = addToGraph(Int32Constant, OpInfo(constant));
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_graph[resultIndex].setInt32Constant(value);
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_constants[constant].asInt32 = resultIndex;
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block        return resultIndex;
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2912bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getDoubleConstant(double value, unsigned constant)
2922bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
2932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex index = m_constants[constant].asNumeric;
2942bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (index != NoNode)
2952bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
2962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex resultIndex = addToGraph(DoubleConstant, OpInfo(constant));
2972bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_graph[resultIndex].setDoubleConstant(value);
2982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_constants[constant].asNumeric = resultIndex;
2992bde8e466a4451c7319e3a072d118917957d6554Steve Block        return resultIndex;
3002bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3012bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getJSConstant(unsigned constant)
3022bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex index = m_constants[constant].asJSValue;
3042bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (index != NoNode)
3052bde8e466a4451c7319e3a072d118917957d6554Steve Block            return index;
3062bde8e466a4451c7319e3a072d118917957d6554Steve Block
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex resultIndex = addToGraph(JSConstant, OpInfo(constant));
3082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_constants[constant].asJSValue = resultIndex;
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block        return resultIndex;
3102bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3112bde8e466a4451c7319e3a072d118917957d6554Steve Block
3122bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Helper functions to get/set the this value.
3132bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex getThis()
3142bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return getArgument(m_codeBlock->thisRegister());
3162bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3172bde8e466a4451c7319e3a072d118917957d6554Steve Block    void setThis(NodeIndex value)
3182bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        setArgument(m_codeBlock->thisRegister(), value);
3202bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3212bde8e466a4451c7319e3a072d118917957d6554Steve Block
3222bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Convenience methods for checking nodes for constants.
3232bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isInt32Constant(NodeIndex index)
3242bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3252bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_graph[index].op == Int32Constant;
3262bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3272bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isDoubleConstant(NodeIndex index)
3282bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3292bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_graph[index].op == DoubleConstant;
3302bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3312bde8e466a4451c7319e3a072d118917957d6554Steve Block    bool isJSConstant(NodeIndex index)
3322bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3332bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_graph[index].op == JSConstant;
3342bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3352bde8e466a4451c7319e3a072d118917957d6554Steve Block
3362bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Convenience methods for getting constant values.
3372bde8e466a4451c7319e3a072d118917957d6554Steve Block    int32_t valueOfInt32Constant(NodeIndex index)
3382bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3392bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(isInt32Constant(index));
3402bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_graph[index].int32Constant();
3412bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3422bde8e466a4451c7319e3a072d118917957d6554Steve Block    double valueOfDoubleConstant(NodeIndex index)
3432bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3442bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(isDoubleConstant(index));
3452bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_graph[index].numericConstant();
3462bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3472bde8e466a4451c7319e3a072d118917957d6554Steve Block    JSValue valueOfJSConstant(NodeIndex index)
3482bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3492bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(isJSConstant(index));
3502bde8e466a4451c7319e3a072d118917957d6554Steve Block        return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
3512bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3522bde8e466a4451c7319e3a072d118917957d6554Steve Block
3532bde8e466a4451c7319e3a072d118917957d6554Steve Block    // This method returns a JSConstant with the value 'undefined'.
3542bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex constantUndefined()
3552bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
3562bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Has m_constantUndefined been set up yet?
3572bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (m_constantUndefined == UINT_MAX) {
3582bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Search the constant pool for undefined, if we find it, we can just reuse this!
3592bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
3602bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {
3612bde8e466a4451c7319e3a072d118917957d6554Steve Block                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);
3622bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (testMe.isUndefined())
3632bde8e466a4451c7319e3a072d118917957d6554Steve Block                    return getJSConstant(m_constantUndefined);
3642bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
3652bde8e466a4451c7319e3a072d118917957d6554Steve Block
3662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == numberOfConstants);
3682bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_codeBlock->addConstant(jsUndefined());
3692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_constants.append(ConstantRecord());
3702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
3712bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
3722bde8e466a4451c7319e3a072d118917957d6554Steve Block
3732bde8e466a4451c7319e3a072d118917957d6554Steve Block        // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
3742bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());
3752bde8e466a4451c7319e3a072d118917957d6554Steve Block        return getJSConstant(m_constantUndefined);
3762bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3772bde8e466a4451c7319e3a072d118917957d6554Steve Block
3782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // This method returns a JSConstant with the value 'null'.
3792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    NodeIndex constantNull()
3802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
3812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Has m_constantNull been set up yet?
3822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_constantNull == UINT_MAX) {
3832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Search the constant pool for null, if we find it, we can just reuse this!
3842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
3852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {
3862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);
3872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (testMe.isNull())
3882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    return getJSConstant(m_constantNull);
3892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
3902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
3922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == numberOfConstants);
3932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_codeBlock->addConstant(jsNull());
3942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_constants.append(ConstantRecord());
3952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
3962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
3972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
3992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());
4002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return getJSConstant(m_constantNull);
4012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
4022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4032bde8e466a4451c7319e3a072d118917957d6554Steve Block    // This method returns a DoubleConstant with the value 1.
4042bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex one()
4052bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
4062bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Has m_constant1 been set up yet?
4072bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (m_constant1 == UINT_MAX) {
4082bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Search the constant pool for the value 1, if we find it, we can just reuse this!
4092bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
4102bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
4112bde8e466a4451c7319e3a072d118917957d6554Steve Block                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
4122bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (testMe.isInt32() && testMe.asInt32() == 1)
4132bde8e466a4451c7319e3a072d118917957d6554Steve Block                    return getDoubleConstant(1, m_constant1);
4142bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
4152bde8e466a4451c7319e3a072d118917957d6554Steve Block
4162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
4172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == numberOfConstants);
4182bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_codeBlock->addConstant(jsNumber(1));
4192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_constants.append(ConstantRecord());
4202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
4212bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
4222bde8e466a4451c7319e3a072d118917957d6554Steve Block
4232bde8e466a4451c7319e3a072d118917957d6554Steve Block        // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
4242bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
4252bde8e466a4451c7319e3a072d118917957d6554Steve Block        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
4262bde8e466a4451c7319e3a072d118917957d6554Steve Block        return getDoubleConstant(1, m_constant1);
4272bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
4282bde8e466a4451c7319e3a072d118917957d6554Steve Block
4292bde8e466a4451c7319e3a072d118917957d6554Steve Block
4302bde8e466a4451c7319e3a072d118917957d6554Steve Block    // These methods create a node and add it to the graph. If nodes of this type are
4312bde8e466a4451c7319e3a072d118917957d6554Steve Block    // 'mustGenerate' then the node  will implicitly be ref'ed to ensure generation.
4322bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
4332bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
4342bde8e466a4451c7319e3a072d118917957d6554Steve Block        NodeIndex resultIndex = (NodeIndex)m_graph.size();
4352bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_graph.append(Node(op, m_currentIndex, child1, child2, child3));
4362bde8e466a4451c7319e3a072d118917957d6554Steve Block
4372bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (op & NodeMustGenerate)
4382bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_graph.ref(resultIndex);
4392bde8e466a4451c7319e3a072d118917957d6554Steve Block        return resultIndex;
4402bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
4412bde8e466a4451c7319e3a072d118917957d6554Steve Block    NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
4422bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
4432bde8e466a4451c7319e3a072d118917957d6554Steve Block        NodeIndex resultIndex = (NodeIndex)m_graph.size();
4442bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_graph.append(Node(op, m_currentIndex, info, child1, child2, child3));
4452bde8e466a4451c7319e3a072d118917957d6554Steve Block
4462bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (op & NodeMustGenerate)
4472bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_graph.ref(resultIndex);
4482bde8e466a4451c7319e3a072d118917957d6554Steve Block        return resultIndex;
4492bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
4502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    NodeIndex addToGraph(NodeType op, OpInfo info1, OpInfo info2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
4512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
4522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex resultIndex = (NodeIndex)m_graph.size();
4532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_graph.append(Node(op, m_currentIndex, info1, info2, child1, child2, child3));
4542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (op & NodeMustGenerate)
4562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_graph.ref(resultIndex);
4572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return resultIndex;
4582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
4592bde8e466a4451c7319e3a072d118917957d6554Steve Block
4602bde8e466a4451c7319e3a072d118917957d6554Steve Block    JSGlobalData* m_globalData;
4612bde8e466a4451c7319e3a072d118917957d6554Steve Block    CodeBlock* m_codeBlock;
4622bde8e466a4451c7319e3a072d118917957d6554Steve Block    Graph& m_graph;
4632bde8e466a4451c7319e3a072d118917957d6554Steve Block
4642bde8e466a4451c7319e3a072d118917957d6554Steve Block    // The bytecode index of the current instruction being generated.
4652bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned m_currentIndex;
4662bde8e466a4451c7319e3a072d118917957d6554Steve Block
4672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Record failures due to unimplemented functionality or regressions.
4682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    bool m_parseFailed;
4692bde8e466a4451c7319e3a072d118917957d6554Steve Block
4702bde8e466a4451c7319e3a072d118917957d6554Steve Block    // We use these values during code generation, and to avoid the need for
4712bde8e466a4451c7319e3a072d118917957d6554Steve Block    // special handling we make sure they are available as constants in the
4722bde8e466a4451c7319e3a072d118917957d6554Steve Block    // CodeBlock's constant pool. These variables are initialized to
4732bde8e466a4451c7319e3a072d118917957d6554Steve Block    // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
4742bde8e466a4451c7319e3a072d118917957d6554Steve Block    // constant pool, as necessary.
4752bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned m_constantUndefined;
4762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned m_constantNull;
4772bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned m_constant1;
4782bde8e466a4451c7319e3a072d118917957d6554Steve Block
4792bde8e466a4451c7319e3a072d118917957d6554Steve Block    // A constant in the constant pool may be represented by more than one
4802bde8e466a4451c7319e3a072d118917957d6554Steve Block    // node in the graph, depending on the context in which it is being used.
4812bde8e466a4451c7319e3a072d118917957d6554Steve Block    struct ConstantRecord {
4822bde8e466a4451c7319e3a072d118917957d6554Steve Block        ConstantRecord()
4832bde8e466a4451c7319e3a072d118917957d6554Steve Block            : asInt32(NoNode)
4842bde8e466a4451c7319e3a072d118917957d6554Steve Block            , asNumeric(NoNode)
4852bde8e466a4451c7319e3a072d118917957d6554Steve Block            , asJSValue(NoNode)
4862bde8e466a4451c7319e3a072d118917957d6554Steve Block        {
4872bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
4882bde8e466a4451c7319e3a072d118917957d6554Steve Block
4892bde8e466a4451c7319e3a072d118917957d6554Steve Block        NodeIndex asInt32;
4902bde8e466a4451c7319e3a072d118917957d6554Steve Block        NodeIndex asNumeric;
4912bde8e466a4451c7319e3a072d118917957d6554Steve Block        NodeIndex asJSValue;
4922bde8e466a4451c7319e3a072d118917957d6554Steve Block    };
4932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // For every local variable we track any existing get or set of the value.
4952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We track the get so that these may be shared, and we track the set to
4962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // retrieve the current value, and to reference the final definition.
4972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    struct VariableRecord {
4982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        VariableRecord()
4992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            : get(NoNode)
5002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            , set(NoNode)
5012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        {
5022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
5032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex get;
5052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        NodeIndex set;
5062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    };
5072bde8e466a4451c7319e3a072d118917957d6554Steve Block
5082bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Track the index of the node whose result is the current value for every
5092bde8e466a4451c7319e3a072d118917957d6554Steve Block    // register value in the bytecode - argument, local, and temporary.
5102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector <ConstantRecord, 32> m_constants;
5112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector <VariableRecord, 32> m_arguments;
5122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector <VariableRecord, 32> m_variables;
5132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Vector <NodeIndex, 32> m_temporaries;
5142bde8e466a4451c7319e3a072d118917957d6554Steve Block
5152bde8e466a4451c7319e3a072d118917957d6554Steve Block    // These maps are used to unique ToNumber and ToInt32 operations.
5162bde8e466a4451c7319e3a072d118917957d6554Steve Block    typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
5172bde8e466a4451c7319e3a072d118917957d6554Steve Block    UnaryOpMap m_int32ToNumberNodes;
5182bde8e466a4451c7319e3a072d118917957d6554Steve Block    UnaryOpMap m_numberToInt32Nodes;
5192bde8e466a4451c7319e3a072d118917957d6554Steve Block};
5202bde8e466a4451c7319e3a072d118917957d6554Steve Block
5212bde8e466a4451c7319e3a072d118917957d6554Steve Block#define NEXT_OPCODE(name) \
5222bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_currentIndex += OPCODE_LENGTH(name); \
5232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    continue
5242bde8e466a4451c7319e3a072d118917957d6554Steve Block
5252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#define LAST_OPCODE(name) \
5262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_currentIndex += OPCODE_LENGTH(name); \
5272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return !m_parseFailed
5282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool ByteCodeParser::parseBlock(unsigned limit)
5302bde8e466a4451c7319e3a072d118917957d6554Steve Block{
5312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // No need to reset state initially, since it has been set by the constructor.
5322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_currentIndex) {
5332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < m_constants.size(); ++i)
5342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_constants[i] = ConstantRecord();
5352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < m_variables.size(); ++i)
5362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_variables[i] = VariableRecord();
5372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < m_arguments.size(); ++i)
5382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_arguments[i] = VariableRecord();
5392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (unsigned i = 0; i < m_temporaries.size(); ++i)
5402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_temporaries[i] = NoNode;
5412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
5422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5432bde8e466a4451c7319e3a072d118917957d6554Steve Block    AliasTracker aliases(m_graph);
5442bde8e466a4451c7319e3a072d118917957d6554Steve Block
5452bde8e466a4451c7319e3a072d118917957d6554Steve Block    Interpreter* interpreter = m_globalData->interpreter;
5462bde8e466a4451c7319e3a072d118917957d6554Steve Block    Instruction* instructionsBegin = m_codeBlock->instructions().begin();
5472bde8e466a4451c7319e3a072d118917957d6554Steve Block    while (true) {
5482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Don't extend over jump destinations.
5492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (m_currentIndex == limit) {
5502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Jump, OpInfo(m_currentIndex));
5512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            return !m_parseFailed;
5522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
5532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5542bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Switch on the current bytecode opcode.
5552bde8e466a4451c7319e3a072d118917957d6554Steve Block        Instruction* currentInstruction = instructionsBegin + m_currentIndex;
5562bde8e466a4451c7319e3a072d118917957d6554Steve Block        switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) {
5572bde8e466a4451c7319e3a072d118917957d6554Steve Block
5582bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Function entry opcodes ===
5592bde8e466a4451c7319e3a072d118917957d6554Steve Block
5602bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_enter:
5612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Initialize all locals to undefined.
5622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            for (int i = 0; i < m_codeBlock->m_numVars; ++i)
5632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                set(i, constantUndefined());
5642bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_enter);
5652bde8e466a4451c7319e3a072d118917957d6554Steve Block
5662bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_convert_this: {
5672bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getThis();
5682bde8e466a4451c7319e3a072d118917957d6554Steve Block            setThis(addToGraph(ConvertThis, op1));
5692bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_convert_this);
5702bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
5712bde8e466a4451c7319e3a072d118917957d6554Steve Block
5722bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Bitwise operations ===
5732bde8e466a4451c7319e3a072d118917957d6554Steve Block
5742bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_bitand: {
5752bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
5762bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
5772bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
5782bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_bitand);
5792bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
5802bde8e466a4451c7319e3a072d118917957d6554Steve Block
5812bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_bitor: {
5822bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
5832bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
5842bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
5852bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_bitor);
5862bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
5872bde8e466a4451c7319e3a072d118917957d6554Steve Block
5882bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_bitxor: {
5892bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
5902bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
5912bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
5922bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_bitxor);
5932bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
5942bde8e466a4451c7319e3a072d118917957d6554Steve Block
5952bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_rshift: {
5962bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
5972bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
5982bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex result;
5992bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Optimize out shifts by zero.
6002bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
6012bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = op1;
6022bde8e466a4451c7319e3a072d118917957d6554Steve Block            else
6032bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = addToGraph(BitRShift, op1, op2);
6042bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, result);
6052bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_rshift);
6062bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6072bde8e466a4451c7319e3a072d118917957d6554Steve Block
6082bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_lshift: {
6092bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
6102bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
6112bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex result;
6122bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Optimize out shifts by zero.
6132bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
6142bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = op1;
6152bde8e466a4451c7319e3a072d118917957d6554Steve Block            else
6162bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = addToGraph(BitLShift, op1, op2);
6172bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, result);
6182bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_lshift);
6192bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6202bde8e466a4451c7319e3a072d118917957d6554Steve Block
6212bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_urshift: {
6222bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
6232bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
6242bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex result;
6252bde8e466a4451c7319e3a072d118917957d6554Steve Block            // The result of a zero-extending right shift is treated as an unsigned value.
6262bde8e466a4451c7319e3a072d118917957d6554Steve Block            // This means that if the top bit is set, the result is not in the int32 range,
6272bde8e466a4451c7319e3a072d118917957d6554Steve Block            // and as such must be stored as a double. If the shift amount is a constant,
6282bde8e466a4451c7319e3a072d118917957d6554Steve Block            // we may be able to optimize.
6292bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (isInt32Constant(op2)) {
6302bde8e466a4451c7319e3a072d118917957d6554Steve Block                // If we know we are shifting by a non-zero amount, then since the operation
6312bde8e466a4451c7319e3a072d118917957d6554Steve Block                // zero fills we know the top bit of the result must be zero, and as such the
6322bde8e466a4451c7319e3a072d118917957d6554Steve Block                // result must be within the int32 range. Conversely, if this is a shift by
6332bde8e466a4451c7319e3a072d118917957d6554Steve Block                // zero, then the result may be changed by the conversion to unsigned, but it
6342bde8e466a4451c7319e3a072d118917957d6554Steve Block                // is not necessary to perform the shift!
6352bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (valueOfInt32Constant(op2) & 0x1f)
6362bde8e466a4451c7319e3a072d118917957d6554Steve Block                    result = addToGraph(BitURShift, op1, op2);
6372bde8e466a4451c7319e3a072d118917957d6554Steve Block                else
6382bde8e466a4451c7319e3a072d118917957d6554Steve Block                    result = addToGraph(UInt32ToNumber, op1);
6392bde8e466a4451c7319e3a072d118917957d6554Steve Block            }  else {
6402bde8e466a4451c7319e3a072d118917957d6554Steve Block                // Cannot optimize at this stage; shift & potentially rebox as a double.
6412bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = addToGraph(BitURShift, op1, op2);
6422bde8e466a4451c7319e3a072d118917957d6554Steve Block                result = addToGraph(UInt32ToNumber, result);
6432bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
6442bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, result);
6452bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_urshift);
6462bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6472bde8e466a4451c7319e3a072d118917957d6554Steve Block
6482bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Increment/Decrement opcodes ===
6492bde8e466a4451c7319e3a072d118917957d6554Steve Block
6502bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_pre_inc: {
6512bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned srcDst = currentInstruction[1].u.operand;
6522bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op = getToNumber(srcDst);
6532bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(srcDst, addToGraph(ArithAdd, op, one()));
6542bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_pre_inc);
6552bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6562bde8e466a4451c7319e3a072d118917957d6554Steve Block
6572bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_post_inc: {
6582bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned result = currentInstruction[1].u.operand;
6592bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned srcDst = currentInstruction[2].u.operand;
6602bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op = getToNumber(srcDst);
6612bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(result, op);
6622bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(srcDst, addToGraph(ArithAdd, op, one()));
6632bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_post_inc);
6642bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6652bde8e466a4451c7319e3a072d118917957d6554Steve Block
6662bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_pre_dec: {
6672bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned srcDst = currentInstruction[1].u.operand;
6682bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op = getToNumber(srcDst);
6692bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(srcDst, addToGraph(ArithSub, op, one()));
6702bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_pre_dec);
6712bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6722bde8e466a4451c7319e3a072d118917957d6554Steve Block
6732bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_post_dec: {
6742bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned result = currentInstruction[1].u.operand;
6752bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned srcDst = currentInstruction[2].u.operand;
6762bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op = getToNumber(srcDst);
6772bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(result, op);
6782bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(srcDst, addToGraph(ArithSub, op, one()));
6792bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_post_dec);
6802bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6812bde8e466a4451c7319e3a072d118917957d6554Steve Block
6822bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Arithmetic operations ===
6832bde8e466a4451c7319e3a072d118917957d6554Steve Block
6842bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_add: {
6852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
6862bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = get(currentInstruction[2].u.operand);
6872bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = get(currentInstruction[3].u.operand);
6882bde8e466a4451c7319e3a072d118917957d6554Steve Block            // If both operands can statically be determined to the numbers, then this is an arithmetic add.
6892bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Otherwise, we must assume this may be performing a concatenation to a string.
6902bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult())
6912bde8e466a4451c7319e3a072d118917957d6554Steve Block                set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2)));
6922bde8e466a4451c7319e3a072d118917957d6554Steve Block            else
6932bde8e466a4451c7319e3a072d118917957d6554Steve Block                set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2));
6942bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_add);
6952bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6962bde8e466a4451c7319e3a072d118917957d6554Steve Block
6972bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_sub: {
6982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
6992bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
7002bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
7012bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(ArithSub, op1, op2));
7022bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_sub);
7032bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7042bde8e466a4451c7319e3a072d118917957d6554Steve Block
7052bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_mul: {
7062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7072bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
7082bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
7092bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(ArithMul, op1, op2));
7102bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_mul);
7112bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7122bde8e466a4451c7319e3a072d118917957d6554Steve Block
7132bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_mod: {
7142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7152bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
7162bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
7172bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(ArithMod, op1, op2));
7182bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_mod);
7192bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7202bde8e466a4451c7319e3a072d118917957d6554Steve Block
7212bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_div: {
7222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7232bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
7242bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
7252bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2));
7262bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_div);
7272bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7282bde8e466a4451c7319e3a072d118917957d6554Steve Block
7292bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Misc operations ===
7302bde8e466a4451c7319e3a072d118917957d6554Steve Block
7312bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_mov: {
7322bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex op = get(currentInstruction[2].u.operand);
7332bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, op);
7342bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_mov);
7352bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
7362bde8e466a4451c7319e3a072d118917957d6554Steve Block
7372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_not: {
7382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex value = get(currentInstruction[2].u.operand);
7402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
7412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_not);
7422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_less: {
7452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
7472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
7482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
7492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_less);
7502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_lesseq: {
7532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
7552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
7562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
7572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_lesseq);
7582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_eq: {
7612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
7632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
7642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
7652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_eq);
7662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_eq_null: {
7692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex value = get(currentInstruction[2].u.operand);
7712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(CompareEq, value, constantNull()));
7722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_eq_null);
7732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_stricteq: {
7762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
7782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
7792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
7802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_stricteq);
7812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_neq: {
7842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
7862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
7872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
7882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_neq);
7892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_neq_null: {
7922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
7932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex value = get(currentInstruction[2].u.operand);
7942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, value, constantNull())));
7952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_neq_null);
7962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
7972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
7982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_nstricteq: {
7992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ARITHMETIC_OP();
8002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[2].u.operand);
8012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[3].u.operand);
8022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareStrictEq, op1, op2)));
8032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NEXT_OPCODE(op_nstricteq);
8042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8062bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Property access operations ===
8072bde8e466a4451c7319e3a072d118917957d6554Steve Block
8082bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_get_by_val: {
8092bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex base = get(currentInstruction[2].u.operand);
8102bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex property = get(currentInstruction[3].u.operand);
8112bde8e466a4451c7319e3a072d118917957d6554Steve Block
8122bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex getByVal = addToGraph(GetByVal, base, property, aliases.lookupGetByVal(base, property));
8132bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, getByVal);
8142bde8e466a4451c7319e3a072d118917957d6554Steve Block            aliases.recordGetByVal(getByVal);
8152bde8e466a4451c7319e3a072d118917957d6554Steve Block
8162bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_get_by_val);
8172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8182bde8e466a4451c7319e3a072d118917957d6554Steve Block
8192bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_put_by_val: {
8202bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex base = get(currentInstruction[1].u.operand);
8212bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex property = get(currentInstruction[2].u.operand);
8222bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex value = get(currentInstruction[3].u.operand);
8232bde8e466a4451c7319e3a072d118917957d6554Steve Block
8242bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex aliasedGet = aliases.lookupGetByVal(base, property);
8252bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex putByVal = addToGraph(aliasedGet != NoNode ? PutByValAlias : PutByVal, base, property, value);
8262bde8e466a4451c7319e3a072d118917957d6554Steve Block            aliases.recordPutByVal(putByVal);
8272bde8e466a4451c7319e3a072d118917957d6554Steve Block
8282bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_put_by_val);
8292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8302bde8e466a4451c7319e3a072d118917957d6554Steve Block
8312bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_get_by_id: {
8322bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex base = get(currentInstruction[2].u.operand);
8332bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned identifier = currentInstruction[3].u.operand;
8342bde8e466a4451c7319e3a072d118917957d6554Steve Block
8352bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex getById = addToGraph(GetById, OpInfo(identifier), base);
8362bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, getById);
8372bde8e466a4451c7319e3a072d118917957d6554Steve Block            aliases.recordGetById(getById);
8382bde8e466a4451c7319e3a072d118917957d6554Steve Block
8392bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_get_by_id);
8402bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
8412bde8e466a4451c7319e3a072d118917957d6554Steve Block
8422bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_put_by_id: {
8432bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex value = get(currentInstruction[3].u.operand);
8442bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex base = get(currentInstruction[1].u.operand);
8452bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned identifier = currentInstruction[2].u.operand;
8462bde8e466a4451c7319e3a072d118917957d6554Steve Block            bool direct = currentInstruction[8].u.operand;
8472bde8e466a4451c7319e3a072d118917957d6554Steve Block
8482bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (direct) {
8492bde8e466a4451c7319e3a072d118917957d6554Steve Block                NodeIndex putByIdDirect = addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
8502bde8e466a4451c7319e3a072d118917957d6554Steve Block                aliases.recordPutByIdDirect(putByIdDirect);
8512bde8e466a4451c7319e3a072d118917957d6554Steve Block            } else {
8522bde8e466a4451c7319e3a072d118917957d6554Steve Block                NodeIndex putById = addToGraph(PutById, OpInfo(identifier), base, value);
8532bde8e466a4451c7319e3a072d118917957d6554Steve Block                aliases.recordPutById(putById);
8542bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
8552bde8e466a4451c7319e3a072d118917957d6554Steve Block
8562bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_put_by_id);
8572bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
8582bde8e466a4451c7319e3a072d118917957d6554Steve Block
8592bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_get_global_var: {
8602bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
8612bde8e466a4451c7319e3a072d118917957d6554Steve Block            set(currentInstruction[1].u.operand, getGlobalVar);
8622bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_get_global_var);
8632bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
8642bde8e466a4451c7319e3a072d118917957d6554Steve Block
8652bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_put_global_var: {
8662bde8e466a4451c7319e3a072d118917957d6554Steve Block            NodeIndex value = get(currentInstruction[2].u.operand);
8672bde8e466a4451c7319e3a072d118917957d6554Steve Block            addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
8682bde8e466a4451c7319e3a072d118917957d6554Steve Block            NEXT_OPCODE(op_put_global_var);
8692bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
8702bde8e466a4451c7319e3a072d118917957d6554Steve Block
8712bde8e466a4451c7319e3a072d118917957d6554Steve Block        // === Block terminators. ===
8722bde8e466a4451c7319e3a072d118917957d6554Steve Block
8732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jmp: {
8742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[1].u.operand;
8752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
8762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jmp);
8772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_loop: {
8802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[1].u.operand;
8812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
8822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_loop);
8832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jtrue: {
8862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
8872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = get(currentInstruction[1].u.operand);
8882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jtrue)), condition);
8892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jtrue);
8902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jfalse: {
8932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
8942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = get(currentInstruction[1].u.operand);
8952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jfalse)), OpInfo(m_currentIndex + relativeOffset), condition);
8962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jfalse);
8972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
8982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_loop_if_true: {
9002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
9012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = get(currentInstruction[1].u.operand);
9022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_true)), condition);
9032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_loop_if_true);
9042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_loop_if_false: {
9072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
9082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = get(currentInstruction[1].u.operand);
9092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_false)), OpInfo(m_currentIndex + relativeOffset), condition);
9102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_loop_if_false);
9112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jeq_null: {
9142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
9152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex value = get(currentInstruction[1].u.operand);
9162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareEq, value, constantNull());
9172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
9182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jeq_null);
9192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jneq_null: {
9222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[2].u.operand;
9232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex value = get(currentInstruction[1].u.operand);
9242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareEq, value, constantNull());
9252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
9262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jneq_null);
9272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jnless: {
9302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLess, op1, op2);
9342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnless)), OpInfo(m_currentIndex + relativeOffset), condition);
9352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jnless);
9362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jnlesseq: {
9392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
9432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnlesseq)), OpInfo(m_currentIndex + relativeOffset), condition);
9442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jnlesseq);
9452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jless: {
9482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLess, op1, op2);
9522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jless)), condition);
9532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jless);
9542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_jlesseq: {
9572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
9612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jlesseq)), condition);
9622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_jlesseq);
9632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_loop_if_less: {
9662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLess, op1, op2);
9702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_less)), condition);
9712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_loop_if_less);
9722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        case op_loop_if_lesseq: {
9752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned relativeOffset = currentInstruction[3].u.operand;
9762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op1 = get(currentInstruction[1].u.operand);
9772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex op2 = get(currentInstruction[2].u.operand);
9782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
9792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_lesseq)), condition);
9802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_loop_if_lesseq);
9812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
9822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9832bde8e466a4451c7319e3a072d118917957d6554Steve Block        case op_ret: {
9842bde8e466a4451c7319e3a072d118917957d6554Steve Block            addToGraph(Return, get(currentInstruction[1].u.operand));
9852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // FIXME: throw away terminal definitions of variables;
9872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // should not be necessary once we have proper DCE!
9882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            for (unsigned i = 0; i < m_variables.size(); ++i) {
9892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                NodeIndex priorSet = m_variables[i].set;
9902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                if (priorSet != NoNode)
9912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                    m_graph.deref(priorSet);
9922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
9932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
9942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            LAST_OPCODE(op_ret);
9952bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
9962bde8e466a4451c7319e3a072d118917957d6554Steve Block
9972bde8e466a4451c7319e3a072d118917957d6554Steve Block        default:
9982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // Parse failed!
9992bde8e466a4451c7319e3a072d118917957d6554Steve Block            return false;
10002bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
10012bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
10022bde8e466a4451c7319e3a072d118917957d6554Steve Block}
10032bde8e466a4451c7319e3a072d118917957d6554Steve Block
10042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool ByteCodeParser::parse()
10052bde8e466a4451c7319e3a072d118917957d6554Steve Block{
10062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Set during construction.
10072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!m_currentIndex);
10082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
10102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions.
10112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned limit = jumpTargetIndex < m_codeBlock->numberOfJumpTargets() ? m_codeBlock->jumpTarget(jumpTargetIndex) : m_codeBlock->instructions().size();
10122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        ASSERT(m_currentIndex < limit);
10132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Loop until we reach the current limit (i.e. next jump target).
10152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        do {
10162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unsigned bytecodeBegin = m_currentIndex;
10172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex begin = m_graph.size();
10182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (!parseBlock(limit))
10202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return false;
10212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            // We should not have gone beyond the limit.
10222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(m_currentIndex <= limit);
10232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            NodeIndex end = m_graph.size();
10252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            m_graph.m_blocks.append(BasicBlock(bytecodeBegin, begin, end));
10262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } while (m_currentIndex < limit);
10272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
10282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Should have reached the end of the instructions.
10302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(m_currentIndex == m_codeBlock->instructions().size());
10312bde8e466a4451c7319e3a072d118917957d6554Steve Block
10322bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Assign VirtualRegisters.
10332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ScoreBoard scoreBoard(m_graph, m_variables.size());
10342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    Node* nodes = m_graph.begin();
10352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    size_t size = m_graph.size();
10362bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (size_t i = 0; i < size; ++i) {
10372bde8e466a4451c7319e3a072d118917957d6554Steve Block        Node& node = nodes[i];
10382bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.refCount) {
10392bde8e466a4451c7319e3a072d118917957d6554Steve Block            // First, call use on all of the current node's children, then
10402bde8e466a4451c7319e3a072d118917957d6554Steve Block            // allocate a VirtualRegister for this node. We do so in this
10412bde8e466a4451c7319e3a072d118917957d6554Steve Block            // order so that if a child is on its last use, and a
10422bde8e466a4451c7319e3a072d118917957d6554Steve Block            // VirtualRegister is freed, then it may be reused for node.
10432bde8e466a4451c7319e3a072d118917957d6554Steve Block            scoreBoard.use(node.child1);
10442bde8e466a4451c7319e3a072d118917957d6554Steve Block            scoreBoard.use(node.child2);
10452bde8e466a4451c7319e3a072d118917957d6554Steve Block            scoreBoard.use(node.child3);
10462bde8e466a4451c7319e3a072d118917957d6554Steve Block            node.virtualRegister = scoreBoard.allocate();
10472bde8e466a4451c7319e3a072d118917957d6554Steve Block            // 'mustGenerate' nodes have their useCount artificially elevated,
10482bde8e466a4451c7319e3a072d118917957d6554Steve Block            // call use now to account for this.
10492bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (node.mustGenerate())
10502bde8e466a4451c7319e3a072d118917957d6554Steve Block                scoreBoard.use(i);
10512bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
10522bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
10532bde8e466a4451c7319e3a072d118917957d6554Steve Block
10542bde8e466a4451c7319e3a072d118917957d6554Steve Block    // 'm_numCalleeRegisters' is the number of locals and temporaries allocated
10552bde8e466a4451c7319e3a072d118917957d6554Steve Block    // for the function (and checked for on entry). Since we perform a new and
10562bde8e466a4451c7319e3a072d118917957d6554Steve Block    // different allocation of temporaries, more registers may now be required.
10572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unsigned calleeRegisters = scoreBoard.allocatedCount() + m_variables.size();
10582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if ((unsigned)m_codeBlock->m_numCalleeRegisters < calleeRegisters)
10592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        m_codeBlock->m_numCalleeRegisters = calleeRegisters;
10602bde8e466a4451c7319e3a072d118917957d6554Steve Block
10612bde8e466a4451c7319e3a072d118917957d6554Steve Block#if DFG_DEBUG_VERBOSE
10622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_graph.dump(m_codeBlock);
10632bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
10642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10652bde8e466a4451c7319e3a072d118917957d6554Steve Block    return true;
10662bde8e466a4451c7319e3a072d118917957d6554Steve Block}
10672bde8e466a4451c7319e3a072d118917957d6554Steve Block
10682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
10692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
10702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if DFG_DEBUG_LOCAL_DISBALE
10712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    UNUSED_PARAM(graph);
10722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    UNUSED_PARAM(globalData);
10732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    UNUSED_PARAM(codeBlock);
10742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return false;
10752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#else
10762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return ByteCodeParser(globalData, codeBlock, graph).parse();
10772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
10782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
10792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
10802bde8e466a4451c7319e3a072d118917957d6554Steve Block} } // namespace JSC::DFG
10812bde8e466a4451c7319e3a072d118917957d6554Steve Block
10822bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
1083