DFG does not speculate aggressively enough on put_by_id
[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 "DFGCapabilities.h"
32 #include "CodeBlock.h"
33 #include <wtf/HashMap.h>
34 #include <wtf/MathExtras.h>
35
36 namespace JSC { namespace DFG {
37
38 // === ByteCodeParser ===
39 //
40 // This class is used to compile the dataflow graph from a CodeBlock.
41 class ByteCodeParser {
42 public:
43     ByteCodeParser(JSGlobalData* globalData, CodeBlock* codeBlock, CodeBlock* profiledBlock, Graph& graph)
44         : m_globalData(globalData)
45         , m_codeBlock(codeBlock)
46         , m_profiledBlock(profiledBlock)
47         , m_graph(graph)
48         , m_currentIndex(0)
49         , m_parseFailed(false)
50         , m_constantUndefined(UINT_MAX)
51         , m_constantNull(UINT_MAX)
52         , m_constantNaN(UINT_MAX)
53         , m_constant1(UINT_MAX)
54         , m_constants(codeBlock->numberOfConstantRegisters())
55         , m_numArguments(codeBlock->m_numParameters)
56         , m_numLocals(codeBlock->m_numCalleeRegisters)
57         , m_preservedVars(codeBlock->m_numVars)
58         , m_parameterSlots(0)
59         , m_numPassedVarArgs(0)
60         , m_globalResolveNumber(0)
61     {
62         ASSERT(m_profiledBlock);
63     }
64
65     // Parse a full CodeBlock of bytecode.
66     bool parse();
67
68 private:
69     // Helper for min and max.
70     bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg);
71     
72     // Handle intrinsic functions.
73     bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int firstArg, int lastArg);
74     // Parse a single basic block of bytecode instructions.
75     bool parseBlock(unsigned limit);
76     // Setup predecessor links in the graph's BasicBlocks.
77     void setupPredecessors();
78     // Link GetLocal & SetLocal nodes, to ensure live values are generated.
79     enum PhiStackType {
80         LocalPhiStack,
81         ArgumentPhiStack
82     };
83     template<PhiStackType stackType>
84     void processPhiStack();
85     // Add spill locations to nodes.
86     void allocateVirtualRegisters();
87     
88     VariableAccessData* newVariableAccessData(int operand)
89     {
90         ASSERT(operand < FirstConstantRegisterIndex);
91         
92         m_graph.m_variableAccessData.append(VariableAccessData(static_cast<VirtualRegister>(operand)));
93         return &m_graph.m_variableAccessData.last();
94     }
95     
96     // Get/Set the operands/result of a bytecode instruction.
97     NodeIndex get(int operand)
98     {
99         // Is this a constant?
100         if (operand >= FirstConstantRegisterIndex) {
101             unsigned constant = operand - FirstConstantRegisterIndex;
102             ASSERT(constant < m_constants.size());
103             return getJSConstant(constant);
104         }
105
106         // Is this an argument?
107         if (operandIsArgument(operand))
108             return getArgument(operand);
109
110         // Must be a local.
111         return getLocal((unsigned)operand);
112     }
113     void set(int operand, NodeIndex value)
114     {
115         // Is this an argument?
116         if (operandIsArgument(operand)) {
117             setArgument(operand, value);
118             return;
119         }
120
121         // Must be a local.
122         setLocal((unsigned)operand, value);
123     }
124
125     // Used in implementing get/set, above, where the operand is a local variable.
126     NodeIndex getLocal(unsigned operand)
127     {
128         NodeIndex nodeIndex = m_currentBlock->m_localsAtTail[operand].value;
129
130         if (nodeIndex != NoNode) {
131             Node& node = m_graph[nodeIndex];
132             if (node.op == GetLocal)
133                 return nodeIndex;
134             ASSERT(node.op == SetLocal);
135             return node.child1();
136         }
137
138         // Check for reads of temporaries from prior blocks,
139         // expand m_preservedVars to cover these.
140         m_preservedVars = std::max(m_preservedVars, operand + 1);
141         
142         VariableAccessData* variableAccessData = newVariableAccessData(operand);
143         
144         NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
145         m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
146         nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
147         m_currentBlock->m_localsAtTail[operand].value = nodeIndex;
148         
149         m_currentBlock->m_localsAtHead[operand].setFirstTime(nodeIndex);
150         
151         return nodeIndex;
152     }
153     void setLocal(unsigned operand, NodeIndex value)
154     {
155         m_currentBlock->m_localsAtTail[operand].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
156     }
157
158     // Used in implementing get/set, above, where the operand is an argument.
159     NodeIndex getArgument(unsigned operand)
160     {
161         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
162         ASSERT(argument < m_numArguments);
163
164         NodeIndex nodeIndex = m_currentBlock->m_argumentsAtTail[argument].value;
165
166         if (nodeIndex != NoNode) {
167             Node& node = m_graph[nodeIndex];
168             if (node.op == SetArgument) {
169                 // We're getting an argument in the first basic block; link
170                 // the GetLocal to the SetArgument.
171                 ASSERT(node.local() == static_cast<VirtualRegister>(operand));
172                 nodeIndex = addToGraph(GetLocal, OpInfo(node.variableAccessData()), nodeIndex);
173                 m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
174                 return nodeIndex;
175             }
176             
177             if (node.op == GetLocal)
178                 return nodeIndex;
179             
180             ASSERT(node.op == SetLocal);
181             return node.child1();
182         }
183         
184         VariableAccessData* variableAccessData = newVariableAccessData(operand);
185
186         NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
187         m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
188         nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
189         m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
190         
191         m_currentBlock->m_argumentsAtHead[argument].setFirstTime(nodeIndex);
192         
193         return nodeIndex;
194     }
195     void setArgument(int operand, NodeIndex value)
196     {
197         unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
198         ASSERT(argument < m_numArguments);
199
200         m_currentBlock->m_argumentsAtTail[argument].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
201     }
202
203     // Get an operand, and perform a ToInt32/ToNumber conversion on it.
204     NodeIndex getToInt32(int operand)
205     {
206         return toInt32(get(operand));
207     }
208     NodeIndex getToNumber(int operand)
209     {
210         return toNumber(get(operand));
211     }
212
213     // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
214     NodeIndex toInt32(NodeIndex index)
215     {
216         Node& node = m_graph[index];
217
218         if (node.hasInt32Result())
219             return index;
220
221         if (node.op == UInt32ToNumber)
222             return node.child1();
223
224         // Check for numeric constants boxed as JSValues.
225         if (node.op == JSConstant) {
226             JSValue v = valueOfJSConstant(index);
227             if (v.isInt32())
228                 return getJSConstant(node.constantNumber());
229             // FIXME: We could convert the double ToInteger at this point.
230         }
231
232         return addToGraph(ValueToInt32, index);
233     }
234
235     // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble.
236     NodeIndex toNumber(NodeIndex index)
237     {
238         Node& node = m_graph[index];
239
240         if (node.hasNumberResult())
241             return index;
242
243         if (node.op == JSConstant) {
244             JSValue v = valueOfJSConstant(index);
245             if (v.isNumber())
246                 return getJSConstant(node.constantNumber());
247         }
248
249         return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index);
250     }
251
252     NodeIndex getJSConstant(unsigned constant)
253     {
254         NodeIndex index = m_constants[constant].asJSValue;
255         if (index != NoNode)
256             return index;
257
258         NodeIndex resultIndex = addToGraph(JSConstant, OpInfo(constant));
259         m_constants[constant].asJSValue = resultIndex;
260         return resultIndex;
261     }
262
263     // Helper functions to get/set the this value.
264     NodeIndex getThis()
265     {
266         return getArgument(m_codeBlock->thisRegister());
267     }
268     void setThis(NodeIndex value)
269     {
270         setArgument(m_codeBlock->thisRegister(), value);
271     }
272
273     // Convenience methods for checking nodes for constants.
274     bool isJSConstant(NodeIndex index)
275     {
276         return m_graph[index].op == JSConstant;
277     }
278     bool isInt32Constant(NodeIndex nodeIndex)
279     {
280         return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
281     }
282     bool isSmallInt32Constant(NodeIndex nodeIndex)
283     {
284         if (!isJSConstant(nodeIndex))
285             return false;
286         JSValue value = valueOfJSConstant(nodeIndex);
287         if (!value.isInt32())
288             return false;
289         int32_t intValue = value.asInt32();
290         return intValue >= -5 && intValue <= 5;
291     }
292     // Convenience methods for getting constant values.
293     JSValue valueOfJSConstant(NodeIndex index)
294     {
295         ASSERT(isJSConstant(index));
296         return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
297     }
298     int32_t valueOfInt32Constant(NodeIndex nodeIndex)
299     {
300         ASSERT(isInt32Constant(nodeIndex));
301         return valueOfJSConstant(nodeIndex).asInt32();
302     }
303
304     // This method returns a JSConstant with the value 'undefined'.
305     NodeIndex constantUndefined()
306     {
307         // Has m_constantUndefined been set up yet?
308         if (m_constantUndefined == UINT_MAX) {
309             // Search the constant pool for undefined, if we find it, we can just reuse this!
310             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
311             for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {
312                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);
313                 if (testMe.isUndefined())
314                     return getJSConstant(m_constantUndefined);
315             }
316
317             // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
318             ASSERT(m_constants.size() == numberOfConstants);
319             m_codeBlock->addConstant(jsUndefined());
320             m_constants.append(ConstantRecord());
321             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
322         }
323
324         // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
325         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());
326         return getJSConstant(m_constantUndefined);
327     }
328
329     // This method returns a JSConstant with the value 'null'.
330     NodeIndex constantNull()
331     {
332         // Has m_constantNull been set up yet?
333         if (m_constantNull == UINT_MAX) {
334             // Search the constant pool for null, if we find it, we can just reuse this!
335             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
336             for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {
337                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);
338                 if (testMe.isNull())
339                     return getJSConstant(m_constantNull);
340             }
341
342             // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
343             ASSERT(m_constants.size() == numberOfConstants);
344             m_codeBlock->addConstant(jsNull());
345             m_constants.append(ConstantRecord());
346             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
347         }
348
349         // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
350         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());
351         return getJSConstant(m_constantNull);
352     }
353
354     // This method returns a DoubleConstant with the value 1.
355     NodeIndex one()
356     {
357         // Has m_constant1 been set up yet?
358         if (m_constant1 == UINT_MAX) {
359             // Search the constant pool for the value 1, if we find it, we can just reuse this!
360             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
361             for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
362                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
363                 if (testMe.isInt32() && testMe.asInt32() == 1)
364                     return getJSConstant(m_constant1);
365             }
366
367             // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
368             ASSERT(m_constants.size() == numberOfConstants);
369             m_codeBlock->addConstant(jsNumber(1));
370             m_constants.append(ConstantRecord());
371             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
372         }
373
374         // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
375         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
376         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
377         return getJSConstant(m_constant1);
378     }
379     
380     // This method returns a DoubleConstant with the value NaN.
381     NodeIndex constantNaN()
382     {
383         JSValue nan = jsNaN();
384         
385         // Has m_constantNaN been set up yet?
386         if (m_constantNaN == UINT_MAX) {
387             // Search the constant pool for the value NaN, if we find it, we can just reuse this!
388             unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
389             for (m_constantNaN = 0; m_constantNaN < numberOfConstants; ++m_constantNaN) {
390                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN);
391                 if (JSValue::encode(testMe) == JSValue::encode(nan))
392                     return getJSConstant(m_constantNaN);
393             }
394
395             // Add the value nan to the CodeBlock's constants, and add a corresponding slot in m_constants.
396             ASSERT(m_constants.size() == numberOfConstants);
397             m_codeBlock->addConstant(nan);
398             m_constants.append(ConstantRecord());
399             ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
400         }
401
402         // m_constantNaN must refer to an entry in the CodeBlock's constant pool that has the value nan.
403         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).isDouble());
404         ASSERT(isnan(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).asDouble()));
405         return getJSConstant(m_constantNaN);
406     }
407     
408     NodeIndex cellConstant(JSCell* cell)
409     {
410         HashMap<JSCell*, unsigned>::iterator iter = m_cellConstants.find(cell);
411         if (iter != m_cellConstants.end())
412             return getJSConstant(iter->second);
413         
414         m_codeBlock->addConstant(cell);
415         m_constants.append(ConstantRecord());
416         ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
417         
418         return getJSConstant(m_codeBlock->numberOfConstantRegisters() - 1);
419     }
420     
421     CodeOrigin currentCodeOrigin()
422     {
423         return CodeOrigin(m_currentIndex);
424     }
425
426     // These methods create a node and add it to the graph. If nodes of this type are
427     // 'mustGenerate' then the node  will implicitly be ref'ed to ensure generation.
428     NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
429     {
430         NodeIndex resultIndex = (NodeIndex)m_graph.size();
431         m_graph.append(Node(op, currentCodeOrigin(), child1, child2, child3));
432
433         if (op & NodeMustGenerate)
434             m_graph.ref(resultIndex);
435         return resultIndex;
436     }
437     NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
438     {
439         NodeIndex resultIndex = (NodeIndex)m_graph.size();
440         m_graph.append(Node(op, currentCodeOrigin(), info, child1, child2, child3));
441
442         if (op & NodeMustGenerate)
443             m_graph.ref(resultIndex);
444         return resultIndex;
445     }
446     NodeIndex addToGraph(NodeType op, OpInfo info1, OpInfo info2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
447     {
448         NodeIndex resultIndex = (NodeIndex)m_graph.size();
449         m_graph.append(Node(op, currentCodeOrigin(), info1, info2, child1, child2, child3));
450
451         if (op & NodeMustGenerate)
452             m_graph.ref(resultIndex);
453         return resultIndex;
454     }
455     
456     NodeIndex addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2)
457     {
458         NodeIndex resultIndex = (NodeIndex)m_graph.size();
459         m_graph.append(Node(Node::VarArg, op, currentCodeOrigin(), info1, info2, m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs));
460         
461         m_numPassedVarArgs = 0;
462         
463         if (op & NodeMustGenerate)
464             m_graph.ref(resultIndex);
465         return resultIndex;
466     }
467     void addVarArgChild(NodeIndex child)
468     {
469         m_graph.m_varArgChildren.append(child);
470         m_numPassedVarArgs++;
471     }
472     
473     NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
474     {
475         Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
476
477         PredictedType prediction = PredictNone;
478         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
479             prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
480         
481         addVarArgChild(get(currentInstruction[1].u.operand));
482         int argCount = currentInstruction[2].u.operand;
483         int registerOffset = currentInstruction[3].u.operand;
484         int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
485         for (int argIdx = firstArg + (op == Construct ? 1 : 0); argIdx < firstArg + argCount; argIdx++)
486             addVarArgChild(get(argIdx));
487         NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
488         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
489             set(putInstruction[1].u.operand, call);
490         if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
491             m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
492         return call;
493     }
494
495     PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
496     {
497         UNUSED_PARAM(nodeIndex);
498         
499         ValueProfile* profile = m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
500         ASSERT(profile);
501         PredictedType prediction = profile->computeUpdatedPrediction();
502 #if ENABLE(DFG_DEBUG_VERBOSE)
503         printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
504 #endif
505         
506         if (prediction == PredictNone) {
507             // We have no information about what values this node generates. Give up
508             // on executing this code, since we're likely to do more damage than good.
509             addToGraph(ForceOSRExit);
510         }
511         
512         return prediction;
513     }
514     
515     PredictedType getPrediction()
516     {
517         return getPrediction(m_graph.size(), m_currentIndex);
518     }
519
520     NodeIndex makeSafe(NodeIndex nodeIndex)
521     {
522         if (!m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
523             return nodeIndex;
524         
525 #if ENABLE(DFG_DEBUG_VERBOSE)
526         printf("Making %s @%u safe at bc#%u because slow-case counter is at %u\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
527 #endif
528         
529         switch (m_graph[nodeIndex].op) {
530         case UInt32ToNumber:
531         case ArithAdd:
532         case ArithSub:
533         case ValueAdd:
534         case ArithMod: // for ArithMode "MayOverflow" means we tried to divide by zero, or we saw double.
535             m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow);
536             break;
537             
538         case ArithMul:
539             if (m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex))
540                 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
541             else
542                 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayNegZero);
543             break;
544             
545         default:
546             ASSERT_NOT_REACHED();
547             break;
548         }
549         
550         return nodeIndex;
551     }
552     
553     NodeIndex makeDivSafe(NodeIndex nodeIndex)
554     {
555         ASSERT(m_graph[nodeIndex].op == ArithDiv);
556         
557         // The main slow case counter for op_div in the old JIT counts only when
558         // the operands are not numbers. We don't care about that since we already
559         // have speculations in place that take care of that separately. We only
560         // care about when the outcome of the division is not an integer, which
561         // is what the special fast case counter tells us.
562         
563         if (!m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex))
564             return nodeIndex;
565         
566         m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
567         
568         return nodeIndex;
569     }
570     
571     JSGlobalData* m_globalData;
572     CodeBlock* m_codeBlock;
573     CodeBlock* m_profiledBlock;
574     Graph& m_graph;
575
576     // The current block being generated.
577     BasicBlock* m_currentBlock;
578     // The bytecode index of the current instruction being generated.
579     unsigned m_currentIndex;
580
581     // Record failures due to unimplemented functionality or regressions.
582     bool m_parseFailed;
583
584     // We use these values during code generation, and to avoid the need for
585     // special handling we make sure they are available as constants in the
586     // CodeBlock's constant pool. These variables are initialized to
587     // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
588     // constant pool, as necessary.
589     unsigned m_constantUndefined;
590     unsigned m_constantNull;
591     unsigned m_constantNaN;
592     unsigned m_constant1;
593     HashMap<JSCell*, unsigned> m_cellConstants;
594
595     // A constant in the constant pool may be represented by more than one
596     // node in the graph, depending on the context in which it is being used.
597     struct ConstantRecord {
598         ConstantRecord()
599             : asInt32(NoNode)
600             , asNumeric(NoNode)
601             , asJSValue(NoNode)
602         {
603         }
604
605         NodeIndex asInt32;
606         NodeIndex asNumeric;
607         NodeIndex asJSValue;
608     };
609
610     // Track the index of the node whose result is the current value for every
611     // register value in the bytecode - argument, local, and temporary.
612     Vector<ConstantRecord, 16> m_constants;
613
614     // The number of arguments passed to the function.
615     unsigned m_numArguments;
616     // The number of locals (vars + temporaries) used in the function.
617     unsigned m_numLocals;
618     // The number of registers we need to preserve across BasicBlock boundaries;
619     // typically equal to the number vars, but we expand this to cover all
620     // temporaries that persist across blocks (dues to ?:, &&, ||, etc).
621     unsigned m_preservedVars;
622     // The number of slots (in units of sizeof(Register)) that we need to
623     // preallocate for calls emanating from this frame. This includes the
624     // size of the CallFrame, only if this is not a leaf function.  (I.e.
625     // this is 0 if and only if this function is a leaf.)
626     unsigned m_parameterSlots;
627     // The number of var args passed to the next var arg node.
628     unsigned m_numPassedVarArgs;
629     // The index in the global resolve info.
630     unsigned m_globalResolveNumber;
631
632     struct PhiStackEntry {
633         PhiStackEntry(BasicBlock* block, NodeIndex phi, unsigned varNo)
634             : m_block(block)
635             , m_phi(phi)
636             , m_varNo(varNo)
637         {
638         }
639
640         BasicBlock* m_block;
641         NodeIndex m_phi;
642         unsigned m_varNo;
643     };
644     Vector<PhiStackEntry, 16> m_argumentPhiStack;
645     Vector<PhiStackEntry, 16> m_localPhiStack;
646     
647     Vector<Node*, 16> m_reusableNodeStack;
648 };
649
650 #define NEXT_OPCODE(name) \
651     m_currentIndex += OPCODE_LENGTH(name); \
652     continue
653
654 #define LAST_OPCODE(name) \
655     m_currentIndex += OPCODE_LENGTH(name); \
656     return !m_parseFailed
657
658 bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg)
659 {
660     if (!usesResult)
661         return true;
662
663     if (lastArg == firstArg) {
664         set(resultOperand, constantNaN());
665         return true;
666     }
667      
668     if (lastArg == firstArg + 1) {
669         set(resultOperand, getToNumber(firstArg + 1));
670         return true;
671     }
672     
673     if (lastArg == firstArg + 2) {
674         set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
675         return true;
676     }
677     
678     // Don't handle >=3 arguments for now.
679     return false;
680 }
681
682 bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg)
683 {
684     switch (intrinsic) {
685     case AbsIntrinsic: {
686         if (!usesResult) {
687             // There is no such thing as executing abs for effect, so this
688             // is dead code.
689             return true;
690         }
691         
692         // We don't care about the this argument. If we don't have a first
693         // argument then make this JSConstant(NaN).
694         int absArg = firstArg + 1;
695         if (absArg > lastArg)
696             set(resultOperand, constantNaN());
697         else
698             set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(absArg)));
699         return true;
700     }
701         
702     case MinIntrinsic:
703         return handleMinMax(usesResult, resultOperand, ArithMin, firstArg, lastArg);
704         
705     case MaxIntrinsic:
706         return handleMinMax(usesResult, resultOperand, ArithMax, firstArg, lastArg);
707         
708     case SqrtIntrinsic: {
709         if (!usesResult)
710             return true;
711         
712         if (firstArg == lastArg) {
713             set(resultOperand, constantNaN());
714             return true;
715         }
716         
717         set(resultOperand, addToGraph(ArithSqrt, getToNumber(firstArg + 1)));
718         return true;
719     }
720         
721     default:
722         ASSERT(intrinsic == NoIntrinsic);
723         return false;
724     }
725 }
726
727 bool ByteCodeParser::parseBlock(unsigned limit)
728 {
729     // No need to reset state initially, since it has been set by the constructor.
730     if (m_currentIndex) {
731         for (unsigned i = 0; i < m_constants.size(); ++i)
732             m_constants[i] = ConstantRecord();
733     }
734     
735     // If we are the first basic block, introduce markers for arguments. This allows
736     // us to track if a use of an argument may use the actual argument passed, as
737     // opposed to using a value we set explicitly.
738     if (!m_currentIndex) {
739         m_graph.m_arguments.resize(m_numArguments);
740         for (unsigned argument = 0; argument < m_numArguments; ++argument) {
741             NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize)));
742             m_graph.m_arguments[argument] = setArgument;
743             m_currentBlock->m_argumentsAtHead[argument].setFirstTime(setArgument);
744             m_currentBlock->m_argumentsAtTail[argument].setFirstTime(setArgument);
745         }
746     }
747
748     Interpreter* interpreter = m_globalData->interpreter;
749     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
750     unsigned blockBegin = m_currentIndex;
751     while (true) {
752         // Don't extend over jump destinations.
753         if (m_currentIndex == limit) {
754             addToGraph(Jump, OpInfo(m_currentIndex));
755             return !m_parseFailed;
756         }
757         
758         // Switch on the current bytecode opcode.
759         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
760         OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
761         switch (opcodeID) {
762
763         // === Function entry opcodes ===
764
765         case op_enter:
766             // Initialize all locals to undefined.
767             for (int i = 0; i < m_codeBlock->m_numVars; ++i)
768                 set(i, constantUndefined());
769             NEXT_OPCODE(op_enter);
770
771         case op_convert_this: {
772             NodeIndex op1 = getThis();
773             setThis(addToGraph(ConvertThis, op1));
774             NEXT_OPCODE(op_convert_this);
775         }
776
777         case op_create_this: {
778             NodeIndex op1 = get(currentInstruction[2].u.operand);
779             set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1));
780             NEXT_OPCODE(op_create_this);
781         }
782             
783         case op_new_object: {
784             set(currentInstruction[1].u.operand, addToGraph(NewObject));
785             NEXT_OPCODE(op_new_object);
786         }
787             
788         case op_new_array: {
789             int startOperand = currentInstruction[2].u.operand;
790             int numOperands = currentInstruction[3].u.operand;
791             for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
792                 addVarArgChild(get(operandIdx));
793             set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
794             NEXT_OPCODE(op_new_array);
795         }
796             
797         case op_new_array_buffer: {
798             int startConstant = currentInstruction[2].u.operand;
799             int numConstants = currentInstruction[3].u.operand;
800             set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(startConstant), OpInfo(numConstants)));
801             NEXT_OPCODE(op_new_array_buffer);
802         }
803             
804         case op_new_regexp: {
805             set(currentInstruction[1].u.operand, addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
806             NEXT_OPCODE(op_new_regexp);
807         }
808             
809         case op_get_callee: {
810             set(currentInstruction[1].u.operand, addToGraph(GetCallee));
811             NEXT_OPCODE(op_get_callee);
812         }
813
814         // === Bitwise operations ===
815
816         case op_bitand: {
817             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
818             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
819             set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
820             NEXT_OPCODE(op_bitand);
821         }
822
823         case op_bitor: {
824             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
825             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
826             set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
827             NEXT_OPCODE(op_bitor);
828         }
829
830         case op_bitxor: {
831             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
832             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
833             set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
834             NEXT_OPCODE(op_bitxor);
835         }
836
837         case op_rshift: {
838             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
839             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
840             NodeIndex result;
841             // Optimize out shifts by zero.
842             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
843                 result = op1;
844             else
845                 result = addToGraph(BitRShift, op1, op2);
846             set(currentInstruction[1].u.operand, result);
847             NEXT_OPCODE(op_rshift);
848         }
849
850         case op_lshift: {
851             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
852             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
853             NodeIndex result;
854             // Optimize out shifts by zero.
855             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
856                 result = op1;
857             else
858                 result = addToGraph(BitLShift, op1, op2);
859             set(currentInstruction[1].u.operand, result);
860             NEXT_OPCODE(op_lshift);
861         }
862
863         case op_urshift: {
864             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
865             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
866             NodeIndex result;
867             // The result of a zero-extending right shift is treated as an unsigned value.
868             // This means that if the top bit is set, the result is not in the int32 range,
869             // and as such must be stored as a double. If the shift amount is a constant,
870             // we may be able to optimize.
871             if (isInt32Constant(op2)) {
872                 // If we know we are shifting by a non-zero amount, then since the operation
873                 // zero fills we know the top bit of the result must be zero, and as such the
874                 // result must be within the int32 range. Conversely, if this is a shift by
875                 // zero, then the result may be changed by the conversion to unsigned, but it
876                 // is not necessary to perform the shift!
877                 if (valueOfInt32Constant(op2) & 0x1f)
878                     result = addToGraph(BitURShift, op1, op2);
879                 else
880                     result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), op1));
881             }  else {
882                 // Cannot optimize at this stage; shift & potentially rebox as a double.
883                 result = addToGraph(BitURShift, op1, op2);
884                 result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result));
885             }
886             set(currentInstruction[1].u.operand, result);
887             NEXT_OPCODE(op_urshift);
888         }
889
890         // === Increment/Decrement opcodes ===
891
892         case op_pre_inc: {
893             unsigned srcDst = currentInstruction[1].u.operand;
894             NodeIndex op = getToNumber(srcDst);
895             set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
896             NEXT_OPCODE(op_pre_inc);
897         }
898
899         case op_post_inc: {
900             unsigned result = currentInstruction[1].u.operand;
901             unsigned srcDst = currentInstruction[2].u.operand;
902             NodeIndex op = getToNumber(srcDst);
903             set(result, op);
904             set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
905             NEXT_OPCODE(op_post_inc);
906         }
907
908         case op_pre_dec: {
909             unsigned srcDst = currentInstruction[1].u.operand;
910             NodeIndex op = getToNumber(srcDst);
911             set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
912             NEXT_OPCODE(op_pre_dec);
913         }
914
915         case op_post_dec: {
916             unsigned result = currentInstruction[1].u.operand;
917             unsigned srcDst = currentInstruction[2].u.operand;
918             NodeIndex op = getToNumber(srcDst);
919             set(result, op);
920             set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
921             NEXT_OPCODE(op_post_dec);
922         }
923
924         // === Arithmetic operations ===
925
926         case op_add: {
927             NodeIndex op1 = get(currentInstruction[2].u.operand);
928             NodeIndex op2 = get(currentInstruction[3].u.operand);
929             if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
930                 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2))));
931             else
932                 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2)));
933             NEXT_OPCODE(op_add);
934         }
935
936         case op_sub: {
937             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
938             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
939             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2)));
940             NEXT_OPCODE(op_sub);
941         }
942
943         case op_mul: {
944             // Multiply requires that the inputs are not truncated, unfortunately.
945             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
946             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
947             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2)));
948             NEXT_OPCODE(op_mul);
949         }
950
951         case op_mod: {
952             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
953             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
954             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, OpInfo(NodeUseBottom), op1, op2)));
955             NEXT_OPCODE(op_mod);
956         }
957
958         case op_div: {
959             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
960             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
961             set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2)));
962             NEXT_OPCODE(op_div);
963         }
964
965         // === Misc operations ===
966
967 #if ENABLE(DEBUG_WITH_BREAKPOINT)
968         case op_debug:
969             addToGraph(Breakpoint);
970             NEXT_OPCODE(op_debug);
971 #endif
972         case op_mov: {
973             NodeIndex op = get(currentInstruction[2].u.operand);
974             set(currentInstruction[1].u.operand, op);
975             NEXT_OPCODE(op_mov);
976         }
977
978         case op_check_has_instance:
979             addToGraph(CheckHasInstance, get(currentInstruction[1].u.operand));
980             NEXT_OPCODE(op_check_has_instance);
981
982         case op_instanceof: {
983             NodeIndex value = get(currentInstruction[2].u.operand);
984             NodeIndex baseValue = get(currentInstruction[3].u.operand);
985             NodeIndex prototype = get(currentInstruction[4].u.operand);
986             set(currentInstruction[1].u.operand, addToGraph(InstanceOf, value, baseValue, prototype));
987             NEXT_OPCODE(op_instanceof);
988         }
989
990         case op_not: {
991             NodeIndex value = get(currentInstruction[2].u.operand);
992             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
993             NEXT_OPCODE(op_not);
994         }
995             
996         case op_to_primitive: {
997             NodeIndex value = get(currentInstruction[2].u.operand);
998             set(currentInstruction[1].u.operand, addToGraph(ToPrimitive, value));
999             NEXT_OPCODE(op_to_primitive);
1000         }
1001             
1002         case op_strcat: {
1003             int startOperand = currentInstruction[2].u.operand;
1004             int numOperands = currentInstruction[3].u.operand;
1005             for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
1006                 addVarArgChild(get(operandIdx));
1007             set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, StrCat, OpInfo(0), OpInfo(0)));
1008             NEXT_OPCODE(op_strcat);
1009         }
1010
1011         case op_less: {
1012             NodeIndex op1 = get(currentInstruction[2].u.operand);
1013             NodeIndex op2 = get(currentInstruction[3].u.operand);
1014             set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
1015             NEXT_OPCODE(op_less);
1016         }
1017
1018         case op_lesseq: {
1019             NodeIndex op1 = get(currentInstruction[2].u.operand);
1020             NodeIndex op2 = get(currentInstruction[3].u.operand);
1021             set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
1022             NEXT_OPCODE(op_lesseq);
1023         }
1024
1025         case op_greater: {
1026             NodeIndex op1 = get(currentInstruction[2].u.operand);
1027             NodeIndex op2 = get(currentInstruction[3].u.operand);
1028             set(currentInstruction[1].u.operand, addToGraph(CompareGreater, op1, op2));
1029             NEXT_OPCODE(op_greater);
1030         }
1031
1032         case op_greatereq: {
1033             NodeIndex op1 = get(currentInstruction[2].u.operand);
1034             NodeIndex op2 = get(currentInstruction[3].u.operand);
1035             set(currentInstruction[1].u.operand, addToGraph(CompareGreaterEq, op1, op2));
1036             NEXT_OPCODE(op_greatereq);
1037         }
1038
1039         case op_eq: {
1040             NodeIndex op1 = get(currentInstruction[2].u.operand);
1041             NodeIndex op2 = get(currentInstruction[3].u.operand);
1042             set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
1043             NEXT_OPCODE(op_eq);
1044         }
1045
1046         case op_eq_null: {
1047             NodeIndex value = get(currentInstruction[2].u.operand);
1048             set(currentInstruction[1].u.operand, addToGraph(CompareEq, value, constantNull()));
1049             NEXT_OPCODE(op_eq_null);
1050         }
1051
1052         case op_stricteq: {
1053             NodeIndex op1 = get(currentInstruction[2].u.operand);
1054             NodeIndex op2 = get(currentInstruction[3].u.operand);
1055             set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
1056             NEXT_OPCODE(op_stricteq);
1057         }
1058
1059         case op_neq: {
1060             NodeIndex op1 = get(currentInstruction[2].u.operand);
1061             NodeIndex op2 = get(currentInstruction[3].u.operand);
1062             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
1063             NEXT_OPCODE(op_neq);
1064         }
1065
1066         case op_neq_null: {
1067             NodeIndex value = get(currentInstruction[2].u.operand);
1068             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, value, constantNull())));
1069             NEXT_OPCODE(op_neq_null);
1070         }
1071
1072         case op_nstricteq: {
1073             NodeIndex op1 = get(currentInstruction[2].u.operand);
1074             NodeIndex op2 = get(currentInstruction[3].u.operand);
1075             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareStrictEq, op1, op2)));
1076             NEXT_OPCODE(op_nstricteq);
1077         }
1078
1079         // === Property access operations ===
1080
1081         case op_get_by_val: {
1082             PredictedType prediction = getPrediction();
1083             
1084             NodeIndex base = get(currentInstruction[2].u.operand);
1085             NodeIndex property = get(currentInstruction[3].u.operand);
1086
1087             NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property);
1088             set(currentInstruction[1].u.operand, getByVal);
1089
1090             NEXT_OPCODE(op_get_by_val);
1091         }
1092
1093         case op_put_by_val: {
1094             NodeIndex base = get(currentInstruction[1].u.operand);
1095             NodeIndex property = get(currentInstruction[2].u.operand);
1096             NodeIndex value = get(currentInstruction[3].u.operand);
1097
1098             addToGraph(PutByVal, base, property, value);
1099
1100             NEXT_OPCODE(op_put_by_val);
1101         }
1102             
1103         case op_method_check: {
1104             Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
1105             
1106             PredictedType prediction = getPrediction();
1107             
1108             ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
1109             
1110             NodeIndex base = get(getInstruction[2].u.operand);
1111             unsigned identifier = getInstruction[3].u.operand;
1112                 
1113             // Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
1114             // node, which is a lot more efficient.
1115             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1116             MethodCallLinkInfo& methodCall = m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
1117             
1118             if (methodCall.seen && !!methodCall.cachedStructure && !stubInfo.seen) {
1119                 // It's monomorphic as far as we can tell, since the method_check was linked
1120                 // but the slow path (i.e. the normal get_by_id) never fired.
1121             
1122                 NodeIndex checkMethod = addToGraph(CheckMethod, OpInfo(identifier), OpInfo(m_graph.m_methodCheckData.size()), base);
1123                 set(getInstruction[1].u.operand, checkMethod);
1124                 
1125                 MethodCheckData methodCheckData;
1126                 methodCheckData.structure = methodCall.cachedStructure.get();
1127                 methodCheckData.prototypeStructure = methodCall.cachedPrototypeStructure.get();
1128                 methodCheckData.function = methodCall.cachedFunction.get();
1129                 methodCheckData.prototype = methodCall.cachedPrototype.get();
1130                 m_graph.m_methodCheckData.append(methodCheckData);
1131             } else {
1132                 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(prediction), base);
1133                 set(getInstruction[1].u.operand, getMethod);
1134             }
1135             
1136             m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
1137             continue;
1138         }
1139         case op_get_scoped_var: {
1140             PredictedType prediction = getPrediction();
1141             int dst = currentInstruction[1].u.operand;
1142             int slot = currentInstruction[2].u.operand;
1143             int depth = currentInstruction[3].u.operand;
1144             NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
1145             NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
1146             set(dst, getScopedVar);
1147             NEXT_OPCODE(op_get_scoped_var);
1148         }
1149         case op_put_scoped_var: {
1150             int slot = currentInstruction[1].u.operand;
1151             int depth = currentInstruction[2].u.operand;
1152             int source = currentInstruction[3].u.operand;
1153             NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
1154             addToGraph(PutScopedVar, OpInfo(slot), getScopeChain, get(source));
1155             NEXT_OPCODE(op_put_scoped_var);
1156         }
1157         case op_get_by_id: {
1158             PredictedType prediction = getPrediction();
1159             
1160             NodeIndex base = get(currentInstruction[2].u.operand);
1161             unsigned identifierNumber = currentInstruction[3].u.operand;
1162             
1163             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1164             
1165             NodeIndex getById = NoNode;
1166             if (stubInfo.seen && stubInfo.accessType == access_get_by_id_self) {
1167                 Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
1168                 Identifier identifier = m_codeBlock->identifier(identifierNumber);
1169                 size_t offset = structure->get(*m_globalData, identifier);
1170                 
1171                 if (offset != notFound) {
1172                     addToGraph(CheckStructure, OpInfo(structure), base);
1173                     getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base));
1174                     
1175                     StorageAccessData storageAccessData;
1176                     storageAccessData.offset = offset;
1177                     storageAccessData.identifierNumber = identifierNumber;
1178                     m_graph.m_storageAccessData.append(storageAccessData);
1179                 }
1180             }
1181             
1182             if (getById == NoNode)
1183                 getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base);
1184             
1185             set(currentInstruction[1].u.operand, getById);
1186
1187             NEXT_OPCODE(op_get_by_id);
1188         }
1189
1190         case op_put_by_id: {
1191             NodeIndex value = get(currentInstruction[3].u.operand);
1192             NodeIndex base = get(currentInstruction[1].u.operand);
1193             unsigned identifierNumber = currentInstruction[2].u.operand;
1194             bool direct = currentInstruction[8].u.operand;
1195
1196             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1197             if (!stubInfo.seen)
1198                 addToGraph(ForceOSRExit);
1199             
1200             bool alreadyGenerated = false;
1201             
1202             if (stubInfo.seen && !m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
1203                 switch (stubInfo.accessType) {
1204                 case access_put_by_id_replace: {
1205                     Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
1206                     Identifier identifier = m_codeBlock->identifier(identifierNumber);
1207                     size_t offset = structure->get(*m_globalData, identifier);
1208                     
1209                     if (offset != notFound) {
1210                         addToGraph(CheckStructure, OpInfo(structure), base);
1211                         addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
1212                         
1213                         StorageAccessData storageAccessData;
1214                         storageAccessData.offset = offset;
1215                         storageAccessData.identifierNumber = identifierNumber;
1216                         m_graph.m_storageAccessData.append(storageAccessData);
1217                         
1218                         alreadyGenerated = true;
1219                     }
1220                     break;
1221                 }
1222                     
1223                 case access_put_by_id_transition: {
1224                     Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
1225                     Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
1226                     
1227                     if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
1228                         break;
1229                     
1230                     StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
1231                     
1232                     Identifier identifier = m_codeBlock->identifier(identifierNumber);
1233                     size_t offset = newStructure->get(*m_globalData, identifier);
1234                     
1235                     if (offset != notFound) {
1236                         addToGraph(CheckStructure, OpInfo(previousStructure), base);
1237                         if (!direct) {
1238                             for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
1239                                 JSValue prototype = (*it)->storedPrototype();
1240                                 if (prototype.isNull())
1241                                     continue;
1242                                 ASSERT(prototype.isCell());
1243                                 addToGraph(CheckStructure, OpInfo(prototype.asCell()->structure()), cellConstant(prototype.asCell()));
1244                             }
1245                         }
1246                         addToGraph(PutStructure, OpInfo(newStructure), base);
1247                         
1248                         addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
1249                         
1250                         StorageAccessData storageAccessData;
1251                         storageAccessData.offset = offset;
1252                         storageAccessData.identifierNumber = identifierNumber;
1253                         m_graph.m_storageAccessData.append(storageAccessData);
1254                         
1255                         alreadyGenerated = true;
1256                     }
1257                     break;
1258                 }
1259                     
1260                 default:
1261                     break;
1262                 }
1263             }
1264             
1265             if (!alreadyGenerated) {
1266                 if (direct)
1267                     addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
1268                 else
1269                     addToGraph(PutById, OpInfo(identifierNumber), base, value);
1270             }
1271
1272             NEXT_OPCODE(op_put_by_id);
1273         }
1274
1275         case op_get_global_var: {
1276             PredictedType prediction = getPrediction();
1277             
1278             NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
1279             set(currentInstruction[1].u.operand, getGlobalVar);
1280             m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction);
1281             NEXT_OPCODE(op_get_global_var);
1282         }
1283
1284         case op_put_global_var: {
1285             NodeIndex value = get(currentInstruction[2].u.operand);
1286             addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
1287             NEXT_OPCODE(op_put_global_var);
1288         }
1289
1290         // === Block terminators. ===
1291
1292         case op_jmp: {
1293             unsigned relativeOffset = currentInstruction[1].u.operand;
1294             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
1295             LAST_OPCODE(op_jmp);
1296         }
1297
1298         case op_loop: {
1299             unsigned relativeOffset = currentInstruction[1].u.operand;
1300             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
1301             LAST_OPCODE(op_loop);
1302         }
1303
1304         case op_jtrue: {
1305             unsigned relativeOffset = currentInstruction[2].u.operand;
1306             NodeIndex condition = get(currentInstruction[1].u.operand);
1307             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jtrue)), condition);
1308             LAST_OPCODE(op_jtrue);
1309         }
1310
1311         case op_jfalse: {
1312             unsigned relativeOffset = currentInstruction[2].u.operand;
1313             NodeIndex condition = get(currentInstruction[1].u.operand);
1314             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jfalse)), OpInfo(m_currentIndex + relativeOffset), condition);
1315             LAST_OPCODE(op_jfalse);
1316         }
1317
1318         case op_loop_if_true: {
1319             unsigned relativeOffset = currentInstruction[2].u.operand;
1320             NodeIndex condition = get(currentInstruction[1].u.operand);
1321             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_true)), condition);
1322             LAST_OPCODE(op_loop_if_true);
1323         }
1324
1325         case op_loop_if_false: {
1326             unsigned relativeOffset = currentInstruction[2].u.operand;
1327             NodeIndex condition = get(currentInstruction[1].u.operand);
1328             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_false)), OpInfo(m_currentIndex + relativeOffset), condition);
1329             LAST_OPCODE(op_loop_if_false);
1330         }
1331
1332         case op_jeq_null: {
1333             unsigned relativeOffset = currentInstruction[2].u.operand;
1334             NodeIndex value = get(currentInstruction[1].u.operand);
1335             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
1336             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
1337             LAST_OPCODE(op_jeq_null);
1338         }
1339
1340         case op_jneq_null: {
1341             unsigned relativeOffset = currentInstruction[2].u.operand;
1342             NodeIndex value = get(currentInstruction[1].u.operand);
1343             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
1344             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
1345             LAST_OPCODE(op_jneq_null);
1346         }
1347
1348         case op_jless: {
1349             unsigned relativeOffset = currentInstruction[3].u.operand;
1350             NodeIndex op1 = get(currentInstruction[1].u.operand);
1351             NodeIndex op2 = get(currentInstruction[2].u.operand);
1352             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1353             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jless)), condition);
1354             LAST_OPCODE(op_jless);
1355         }
1356
1357         case op_jlesseq: {
1358             unsigned relativeOffset = currentInstruction[3].u.operand;
1359             NodeIndex op1 = get(currentInstruction[1].u.operand);
1360             NodeIndex op2 = get(currentInstruction[2].u.operand);
1361             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1362             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jlesseq)), condition);
1363             LAST_OPCODE(op_jlesseq);
1364         }
1365
1366         case op_jgreater: {
1367             unsigned relativeOffset = currentInstruction[3].u.operand;
1368             NodeIndex op1 = get(currentInstruction[1].u.operand);
1369             NodeIndex op2 = get(currentInstruction[2].u.operand);
1370             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1371             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreater)), condition);
1372             LAST_OPCODE(op_jgreater);
1373         }
1374
1375         case op_jgreatereq: {
1376             unsigned relativeOffset = currentInstruction[3].u.operand;
1377             NodeIndex op1 = get(currentInstruction[1].u.operand);
1378             NodeIndex op2 = get(currentInstruction[2].u.operand);
1379             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1380             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreatereq)), condition);
1381             LAST_OPCODE(op_jgreatereq);
1382         }
1383
1384         case op_jnless: {
1385             unsigned relativeOffset = currentInstruction[3].u.operand;
1386             NodeIndex op1 = get(currentInstruction[1].u.operand);
1387             NodeIndex op2 = get(currentInstruction[2].u.operand);
1388             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1389             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnless)), OpInfo(m_currentIndex + relativeOffset), condition);
1390             LAST_OPCODE(op_jnless);
1391         }
1392
1393         case op_jnlesseq: {
1394             unsigned relativeOffset = currentInstruction[3].u.operand;
1395             NodeIndex op1 = get(currentInstruction[1].u.operand);
1396             NodeIndex op2 = get(currentInstruction[2].u.operand);
1397             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1398             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnlesseq)), OpInfo(m_currentIndex + relativeOffset), condition);
1399             LAST_OPCODE(op_jnlesseq);
1400         }
1401
1402         case op_jngreater: {
1403             unsigned relativeOffset = currentInstruction[3].u.operand;
1404             NodeIndex op1 = get(currentInstruction[1].u.operand);
1405             NodeIndex op2 = get(currentInstruction[2].u.operand);
1406             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1407             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreater)), OpInfo(m_currentIndex + relativeOffset), condition);
1408             LAST_OPCODE(op_jngreater);
1409         }
1410
1411         case op_jngreatereq: {
1412             unsigned relativeOffset = currentInstruction[3].u.operand;
1413             NodeIndex op1 = get(currentInstruction[1].u.operand);
1414             NodeIndex op2 = get(currentInstruction[2].u.operand);
1415             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1416             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreatereq)), OpInfo(m_currentIndex + relativeOffset), condition);
1417             LAST_OPCODE(op_jngreatereq);
1418         }
1419
1420         case op_loop_if_less: {
1421             unsigned relativeOffset = currentInstruction[3].u.operand;
1422             NodeIndex op1 = get(currentInstruction[1].u.operand);
1423             NodeIndex op2 = get(currentInstruction[2].u.operand);
1424             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1425             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_less)), condition);
1426             LAST_OPCODE(op_loop_if_less);
1427         }
1428
1429         case op_loop_if_lesseq: {
1430             unsigned relativeOffset = currentInstruction[3].u.operand;
1431             NodeIndex op1 = get(currentInstruction[1].u.operand);
1432             NodeIndex op2 = get(currentInstruction[2].u.operand);
1433             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1434             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_lesseq)), condition);
1435             LAST_OPCODE(op_loop_if_lesseq);
1436         }
1437
1438         case op_loop_if_greater: {
1439             unsigned relativeOffset = currentInstruction[3].u.operand;
1440             NodeIndex op1 = get(currentInstruction[1].u.operand);
1441             NodeIndex op2 = get(currentInstruction[2].u.operand);
1442             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1443             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greater)), condition);
1444             LAST_OPCODE(op_loop_if_greater);
1445         }
1446
1447         case op_loop_if_greatereq: {
1448             unsigned relativeOffset = currentInstruction[3].u.operand;
1449             NodeIndex op1 = get(currentInstruction[1].u.operand);
1450             NodeIndex op2 = get(currentInstruction[2].u.operand);
1451             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1452             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greatereq)), condition);
1453             LAST_OPCODE(op_loop_if_greatereq);
1454         }
1455
1456         case op_ret:
1457             addToGraph(Return, get(currentInstruction[1].u.operand));
1458             LAST_OPCODE(op_ret);
1459             
1460         case op_end:
1461             addToGraph(Return, get(currentInstruction[1].u.operand));
1462             LAST_OPCODE(op_end);
1463
1464         case op_throw:
1465             addToGraph(Throw, get(currentInstruction[1].u.operand));
1466             LAST_OPCODE(op_throw);
1467             
1468         case op_throw_reference_error:
1469             addToGraph(ThrowReferenceError);
1470             LAST_OPCODE(op_throw_reference_error);
1471             
1472         case op_call: {
1473             NodeIndex callTarget = get(currentInstruction[1].u.operand);
1474             if (m_graph.isFunctionConstant(m_codeBlock, callTarget)) {
1475                 int argCount = currentInstruction[2].u.operand;
1476                 int registerOffset = currentInstruction[3].u.operand;
1477                 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
1478                 int lastArg = firstArg + argCount - 1;
1479                 
1480                 // Do we have a result?
1481                 bool usesResult = false;
1482                 int resultOperand = 0; // make compiler happy
1483                 Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
1484                 if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
1485                     resultOperand = putInstruction[1].u.operand;
1486                     usesResult = true;
1487                 }
1488                 
1489                 DFG::Intrinsic intrinsic = m_graph.valueOfFunctionConstant(m_codeBlock, callTarget)->executable()->intrinsic();
1490                 
1491                 if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg)) {
1492                     // NEXT_OPCODE() has to be inside braces.
1493                     NEXT_OPCODE(op_call);
1494                 }
1495             }
1496             
1497             addCall(interpreter, currentInstruction, Call);
1498             NEXT_OPCODE(op_call);
1499         }
1500             
1501         case op_construct: {
1502             addCall(interpreter, currentInstruction, Construct);
1503             NEXT_OPCODE(op_construct);
1504         }
1505             
1506         case op_call_put_result:
1507             NEXT_OPCODE(op_call_put_result);
1508
1509         case op_resolve: {
1510             PredictedType prediction = getPrediction();
1511             
1512             unsigned identifier = currentInstruction[2].u.operand;
1513
1514             NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(prediction));
1515             set(currentInstruction[1].u.operand, resolve);
1516
1517             NEXT_OPCODE(op_resolve);
1518         }
1519
1520         case op_resolve_base: {
1521             PredictedType prediction = getPrediction();
1522             
1523             unsigned identifier = currentInstruction[2].u.operand;
1524
1525             NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(prediction));
1526             set(currentInstruction[1].u.operand, resolve);
1527
1528             NEXT_OPCODE(op_resolve_base);
1529         }
1530             
1531         case op_resolve_global: {
1532             PredictedType prediction = getPrediction();
1533             
1534             NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
1535             m_graph.m_resolveGlobalData.append(ResolveGlobalData());
1536             ResolveGlobalData& data = m_graph.m_resolveGlobalData.last();
1537             data.identifierNumber = currentInstruction[2].u.operand;
1538             data.resolveInfoIndex = m_globalResolveNumber++;
1539             set(currentInstruction[1].u.operand, resolve);
1540
1541             NEXT_OPCODE(op_resolve_global);
1542         }
1543
1544         case op_loop_hint: {
1545             // Baseline->DFG OSR jumps between loop hints. The DFG assumes that Baseline->DFG
1546             // OSR can only happen at basic block boundaries. Assert that these two statements
1547             // are compatible.
1548             ASSERT_UNUSED(blockBegin, m_currentIndex == blockBegin);
1549             
1550             m_currentBlock->isOSRTarget = true;
1551             
1552             NEXT_OPCODE(op_loop_hint);
1553         }
1554
1555         default:
1556             // Parse failed! This should not happen because the capabilities checker
1557             // should have caught it.
1558             ASSERT_NOT_REACHED();
1559             return false;
1560         }
1561         
1562         ASSERT(canCompileOpcode(opcodeID));
1563     }
1564 }
1565
1566 template<ByteCodeParser::PhiStackType stackType>
1567 void ByteCodeParser::processPhiStack()
1568 {
1569     Vector<PhiStackEntry, 16>& phiStack = (stackType == ArgumentPhiStack) ? m_argumentPhiStack : m_localPhiStack;
1570
1571     while (!phiStack.isEmpty()) {
1572         PhiStackEntry entry = phiStack.last();
1573         phiStack.removeLast();
1574         
1575         PredecessorList& predecessors = entry.m_block->m_predecessors;
1576         unsigned varNo = entry.m_varNo;
1577         VariableAccessData* dataForPhi = m_graph[entry.m_phi].variableAccessData();
1578
1579         for (size_t i = 0; i < predecessors.size(); ++i) {
1580             BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
1581
1582             VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_argumentsAtTail[varNo] : predecessorBlock->m_localsAtTail[varNo];
1583
1584             NodeIndex valueInPredecessor = var.value;
1585             if (valueInPredecessor == NoNode) {
1586                 valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo)));
1587                 var.setFirstTime(valueInPredecessor);
1588                 if (stackType == ArgumentPhiStack)
1589                     predecessorBlock->m_argumentsAtHead[varNo].setFirstTime(valueInPredecessor);
1590                 else
1591                     predecessorBlock->m_localsAtHead[varNo].setFirstTime(valueInPredecessor);
1592                 phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
1593             } else if (m_graph[valueInPredecessor].op == GetLocal) {
1594                 // We want to ensure that the VariableAccessDatas are identical between the
1595                 // GetLocal and its block-local Phi. Strictly speaking we only need the two
1596                 // to be unified. But for efficiency, we want the code that creates GetLocals
1597                 // and Phis to try to reuse VariableAccessDatas as much as possible.
1598                 ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1()].variableAccessData());
1599                 
1600                 valueInPredecessor = m_graph[valueInPredecessor].child1();
1601             }
1602             ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi || (m_graph[valueInPredecessor].op == SetArgument && stackType == ArgumentPhiStack));
1603             
1604             VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData();
1605             
1606             dataForPredecessor->unify(dataForPhi);
1607
1608             Node* phiNode = &m_graph[entry.m_phi];
1609             if (phiNode->refCount())
1610                 m_graph.ref(valueInPredecessor);
1611
1612             if (phiNode->child1() == NoNode) {
1613                 phiNode->children.fixed.child1 = valueInPredecessor;
1614                 continue;
1615             }
1616             if (phiNode->child2() == NoNode) {
1617                 phiNode->children.fixed.child2 = valueInPredecessor;
1618                 continue;
1619             }
1620             if (phiNode->child3() == NoNode) {
1621                 phiNode->children.fixed.child3 = valueInPredecessor;
1622                 continue;
1623             }
1624             
1625             NodeIndex newPhi = addToGraph(Phi, OpInfo(dataForPhi));
1626             
1627             phiNode = &m_graph[entry.m_phi]; // reload after vector resize
1628             Node& newPhiNode = m_graph[newPhi];
1629             if (phiNode->refCount())
1630                 m_graph.ref(newPhi);
1631
1632             newPhiNode.children.fixed.child1 = phiNode->child1();
1633             newPhiNode.children.fixed.child2 = phiNode->child2();
1634             newPhiNode.children.fixed.child3 = phiNode->child3();
1635
1636             phiNode->children.fixed.child1 = newPhi;
1637             phiNode->children.fixed.child1 = valueInPredecessor;
1638             phiNode->children.fixed.child3 = NoNode;
1639         }
1640     }
1641 }
1642
1643 void ByteCodeParser::setupPredecessors()
1644 {
1645     for (BlockIndex index = 0; index < m_graph.m_blocks.size(); ++index) {
1646         BasicBlock* block = m_graph.m_blocks[index].get();
1647         ASSERT(block->end != NoNode);
1648         Node& node = m_graph[block->end - 1];
1649         ASSERT(node.isTerminal());
1650
1651         if (node.isJump())
1652             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1653         else if (node.isBranch()) {
1654             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1655             m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
1656         }
1657     }
1658 }
1659
1660 bool ByteCodeParser::parse()
1661 {
1662     // Set during construction.
1663     ASSERT(!m_currentIndex);
1664
1665     for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
1666         // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions.
1667         unsigned limit = jumpTargetIndex < m_codeBlock->numberOfJumpTargets() ? m_codeBlock->jumpTarget(jumpTargetIndex) : m_codeBlock->instructions().size();
1668         ASSERT(m_currentIndex < limit);
1669
1670         // Loop until we reach the current limit (i.e. next jump target).
1671         do {
1672             OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
1673             m_currentBlock = block.get();
1674             m_graph.m_blocks.append(block.release());
1675
1676             if (!parseBlock(limit))
1677                 return false;
1678             // We should not have gone beyond the limit.
1679             ASSERT(m_currentIndex <= limit);
1680
1681             m_currentBlock->end = m_graph.size();
1682         } while (m_currentIndex < limit);
1683     }
1684
1685     // Should have reached the end of the instructions.
1686     ASSERT(m_currentIndex == m_codeBlock->instructions().size());
1687
1688     setupPredecessors();
1689     processPhiStack<LocalPhiStack>();
1690     processPhiStack<ArgumentPhiStack>();
1691     
1692     m_graph.m_preservedVars = m_preservedVars;
1693     m_graph.m_localVars = m_numLocals;
1694     m_graph.m_parameterSlots = m_parameterSlots;
1695
1696     return true;
1697 }
1698
1699 bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
1700 {
1701 #if DFG_DEBUG_LOCAL_DISBALE
1702     UNUSED_PARAM(graph);
1703     UNUSED_PARAM(globalData);
1704     UNUSED_PARAM(codeBlock);
1705     return false;
1706 #else
1707     return ByteCodeParser(globalData, codeBlock, codeBlock->alternative(), graph).parse();
1708 #endif
1709 }
1710
1711 } } // namespace JSC::DFG
1712
1713 #endif