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