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