2011-04-25 Adam Barth <abarth@webkit.org>
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGByteCodeParser.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGByteCodeParser.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGAliasTracker.h"
32 #include "DFGScoreBoard.h"
33 #include "CodeBlock.h"
34
35 namespace JSC { namespace DFG {
36
37 #if ENABLE(DFG_JIT_RESTRICTIONS)
38 // FIXME: Temporarily disable arithmetic, until we fix associated performance regressions.
39 #define ARITHMETIC_OP() m_parseFailed = true
40 #else
41 #define ARITHMETIC_OP() ((void)0)
42 #endif
43
44 // === ByteCodeParser ===
45 //
46 // This class is used to compile the dataflow graph from a CodeBlock.
47 class ByteCodeParser {
48 public:
49     ByteCodeParser(JSGlobalData* globalData, CodeBlock* codeBlock, Graph& graph)
50         : m_globalData(globalData)
51         , m_codeBlock(codeBlock)
52         , m_graph(graph)
53         , m_currentIndex(0)
54         , m_parseFailed(false)
55         , m_constantUndefined(UINT_MAX)
56         , m_constantNull(UINT_MAX)
57         , m_constant1(UINT_MAX)
58         , m_constants(codeBlock->numberOfConstantRegisters())
59         , m_numArguments(codeBlock->m_numParameters)
60         , m_numLocals(codeBlock->m_numCalleeRegisters)
61         , m_preservedVars(codeBlock->m_numVars)
62     {
63     }
64
65     // Parse a full CodeBlock of bytecode.
66     bool parse();
67
68 private:
69     // Parse a single basic block of bytecode instructions.
70     bool parseBlock(unsigned limit);
71     // Setup predecessor links in the graph's BasicBlocks.
72     void setupPredecessors();
73     // Link GetLocal & SetLocal nodes, to ensure live values are generated.
74     enum PhiStackType {
75         LocalPhiStack,
76         ArgumentPhiStack
77     };
78     template<PhiStackType stackType>
79     void processPhiStack();
80     // Add spill locations to nodes.
81     void allocateVirtualRegisters();
82
83     // Get/Set the operands/result of a bytecode instruction.
84     NodeIndex get(int operand)
85     {
86         // Is this a constant?
87         if (operand >= FirstConstantRegisterIndex) {
88             unsigned constant = operand - FirstConstantRegisterIndex;
89             ASSERT(constant < m_constants.size());
90             return getJSConstant(constant);
91         }
92
93         // Is this an argument?
94         if (operand < 0)
95             return getArgument(operand);
96
97         // Must be a local.
98         return getLocal((unsigned)operand);
99     }
100     void set(int operand, NodeIndex value)
101     {
102         // Is this an argument?
103         if (operand < 0) {
104             setArgument(operand, value);
105             return;
106         }
107
108         // Must be a local.
109         setLocal((unsigned)operand, value);
110     }
111
112     // Used in implementing get/set, above, where the operand is a local variable.
113     NodeIndex getLocal(unsigned operand)
114     {
115         NodeIndex nodeIndex = m_currentBlock->m_locals[operand].value;
116
117         if (nodeIndex != NoNode) {
118             Node& node = m_graph[nodeIndex];
119             if (node.op == GetLocal)
120                 return nodeIndex;
121             ASSERT(node.op == SetLocal);
122             return node.child1;
123         }
124
125         // Check for reads of temporaries from prior blocks,
126         // expand m_preservedVars to cover these.
127         m_preservedVars = std::max(m_preservedVars, operand + 1);
128
129         NodeIndex phi = addToGraph(Phi);
130         m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
131         nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
132         m_currentBlock->m_locals[operand].value = nodeIndex;
133         return nodeIndex;
134     }
135     void setLocal(unsigned operand, NodeIndex value)
136     {
137         m_currentBlock->m_locals[operand].value = addToGraph(SetLocal, OpInfo(operand), value);
138     }
139
140     // Used in implementing get/set, above, where the operand is an argument.
141     NodeIndex getArgument(unsigned operand)
142     {
143         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
144         ASSERT(argument < m_numArguments);
145
146         NodeIndex nodeIndex = m_currentBlock->m_arguments[argument].value;
147
148         if (nodeIndex != NoNode) {
149             Node& node = m_graph[nodeIndex];
150             if (node.op == GetLocal)
151                 return nodeIndex;
152             ASSERT(node.op == SetLocal);
153             return node.child1;
154         }
155
156         NodeIndex phi = addToGraph(Phi);
157         m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
158         nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
159         m_currentBlock->m_arguments[argument].value = nodeIndex;
160         return nodeIndex;
161     }
162     void setArgument(int operand, NodeIndex value)
163     {
164         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
165         ASSERT(argument < m_numArguments);
166
167         m_currentBlock->m_arguments[argument].value = addToGraph(SetLocal, OpInfo(operand), value);
168     }
169
170     // Get an operand, and perform a ToInt32/ToNumber conversion on it.
171     NodeIndex getToInt32(int operand)
172     {
173         // Avoid wastefully adding a JSConstant node to the graph, only to
174         // replace it with a Int32Constant (which is what would happen if
175         // we called 'toInt32(get(operand))' in this case).
176         if (operand >= FirstConstantRegisterIndex) {
177             JSValue v = m_codeBlock->getConstant(operand);
178             if (v.isInt32())
179                 return getInt32Constant(v.asInt32(), operand - FirstConstantRegisterIndex);
180         }
181         return toInt32(get(operand));
182     }
183     NodeIndex getToNumber(int operand)
184     {
185         // Avoid wastefully adding a JSConstant node to the graph, only to
186         // replace it with a DoubleConstant (which is what would happen if
187         // we called 'toNumber(get(operand))' in this case).
188         if (operand >= FirstConstantRegisterIndex) {
189             JSValue v = m_codeBlock->getConstant(operand);
190             if (v.isNumber())
191                 return getDoubleConstant(v.uncheckedGetNumber(), operand - FirstConstantRegisterIndex);
192         }
193         return toNumber(get(operand));
194     }
195
196     // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
197     NodeIndex toInt32(NodeIndex index)
198     {
199         Node& node = m_graph[index];
200
201         if (node.hasInt32Result())
202             return index;
203
204         if (node.hasDoubleResult()) {
205             if (node.op == DoubleConstant)
206                 return getInt32Constant(JSC::toInt32(valueOfDoubleConstant(index)), node.constantNumber());
207             // 'NumberToInt32(Int32ToNumber(X))' == X, and 'NumberToInt32(UInt32ToNumber(X)) == X'
208             if (node.op == Int32ToNumber || node.op == UInt32ToNumber)
209                 return node.child1;
210
211             // We unique NumberToInt32 nodes in a map to prevent duplicate conversions.
212             pair<UnaryOpMap::iterator, bool> result = m_numberToInt32Nodes.add(index, NoNode);
213             // Either we added a new value, or the existing value in the map is non-zero.
214             ASSERT(result.second == (result.first->second == NoNode));
215             if (result.second)
216                 result.first->second = addToGraph(NumberToInt32, index);
217             return result.first->second;
218         }
219
220         // Check for numeric constants boxed as JSValues.
221         if (node.op == JSConstant) {
222             JSValue v = valueOfJSConstant(index);
223             if (v.isInt32())
224                 return getInt32Constant(v.asInt32(), node.constantNumber());
225             if (v.isNumber())
226                 return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber());
227         }
228
229         return addToGraph(ValueToInt32, index);
230     }
231
232     // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble.
233     NodeIndex toNumber(NodeIndex index)
234     {
235         Node& node = m_graph[index];
236
237         if (node.hasDoubleResult())
238             return index;
239
240         if (node.hasInt32Result()) {
241             if (node.op == Int32Constant)
242                 return getDoubleConstant(valueOfInt32Constant(index), node.constantNumber());
243
244             // We unique Int32ToNumber nodes in a map to prevent duplicate conversions.
245             pair<UnaryOpMap::iterator, bool> result = m_int32ToNumberNodes.add(index, NoNode);
246             // Either we added a new value, or the existing value in the map is non-zero.
247             ASSERT(result.second == (result.first->second == NoNode));
248             if (result.second)
249                 result.first->second = addToGraph(Int32ToNumber, index);
250             return result.first->second;
251         }
252
253         if (node.op == JSConstant) {
254             JSValue v = valueOfJSConstant(index);
255             if (v.isNumber())
256                 return getDoubleConstant(v.uncheckedGetNumber(), node.constantNumber());
257         }
258
259         return addToGraph(ValueToNumber, index);
260     }
261
262
263     // Used in implementing get, above, where the operand is a constant.
264     NodeIndex getInt32Constant(int32_t value, unsigned constant)
265     {
266         NodeIndex index = m_constants[constant].asInt32;
267         if (index != NoNode)
268             return index;
269         NodeIndex resultIndex = addToGraph(Int32Constant, OpInfo(constant));
270         m_graph[resultIndex].setInt32Constant(value);
271         m_constants[constant].asInt32 = resultIndex;
272         return resultIndex;
273     }
274     NodeIndex getDoubleConstant(double value, unsigned constant)
275     {
276         NodeIndex index = m_constants[constant].asNumeric;
277         if (index != NoNode)
278             return index;
279         NodeIndex resultIndex = addToGraph(DoubleConstant, OpInfo(constant));
280         m_graph[resultIndex].setDoubleConstant(value);
281         m_constants[constant].asNumeric = resultIndex;
282         return resultIndex;
283     }
284     NodeIndex getJSConstant(unsigned constant)
285     {
286         NodeIndex index = m_constants[constant].asJSValue;
287         if (index != NoNode)
288             return index;
289
290         NodeIndex resultIndex = addToGraph(JSConstant, OpInfo(constant));
291         m_constants[constant].asJSValue = resultIndex;
292         return resultIndex;
293     }
294
295     // Helper functions to get/set the this value.
296     NodeIndex getThis()
297     {
298         return getArgument(m_codeBlock->thisRegister());
299     }
300     void setThis(NodeIndex value)
301     {
302         setArgument(m_codeBlock->thisRegister(), value);
303     }
304
305     // Convenience methods for checking nodes for constants.
306     bool isInt32Constant(NodeIndex index)
307     {
308         return m_graph[index].op == Int32Constant;
309     }
310     bool isDoubleConstant(NodeIndex index)
311     {
312         return m_graph[index].op == DoubleConstant;
313     }
314     bool isJSConstant(NodeIndex index)
315     {
316         return m_graph[index].op == JSConstant;
317     }
318
319     // Convenience methods for getting constant values.
320     int32_t valueOfInt32Constant(NodeIndex index)
321     {
322         ASSERT(isInt32Constant(index));
323         return m_graph[index].int32Constant();
324     }
325     double valueOfDoubleConstant(NodeIndex index)
326     {
327         ASSERT(isDoubleConstant(index));
328         return m_graph[index].numericConstant();
329     }
330     JSValue valueOfJSConstant(NodeIndex index)
331     {
332         ASSERT(isJSConstant(index));
333         return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
334     }
335
336     // This method returns a JSConstant with the value 'undefined'.
337     NodeIndex constantUndefined()
338     {
339         // Has m_constantUndefined been set up yet?
340         if (m_constantUndefined == UINT_MAX) {
341             // Search the constant pool for undefined, if we find it, we can just reuse this!
342             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
343             for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {
344                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);
345                 if (testMe.isUndefined())
346                     return getJSConstant(m_constantUndefined);
347             }
348
349             // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
350             ASSERT(m_constants.size() == numberOfConstants);
351             m_codeBlock->addConstant(jsUndefined());
352             m_constants.append(ConstantRecord());
353             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
354         }
355
356         // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
357         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());
358         return getJSConstant(m_constantUndefined);
359     }
360
361     // This method returns a JSConstant with the value 'null'.
362     NodeIndex constantNull()
363     {
364         // Has m_constantNull been set up yet?
365         if (m_constantNull == UINT_MAX) {
366             // Search the constant pool for null, if we find it, we can just reuse this!
367             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
368             for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {
369                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);
370                 if (testMe.isNull())
371                     return getJSConstant(m_constantNull);
372             }
373
374             // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
375             ASSERT(m_constants.size() == numberOfConstants);
376             m_codeBlock->addConstant(jsNull());
377             m_constants.append(ConstantRecord());
378             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
379         }
380
381         // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
382         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());
383         return getJSConstant(m_constantNull);
384     }
385
386     // This method returns a DoubleConstant with the value 1.
387     NodeIndex one()
388     {
389         // Has m_constant1 been set up yet?
390         if (m_constant1 == UINT_MAX) {
391             // Search the constant pool for the value 1, if we find it, we can just reuse this!
392             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
393             for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
394                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
395                 if (testMe.isInt32() && testMe.asInt32() == 1)
396                     return getDoubleConstant(1, m_constant1);
397             }
398
399             // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
400             ASSERT(m_constants.size() == numberOfConstants);
401             m_codeBlock->addConstant(jsNumber(1));
402             m_constants.append(ConstantRecord());
403             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
404         }
405
406         // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
407         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
408         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
409         return getDoubleConstant(1, m_constant1);
410     }
411
412
413     // These methods create a node and add it to the graph. If nodes of this type are
414     // 'mustGenerate' then the node  will implicitly be ref'ed to ensure generation.
415     NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
416     {
417         NodeIndex resultIndex = (NodeIndex)m_graph.size();
418         m_graph.append(Node(op, m_currentIndex, child1, child2, child3));
419
420         if (op & NodeMustGenerate)
421             m_graph.ref(resultIndex);
422         return resultIndex;
423     }
424     NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
425     {
426         NodeIndex resultIndex = (NodeIndex)m_graph.size();
427         m_graph.append(Node(op, m_currentIndex, info, child1, child2, child3));
428
429         if (op & NodeMustGenerate)
430             m_graph.ref(resultIndex);
431         return resultIndex;
432     }
433     NodeIndex addToGraph(NodeType op, OpInfo info1, OpInfo info2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
434     {
435         NodeIndex resultIndex = (NodeIndex)m_graph.size();
436         m_graph.append(Node(op, m_currentIndex, info1, info2, child1, child2, child3));
437
438         if (op & NodeMustGenerate)
439             m_graph.ref(resultIndex);
440         return resultIndex;
441     }
442
443     JSGlobalData* m_globalData;
444     CodeBlock* m_codeBlock;
445     Graph& m_graph;
446
447     // The current block being generated.
448     BasicBlock* m_currentBlock;
449     // The bytecode index of the current instruction being generated.
450     unsigned m_currentIndex;
451
452     // Record failures due to unimplemented functionality or regressions.
453     bool m_parseFailed;
454
455     // We use these values during code generation, and to avoid the need for
456     // special handling we make sure they are available as constants in the
457     // CodeBlock's constant pool. These variables are initialized to
458     // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
459     // constant pool, as necessary.
460     unsigned m_constantUndefined;
461     unsigned m_constantNull;
462     unsigned m_constant1;
463
464     // A constant in the constant pool may be represented by more than one
465     // node in the graph, depending on the context in which it is being used.
466     struct ConstantRecord {
467         ConstantRecord()
468             : asInt32(NoNode)
469             , asNumeric(NoNode)
470             , asJSValue(NoNode)
471         {
472         }
473
474         NodeIndex asInt32;
475         NodeIndex asNumeric;
476         NodeIndex asJSValue;
477     };
478
479     // Track the index of the node whose result is the current value for every
480     // register value in the bytecode - argument, local, and temporary.
481     Vector<ConstantRecord, 16> m_constants;
482
483     // The number of arguments passed to the function.
484     unsigned m_numArguments;
485     // The number of locals (vars + temporaries) used in the function.
486     unsigned m_numLocals;
487     // The number of registers we need to preserve across BasicBlock boundaries;
488     // typically equal to the number vars, but we expand this to cover all
489     // temporaries that persist across blocks (dues to ?:, &&, ||, etc).
490     unsigned m_preservedVars;
491
492     struct PhiStackEntry {
493         PhiStackEntry(BasicBlock* block, NodeIndex phi, unsigned varNo)
494             : m_block(block)
495             , m_phi(phi)
496             , m_varNo(varNo)
497         {
498         }
499
500         BasicBlock* m_block;
501         NodeIndex m_phi;
502         unsigned m_varNo;
503     };
504     Vector<PhiStackEntry, 16> m_argumentPhiStack;
505     Vector<PhiStackEntry, 16> m_localPhiStack;
506
507     // These maps are used to unique ToNumber and ToInt32 operations.
508     typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
509     UnaryOpMap m_int32ToNumberNodes;
510     UnaryOpMap m_numberToInt32Nodes;
511 };
512
513 #define NEXT_OPCODE(name) \
514     m_currentIndex += OPCODE_LENGTH(name); \
515     continue
516
517 #define LAST_OPCODE(name) \
518     m_currentIndex += OPCODE_LENGTH(name); \
519     return !m_parseFailed
520
521 bool ByteCodeParser::parseBlock(unsigned limit)
522 {
523     // No need to reset state initially, since it has been set by the constructor.
524     if (m_currentIndex) {
525         for (unsigned i = 0; i < m_constants.size(); ++i)
526             m_constants[i] = ConstantRecord();
527     }
528
529     AliasTracker aliases(m_graph);
530
531     Interpreter* interpreter = m_globalData->interpreter;
532     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
533     while (true) {
534         // Don't extend over jump destinations.
535         if (m_currentIndex == limit) {
536             addToGraph(Jump, OpInfo(m_currentIndex));
537             return !m_parseFailed;
538         }
539
540         // Switch on the current bytecode opcode.
541         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
542         switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) {
543
544         // === Function entry opcodes ===
545
546         case op_enter:
547             // Initialize all locals to undefined.
548             for (int i = 0; i < m_codeBlock->m_numVars; ++i)
549                 set(i, constantUndefined());
550             NEXT_OPCODE(op_enter);
551
552         case op_convert_this: {
553             NodeIndex op1 = getThis();
554             setThis(addToGraph(ConvertThis, op1));
555             NEXT_OPCODE(op_convert_this);
556         }
557
558         // === Bitwise operations ===
559
560         case op_bitand: {
561             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
562             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
563             set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
564             NEXT_OPCODE(op_bitand);
565         }
566
567         case op_bitor: {
568             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
569             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
570             set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
571             NEXT_OPCODE(op_bitor);
572         }
573
574         case op_bitxor: {
575             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
576             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
577             set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
578             NEXT_OPCODE(op_bitxor);
579         }
580
581         case op_rshift: {
582             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
583             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
584             NodeIndex result;
585             // Optimize out shifts by zero.
586             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
587                 result = op1;
588             else
589                 result = addToGraph(BitRShift, op1, op2);
590             set(currentInstruction[1].u.operand, result);
591             NEXT_OPCODE(op_rshift);
592         }
593
594         case op_lshift: {
595             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
596             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
597             NodeIndex result;
598             // Optimize out shifts by zero.
599             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
600                 result = op1;
601             else
602                 result = addToGraph(BitLShift, op1, op2);
603             set(currentInstruction[1].u.operand, result);
604             NEXT_OPCODE(op_lshift);
605         }
606
607         case op_urshift: {
608             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
609             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
610             NodeIndex result;
611             // The result of a zero-extending right shift is treated as an unsigned value.
612             // This means that if the top bit is set, the result is not in the int32 range,
613             // and as such must be stored as a double. If the shift amount is a constant,
614             // we may be able to optimize.
615             if (isInt32Constant(op2)) {
616                 // If we know we are shifting by a non-zero amount, then since the operation
617                 // zero fills we know the top bit of the result must be zero, and as such the
618                 // result must be within the int32 range. Conversely, if this is a shift by
619                 // zero, then the result may be changed by the conversion to unsigned, but it
620                 // is not necessary to perform the shift!
621                 if (valueOfInt32Constant(op2) & 0x1f)
622                     result = addToGraph(BitURShift, op1, op2);
623                 else
624                     result = addToGraph(UInt32ToNumber, op1);
625             }  else {
626                 // Cannot optimize at this stage; shift & potentially rebox as a double.
627                 result = addToGraph(BitURShift, op1, op2);
628                 result = addToGraph(UInt32ToNumber, result);
629             }
630             set(currentInstruction[1].u.operand, result);
631             NEXT_OPCODE(op_urshift);
632         }
633
634         // === Increment/Decrement opcodes ===
635
636         case op_pre_inc: {
637             unsigned srcDst = currentInstruction[1].u.operand;
638             NodeIndex op = getToNumber(srcDst);
639             set(srcDst, addToGraph(ArithAdd, op, one()));
640             NEXT_OPCODE(op_pre_inc);
641         }
642
643         case op_post_inc: {
644             unsigned result = currentInstruction[1].u.operand;
645             unsigned srcDst = currentInstruction[2].u.operand;
646             NodeIndex op = getToNumber(srcDst);
647             set(result, op);
648             set(srcDst, addToGraph(ArithAdd, op, one()));
649             NEXT_OPCODE(op_post_inc);
650         }
651
652         case op_pre_dec: {
653             unsigned srcDst = currentInstruction[1].u.operand;
654             NodeIndex op = getToNumber(srcDst);
655             set(srcDst, addToGraph(ArithSub, op, one()));
656             NEXT_OPCODE(op_pre_dec);
657         }
658
659         case op_post_dec: {
660             unsigned result = currentInstruction[1].u.operand;
661             unsigned srcDst = currentInstruction[2].u.operand;
662             NodeIndex op = getToNumber(srcDst);
663             set(result, op);
664             set(srcDst, addToGraph(ArithSub, op, one()));
665             NEXT_OPCODE(op_post_dec);
666         }
667
668         // === Arithmetic operations ===
669
670         case op_add: {
671             ARITHMETIC_OP();
672             NodeIndex op1 = get(currentInstruction[2].u.operand);
673             NodeIndex op2 = get(currentInstruction[3].u.operand);
674             // If both operands can statically be determined to the numbers, then this is an arithmetic add.
675             // Otherwise, we must assume this may be performing a concatenation to a string.
676             if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult())
677                 set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2)));
678             else
679                 set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2));
680             NEXT_OPCODE(op_add);
681         }
682
683         case op_sub: {
684             ARITHMETIC_OP();
685             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
686             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
687             set(currentInstruction[1].u.operand, addToGraph(ArithSub, op1, op2));
688             NEXT_OPCODE(op_sub);
689         }
690
691         case op_mul: {
692             ARITHMETIC_OP();
693             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
694             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
695             set(currentInstruction[1].u.operand, addToGraph(ArithMul, op1, op2));
696             NEXT_OPCODE(op_mul);
697         }
698
699         case op_mod: {
700             ARITHMETIC_OP();
701             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
702             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
703             set(currentInstruction[1].u.operand, addToGraph(ArithMod, op1, op2));
704             NEXT_OPCODE(op_mod);
705         }
706
707         case op_div: {
708             ARITHMETIC_OP();
709             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
710             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
711             set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2));
712             NEXT_OPCODE(op_div);
713         }
714
715         // === Misc operations ===
716
717         case op_mov: {
718             NodeIndex op = get(currentInstruction[2].u.operand);
719             set(currentInstruction[1].u.operand, op);
720             NEXT_OPCODE(op_mov);
721         }
722
723         case op_not: {
724             ARITHMETIC_OP();
725             NodeIndex value = get(currentInstruction[2].u.operand);
726             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
727             NEXT_OPCODE(op_not);
728         }
729
730         case op_less: {
731             ARITHMETIC_OP();
732             NodeIndex op1 = get(currentInstruction[2].u.operand);
733             NodeIndex op2 = get(currentInstruction[3].u.operand);
734             set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
735             NEXT_OPCODE(op_less);
736         }
737
738         case op_lesseq: {
739             ARITHMETIC_OP();
740             NodeIndex op1 = get(currentInstruction[2].u.operand);
741             NodeIndex op2 = get(currentInstruction[3].u.operand);
742             set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
743             NEXT_OPCODE(op_lesseq);
744         }
745
746         case op_eq: {
747             ARITHMETIC_OP();
748             NodeIndex op1 = get(currentInstruction[2].u.operand);
749             NodeIndex op2 = get(currentInstruction[3].u.operand);
750             set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
751             NEXT_OPCODE(op_eq);
752         }
753
754         case op_eq_null: {
755             ARITHMETIC_OP();
756             NodeIndex value = get(currentInstruction[2].u.operand);
757             set(currentInstruction[1].u.operand, addToGraph(CompareEq, value, constantNull()));
758             NEXT_OPCODE(op_eq_null);
759         }
760
761         case op_stricteq: {
762             ARITHMETIC_OP();
763             NodeIndex op1 = get(currentInstruction[2].u.operand);
764             NodeIndex op2 = get(currentInstruction[3].u.operand);
765             set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
766             NEXT_OPCODE(op_stricteq);
767         }
768
769         case op_neq: {
770             ARITHMETIC_OP();
771             NodeIndex op1 = get(currentInstruction[2].u.operand);
772             NodeIndex op2 = get(currentInstruction[3].u.operand);
773             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
774             NEXT_OPCODE(op_neq);
775         }
776
777         case op_neq_null: {
778             ARITHMETIC_OP();
779             NodeIndex value = get(currentInstruction[2].u.operand);
780             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, value, constantNull())));
781             NEXT_OPCODE(op_neq_null);
782         }
783
784         case op_nstricteq: {
785             ARITHMETIC_OP();
786             NodeIndex op1 = get(currentInstruction[2].u.operand);
787             NodeIndex op2 = get(currentInstruction[3].u.operand);
788             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareStrictEq, op1, op2)));
789             NEXT_OPCODE(op_nstricteq);
790         }
791
792         // === Property access operations ===
793
794         case op_get_by_val: {
795             NodeIndex base = get(currentInstruction[2].u.operand);
796             NodeIndex property = get(currentInstruction[3].u.operand);
797
798             NodeIndex getByVal = addToGraph(GetByVal, base, property, aliases.lookupGetByVal(base, property));
799             set(currentInstruction[1].u.operand, getByVal);
800             aliases.recordGetByVal(getByVal);
801
802             NEXT_OPCODE(op_get_by_val);
803         }
804
805         case op_put_by_val: {
806             NodeIndex base = get(currentInstruction[1].u.operand);
807             NodeIndex property = get(currentInstruction[2].u.operand);
808             NodeIndex value = get(currentInstruction[3].u.operand);
809
810             NodeIndex aliasedGet = aliases.lookupGetByVal(base, property);
811             NodeIndex putByVal = addToGraph(aliasedGet != NoNode ? PutByValAlias : PutByVal, base, property, value);
812             aliases.recordPutByVal(putByVal);
813
814             NEXT_OPCODE(op_put_by_val);
815         }
816
817         case op_get_by_id: {
818             NodeIndex base = get(currentInstruction[2].u.operand);
819             unsigned identifier = currentInstruction[3].u.operand;
820
821             NodeIndex getById = addToGraph(GetById, OpInfo(identifier), base);
822             set(currentInstruction[1].u.operand, getById);
823             aliases.recordGetById(getById);
824
825             NEXT_OPCODE(op_get_by_id);
826         }
827
828         case op_put_by_id: {
829             NodeIndex value = get(currentInstruction[3].u.operand);
830             NodeIndex base = get(currentInstruction[1].u.operand);
831             unsigned identifier = currentInstruction[2].u.operand;
832             bool direct = currentInstruction[8].u.operand;
833
834             if (direct) {
835                 NodeIndex putByIdDirect = addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
836                 aliases.recordPutByIdDirect(putByIdDirect);
837             } else {
838                 NodeIndex putById = addToGraph(PutById, OpInfo(identifier), base, value);
839                 aliases.recordPutById(putById);
840             }
841
842             NEXT_OPCODE(op_put_by_id);
843         }
844
845         case op_get_global_var: {
846             NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
847             set(currentInstruction[1].u.operand, getGlobalVar);
848             NEXT_OPCODE(op_get_global_var);
849         }
850
851         case op_put_global_var: {
852             NodeIndex value = get(currentInstruction[2].u.operand);
853             addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
854             NEXT_OPCODE(op_put_global_var);
855         }
856
857         // === Block terminators. ===
858
859         case op_jmp: {
860             unsigned relativeOffset = currentInstruction[1].u.operand;
861             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
862             LAST_OPCODE(op_jmp);
863         }
864
865         case op_loop: {
866             unsigned relativeOffset = currentInstruction[1].u.operand;
867             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
868             LAST_OPCODE(op_loop);
869         }
870
871         case op_jtrue: {
872             unsigned relativeOffset = currentInstruction[2].u.operand;
873             NodeIndex condition = get(currentInstruction[1].u.operand);
874             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jtrue)), condition);
875             LAST_OPCODE(op_jtrue);
876         }
877
878         case op_jfalse: {
879             unsigned relativeOffset = currentInstruction[2].u.operand;
880             NodeIndex condition = get(currentInstruction[1].u.operand);
881             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jfalse)), OpInfo(m_currentIndex + relativeOffset), condition);
882             LAST_OPCODE(op_jfalse);
883         }
884
885         case op_loop_if_true: {
886             unsigned relativeOffset = currentInstruction[2].u.operand;
887             NodeIndex condition = get(currentInstruction[1].u.operand);
888             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_true)), condition);
889             LAST_OPCODE(op_loop_if_true);
890         }
891
892         case op_loop_if_false: {
893             unsigned relativeOffset = currentInstruction[2].u.operand;
894             NodeIndex condition = get(currentInstruction[1].u.operand);
895             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_false)), OpInfo(m_currentIndex + relativeOffset), condition);
896             LAST_OPCODE(op_loop_if_false);
897         }
898
899         case op_jeq_null: {
900             unsigned relativeOffset = currentInstruction[2].u.operand;
901             NodeIndex value = get(currentInstruction[1].u.operand);
902             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
903             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
904             LAST_OPCODE(op_jeq_null);
905         }
906
907         case op_jneq_null: {
908             unsigned relativeOffset = currentInstruction[2].u.operand;
909             NodeIndex value = get(currentInstruction[1].u.operand);
910             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
911             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
912             LAST_OPCODE(op_jneq_null);
913         }
914
915         case op_jnless: {
916             unsigned relativeOffset = currentInstruction[3].u.operand;
917             NodeIndex op1 = get(currentInstruction[1].u.operand);
918             NodeIndex op2 = get(currentInstruction[2].u.operand);
919             NodeIndex condition = addToGraph(CompareLess, op1, op2);
920             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnless)), OpInfo(m_currentIndex + relativeOffset), condition);
921             LAST_OPCODE(op_jnless);
922         }
923
924         case op_jnlesseq: {
925             unsigned relativeOffset = currentInstruction[3].u.operand;
926             NodeIndex op1 = get(currentInstruction[1].u.operand);
927             NodeIndex op2 = get(currentInstruction[2].u.operand);
928             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
929             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnlesseq)), OpInfo(m_currentIndex + relativeOffset), condition);
930             LAST_OPCODE(op_jnlesseq);
931         }
932
933         case op_jless: {
934             unsigned relativeOffset = currentInstruction[3].u.operand;
935             NodeIndex op1 = get(currentInstruction[1].u.operand);
936             NodeIndex op2 = get(currentInstruction[2].u.operand);
937             NodeIndex condition = addToGraph(CompareLess, op1, op2);
938             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jless)), condition);
939             LAST_OPCODE(op_jless);
940         }
941
942         case op_jlesseq: {
943             unsigned relativeOffset = currentInstruction[3].u.operand;
944             NodeIndex op1 = get(currentInstruction[1].u.operand);
945             NodeIndex op2 = get(currentInstruction[2].u.operand);
946             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
947             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jlesseq)), condition);
948             LAST_OPCODE(op_jlesseq);
949         }
950
951         case op_loop_if_less: {
952             unsigned relativeOffset = currentInstruction[3].u.operand;
953             NodeIndex op1 = get(currentInstruction[1].u.operand);
954             NodeIndex op2 = get(currentInstruction[2].u.operand);
955             NodeIndex condition = addToGraph(CompareLess, op1, op2);
956             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_less)), condition);
957             LAST_OPCODE(op_loop_if_less);
958         }
959
960         case op_loop_if_lesseq: {
961             unsigned relativeOffset = currentInstruction[3].u.operand;
962             NodeIndex op1 = get(currentInstruction[1].u.operand);
963             NodeIndex op2 = get(currentInstruction[2].u.operand);
964             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
965             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_lesseq)), condition);
966             LAST_OPCODE(op_loop_if_lesseq);
967         }
968
969         case op_ret: {
970             addToGraph(Return, get(currentInstruction[1].u.operand));
971             LAST_OPCODE(op_ret);
972         }
973
974         default:
975             // Parse failed!
976             return false;
977         }
978     }
979 }
980
981 template<ByteCodeParser::PhiStackType stackType>
982 void ByteCodeParser::processPhiStack()
983 {
984     Vector<PhiStackEntry, 16>& phiStack = (stackType == ArgumentPhiStack) ? m_argumentPhiStack : m_localPhiStack;
985
986     while (!phiStack.isEmpty()) {
987         PhiStackEntry entry = phiStack.last();
988         phiStack.removeLast();
989         
990         Node& phiNode = m_graph[entry.m_phi];
991         PredecessorList& predecessors = entry.m_block->m_predecessors;
992         unsigned varNo = entry.m_varNo;
993
994         for (size_t i = 0; i < predecessors.size(); ++i) {
995             BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
996
997             VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_arguments[varNo] : predecessorBlock->m_locals[varNo];
998
999             NodeIndex valueInPredecessor = var.value;
1000             if (valueInPredecessor == NoNode) {
1001                 valueInPredecessor = addToGraph(Phi);
1002                 var.value = valueInPredecessor;
1003                 phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
1004             } else if (m_graph[valueInPredecessor].op == GetLocal)
1005                 valueInPredecessor = m_graph[valueInPredecessor].child1;
1006             ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi);
1007
1008             if (phiNode.refCount())
1009                 m_graph.ref(valueInPredecessor);
1010
1011             if (phiNode.child1 == NoNode) {
1012                 phiNode.child1 = valueInPredecessor;
1013                 continue;
1014             }
1015             if (phiNode.child2 == NoNode) {
1016                 phiNode.child2 = valueInPredecessor;
1017                 continue;
1018             }
1019             if (phiNode.child3 == NoNode) {
1020                 phiNode.child3 = valueInPredecessor;
1021                 continue;
1022             }
1023
1024             NodeIndex newPhi = addToGraph(Phi);
1025             Node& newPhiNode = m_graph[newPhi];
1026             if (phiNode.refCount())
1027                 m_graph.ref(newPhi);
1028
1029             newPhiNode.child1 = phiNode.child1;
1030             newPhiNode.child2 = phiNode.child2;
1031             newPhiNode.child3 = phiNode.child3;
1032
1033             phiNode.child1 = newPhi;
1034             phiNode.child1 = valueInPredecessor;
1035             phiNode.child3 = NoNode;
1036         }
1037     }
1038 }
1039
1040 void ByteCodeParser::setupPredecessors()
1041 {
1042     for (BlockIndex index = 0; index < m_graph.m_blocks.size(); ++index) {
1043         BasicBlock* block = m_graph.m_blocks[index].get();
1044         ASSERT(block->end != NoNode);
1045         Node& node = m_graph[block->end - 1];
1046         ASSERT(node.isTerminal());
1047
1048         if (node.isJump())
1049             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1050         else if (node.isBranch()) {
1051             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1052             m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
1053         }
1054     }
1055 }
1056
1057 void ByteCodeParser::allocateVirtualRegisters()
1058 {
1059     ScoreBoard scoreBoard(m_graph, m_preservedVars);
1060     unsigned sizeExcludingPhiNodes = m_graph.m_blocks.last()->end;
1061     for (size_t i = 0; i < sizeExcludingPhiNodes; ++i) {
1062         Node& node = m_graph[i];
1063         if (!node.shouldGenerate())
1064             continue;
1065
1066         // GetLocal nodes are effectively phi nodes in the graph, referencing
1067         // results from prior blocks.
1068         if (node.op != GetLocal) {
1069             // First, call use on all of the current node's children, then
1070             // allocate a VirtualRegister for this node. We do so in this
1071             // order so that if a child is on its last use, and a
1072             // VirtualRegister is freed, then it may be reused for node.
1073             scoreBoard.use(node.child1);
1074             scoreBoard.use(node.child2);
1075             scoreBoard.use(node.child3);
1076         }
1077
1078         if (!node.hasResult())
1079             continue;
1080
1081         node.setVirtualRegister(scoreBoard.allocate());
1082         // 'mustGenerate' nodes have their useCount artificially elevated,
1083         // call use now to account for this.
1084         if (node.mustGenerate())
1085             scoreBoard.use(i);
1086     }
1087
1088     // 'm_numCalleeRegisters' is the number of locals and temporaries allocated
1089     // for the function (and checked for on entry). Since we perform a new and
1090     // different allocation of temporaries, more registers may now be required.
1091     unsigned calleeRegisters = scoreBoard.allocatedCount() + m_preservedVars;
1092     if ((unsigned)m_codeBlock->m_numCalleeRegisters < calleeRegisters)
1093         m_codeBlock->m_numCalleeRegisters = calleeRegisters;
1094 }
1095
1096 bool ByteCodeParser::parse()
1097 {
1098     // Set during construction.
1099     ASSERT(!m_currentIndex);
1100
1101     for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
1102         // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions.
1103         unsigned limit = jumpTargetIndex < m_codeBlock->numberOfJumpTargets() ? m_codeBlock->jumpTarget(jumpTargetIndex) : m_codeBlock->instructions().size();
1104         ASSERT(m_currentIndex < limit);
1105
1106         // Loop until we reach the current limit (i.e. next jump target).
1107         do {
1108             OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
1109             m_currentBlock = block.get();
1110             m_graph.m_blocks.append(block.release());
1111
1112             if (!parseBlock(limit))
1113                 return false;
1114             // We should not have gone beyond the limit.
1115             ASSERT(m_currentIndex <= limit);
1116
1117             m_currentBlock->end = m_graph.size();
1118         } while (m_currentIndex < limit);
1119     }
1120
1121     // Should have reached the end of the instructions.
1122     ASSERT(m_currentIndex == m_codeBlock->instructions().size());
1123
1124     setupPredecessors();
1125     processPhiStack<LocalPhiStack>();
1126     processPhiStack<ArgumentPhiStack>();
1127
1128     allocateVirtualRegisters();
1129
1130 #if DFG_DEBUG_VERBOSE
1131     m_graph.dump(m_codeBlock);
1132 #endif
1133
1134     return true;
1135 }
1136
1137 bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
1138 {
1139 #if DFG_DEBUG_LOCAL_DISBALE
1140     UNUSED_PARAM(graph);
1141     UNUSED_PARAM(globalData);
1142     UNUSED_PARAM(codeBlock);
1143     return false;
1144 #else
1145     return ByteCodeParser(globalData, codeBlock, graph).parse();
1146 #endif
1147 }
1148
1149 } } // namespace JSC::DFG
1150
1151 #endif