d36bf5da8266c5550d58976b2c833c43bd13ee4f
[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         m_cellConstants.add(cell, m_codeBlock->numberOfConstantRegisters() - 1);
419         
420         return getJSConstant(m_codeBlock->numberOfConstantRegisters() - 1);
421     }
422     
423     CodeOrigin currentCodeOrigin()
424     {
425         return CodeOrigin(m_currentIndex);
426     }
427
428     // These methods create a node and add it to the graph. If nodes of this type are
429     // 'mustGenerate' then the node  will implicitly be ref'ed to ensure generation.
430     NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
431     {
432         NodeIndex resultIndex = (NodeIndex)m_graph.size();
433         m_graph.append(Node(op, currentCodeOrigin(), child1, child2, child3));
434
435         if (op & NodeMustGenerate)
436             m_graph.ref(resultIndex);
437         return resultIndex;
438     }
439     NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
440     {
441         NodeIndex resultIndex = (NodeIndex)m_graph.size();
442         m_graph.append(Node(op, currentCodeOrigin(), info, child1, child2, child3));
443
444         if (op & NodeMustGenerate)
445             m_graph.ref(resultIndex);
446         return resultIndex;
447     }
448     NodeIndex addToGraph(NodeType op, OpInfo info1, OpInfo info2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
449     {
450         NodeIndex resultIndex = (NodeIndex)m_graph.size();
451         m_graph.append(Node(op, currentCodeOrigin(), info1, info2, child1, child2, child3));
452
453         if (op & NodeMustGenerate)
454             m_graph.ref(resultIndex);
455         return resultIndex;
456     }
457     
458     NodeIndex addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2)
459     {
460         NodeIndex resultIndex = (NodeIndex)m_graph.size();
461         m_graph.append(Node(Node::VarArg, op, currentCodeOrigin(), info1, info2, m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs));
462         
463         m_numPassedVarArgs = 0;
464         
465         if (op & NodeMustGenerate)
466             m_graph.ref(resultIndex);
467         return resultIndex;
468     }
469     void addVarArgChild(NodeIndex child)
470     {
471         m_graph.m_varArgChildren.append(child);
472         m_numPassedVarArgs++;
473     }
474     
475     NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
476     {
477         Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
478
479         PredictedType prediction = PredictNone;
480         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
481             prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
482         
483         addVarArgChild(get(currentInstruction[1].u.operand));
484         int argCount = currentInstruction[2].u.operand;
485         int registerOffset = currentInstruction[3].u.operand;
486         int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
487         for (int argIdx = firstArg + (op == Construct ? 1 : 0); argIdx < firstArg + argCount; argIdx++)
488             addVarArgChild(get(argIdx));
489         NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
490         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
491             set(putInstruction[1].u.operand, call);
492         if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
493             m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
494         return call;
495     }
496
497     PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
498     {
499         UNUSED_PARAM(nodeIndex);
500         
501         ValueProfile* profile = m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
502         ASSERT(profile);
503         PredictedType prediction = profile->computeUpdatedPrediction();
504 #if ENABLE(DFG_DEBUG_VERBOSE)
505         printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
506 #endif
507         
508         if (prediction == PredictNone) {
509             // We have no information about what values this node generates. Give up
510             // on executing this code, since we're likely to do more damage than good.
511             addToGraph(ForceOSRExit);
512         }
513         
514         return prediction;
515     }
516     
517     PredictedType getPrediction()
518     {
519         return getPrediction(m_graph.size(), m_currentIndex);
520     }
521
522     NodeIndex makeSafe(NodeIndex nodeIndex)
523     {
524         if (!m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
525             return nodeIndex;
526         
527 #if ENABLE(DFG_DEBUG_VERBOSE)
528         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);
529 #endif
530         
531         switch (m_graph[nodeIndex].op) {
532         case UInt32ToNumber:
533         case ArithAdd:
534         case ArithSub:
535         case ValueAdd:
536         case ArithMod: // for ArithMode "MayOverflow" means we tried to divide by zero, or we saw double.
537             m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow);
538             break;
539             
540         case ArithMul:
541             if (m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex))
542                 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
543             else
544                 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayNegZero);
545             break;
546             
547         default:
548             ASSERT_NOT_REACHED();
549             break;
550         }
551         
552         return nodeIndex;
553     }
554     
555     NodeIndex makeDivSafe(NodeIndex nodeIndex)
556     {
557         ASSERT(m_graph[nodeIndex].op == ArithDiv);
558         
559         // The main slow case counter for op_div in the old JIT counts only when
560         // the operands are not numbers. We don't care about that since we already
561         // have speculations in place that take care of that separately. We only
562         // care about when the outcome of the division is not an integer, which
563         // is what the special fast case counter tells us.
564         
565         if (!m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex))
566             return nodeIndex;
567         
568         m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
569         
570         return nodeIndex;
571     }
572     
573     JSGlobalData* m_globalData;
574     CodeBlock* m_codeBlock;
575     CodeBlock* m_profiledBlock;
576     Graph& m_graph;
577
578     // The current block being generated.
579     BasicBlock* m_currentBlock;
580     // The bytecode index of the current instruction being generated.
581     unsigned m_currentIndex;
582
583     // Record failures due to unimplemented functionality or regressions.
584     bool m_parseFailed;
585
586     // We use these values during code generation, and to avoid the need for
587     // special handling we make sure they are available as constants in the
588     // CodeBlock's constant pool. These variables are initialized to
589     // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
590     // constant pool, as necessary.
591     unsigned m_constantUndefined;
592     unsigned m_constantNull;
593     unsigned m_constantNaN;
594     unsigned m_constant1;
595     HashMap<JSCell*, unsigned> m_cellConstants;
596
597     // A constant in the constant pool may be represented by more than one
598     // node in the graph, depending on the context in which it is being used.
599     struct ConstantRecord {
600         ConstantRecord()
601             : asInt32(NoNode)
602             , asNumeric(NoNode)
603             , asJSValue(NoNode)
604         {
605         }
606
607         NodeIndex asInt32;
608         NodeIndex asNumeric;
609         NodeIndex asJSValue;
610     };
611
612     // Track the index of the node whose result is the current value for every
613     // register value in the bytecode - argument, local, and temporary.
614     Vector<ConstantRecord, 16> m_constants;
615
616     // The number of arguments passed to the function.
617     unsigned m_numArguments;
618     // The number of locals (vars + temporaries) used in the function.
619     unsigned m_numLocals;
620     // The number of registers we need to preserve across BasicBlock boundaries;
621     // typically equal to the number vars, but we expand this to cover all
622     // temporaries that persist across blocks (dues to ?:, &&, ||, etc).
623     unsigned m_preservedVars;
624     // The number of slots (in units of sizeof(Register)) that we need to
625     // preallocate for calls emanating from this frame. This includes the
626     // size of the CallFrame, only if this is not a leaf function.  (I.e.
627     // this is 0 if and only if this function is a leaf.)
628     unsigned m_parameterSlots;
629     // The number of var args passed to the next var arg node.
630     unsigned m_numPassedVarArgs;
631     // The index in the global resolve info.
632     unsigned m_globalResolveNumber;
633
634     struct PhiStackEntry {
635         PhiStackEntry(BasicBlock* block, NodeIndex phi, unsigned varNo)
636             : m_block(block)
637             , m_phi(phi)
638             , m_varNo(varNo)
639         {
640         }
641
642         BasicBlock* m_block;
643         NodeIndex m_phi;
644         unsigned m_varNo;
645     };
646     Vector<PhiStackEntry, 16> m_argumentPhiStack;
647     Vector<PhiStackEntry, 16> m_localPhiStack;
648     
649     Vector<Node*, 16> m_reusableNodeStack;
650 };
651
652 #define NEXT_OPCODE(name) \
653     m_currentIndex += OPCODE_LENGTH(name); \
654     continue
655
656 #define LAST_OPCODE(name) \
657     m_currentIndex += OPCODE_LENGTH(name); \
658     return !m_parseFailed
659
660 bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int firstArg, int lastArg)
661 {
662     if (!usesResult)
663         return true;
664
665     if (lastArg == firstArg) {
666         set(resultOperand, constantNaN());
667         return true;
668     }
669      
670     if (lastArg == firstArg + 1) {
671         set(resultOperand, getToNumber(firstArg + 1));
672         return true;
673     }
674     
675     if (lastArg == firstArg + 2) {
676         set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(firstArg + 1), getToNumber(firstArg + 2)));
677         return true;
678     }
679     
680     // Don't handle >=3 arguments for now.
681     return false;
682 }
683
684 bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int firstArg, int lastArg)
685 {
686     switch (intrinsic) {
687     case AbsIntrinsic: {
688         if (!usesResult) {
689             // There is no such thing as executing abs for effect, so this
690             // is dead code.
691             return true;
692         }
693         
694         // We don't care about the this argument. If we don't have a first
695         // argument then make this JSConstant(NaN).
696         int absArg = firstArg + 1;
697         if (absArg > lastArg)
698             set(resultOperand, constantNaN());
699         else
700             set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(absArg)));
701         return true;
702     }
703         
704     case MinIntrinsic:
705         return handleMinMax(usesResult, resultOperand, ArithMin, firstArg, lastArg);
706         
707     case MaxIntrinsic:
708         return handleMinMax(usesResult, resultOperand, ArithMax, firstArg, lastArg);
709         
710     case SqrtIntrinsic: {
711         if (!usesResult)
712             return true;
713         
714         if (firstArg == lastArg) {
715             set(resultOperand, constantNaN());
716             return true;
717         }
718         
719         set(resultOperand, addToGraph(ArithSqrt, getToNumber(firstArg + 1)));
720         return true;
721     }
722         
723     default:
724         ASSERT(intrinsic == NoIntrinsic);
725         return false;
726     }
727 }
728
729 bool ByteCodeParser::parseBlock(unsigned limit)
730 {
731     // No need to reset state initially, since it has been set by the constructor.
732     if (m_currentIndex) {
733         for (unsigned i = 0; i < m_constants.size(); ++i)
734             m_constants[i] = ConstantRecord();
735     }
736     
737     // If we are the first basic block, introduce markers for arguments. This allows
738     // us to track if a use of an argument may use the actual argument passed, as
739     // opposed to using a value we set explicitly.
740     if (!m_currentIndex) {
741         m_graph.m_arguments.resize(m_numArguments);
742         for (unsigned argument = 0; argument < m_numArguments; ++argument) {
743             NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize)));
744             m_graph.m_arguments[argument] = setArgument;
745             m_currentBlock->m_argumentsAtHead[argument].setFirstTime(setArgument);
746             m_currentBlock->m_argumentsAtTail[argument].setFirstTime(setArgument);
747         }
748     }
749
750     Interpreter* interpreter = m_globalData->interpreter;
751     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
752     unsigned blockBegin = m_currentIndex;
753     while (true) {
754         // Don't extend over jump destinations.
755         if (m_currentIndex == limit) {
756             addToGraph(Jump, OpInfo(m_currentIndex));
757             return !m_parseFailed;
758         }
759         
760         // Switch on the current bytecode opcode.
761         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
762         OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
763         switch (opcodeID) {
764
765         // === Function entry opcodes ===
766
767         case op_enter:
768             // Initialize all locals to undefined.
769             for (int i = 0; i < m_codeBlock->m_numVars; ++i)
770                 set(i, constantUndefined());
771             NEXT_OPCODE(op_enter);
772
773         case op_convert_this: {
774             NodeIndex op1 = getThis();
775             setThis(addToGraph(ConvertThis, op1));
776             NEXT_OPCODE(op_convert_this);
777         }
778
779         case op_create_this: {
780             NodeIndex op1 = get(currentInstruction[2].u.operand);
781             set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1));
782             NEXT_OPCODE(op_create_this);
783         }
784             
785         case op_new_object: {
786             set(currentInstruction[1].u.operand, addToGraph(NewObject));
787             NEXT_OPCODE(op_new_object);
788         }
789             
790         case op_new_array: {
791             int startOperand = currentInstruction[2].u.operand;
792             int numOperands = currentInstruction[3].u.operand;
793             for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
794                 addVarArgChild(get(operandIdx));
795             set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
796             NEXT_OPCODE(op_new_array);
797         }
798             
799         case op_new_array_buffer: {
800             int startConstant = currentInstruction[2].u.operand;
801             int numConstants = currentInstruction[3].u.operand;
802             set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(startConstant), OpInfo(numConstants)));
803             NEXT_OPCODE(op_new_array_buffer);
804         }
805             
806         case op_new_regexp: {
807             set(currentInstruction[1].u.operand, addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
808             NEXT_OPCODE(op_new_regexp);
809         }
810             
811         case op_get_callee: {
812             set(currentInstruction[1].u.operand, addToGraph(GetCallee));
813             NEXT_OPCODE(op_get_callee);
814         }
815
816         // === Bitwise operations ===
817
818         case op_bitand: {
819             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
820             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
821             set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
822             NEXT_OPCODE(op_bitand);
823         }
824
825         case op_bitor: {
826             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
827             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
828             set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
829             NEXT_OPCODE(op_bitor);
830         }
831
832         case op_bitxor: {
833             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
834             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
835             set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
836             NEXT_OPCODE(op_bitxor);
837         }
838
839         case op_rshift: {
840             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
841             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
842             NodeIndex result;
843             // Optimize out shifts by zero.
844             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
845                 result = op1;
846             else
847                 result = addToGraph(BitRShift, op1, op2);
848             set(currentInstruction[1].u.operand, result);
849             NEXT_OPCODE(op_rshift);
850         }
851
852         case op_lshift: {
853             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
854             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
855             NodeIndex result;
856             // Optimize out shifts by zero.
857             if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
858                 result = op1;
859             else
860                 result = addToGraph(BitLShift, op1, op2);
861             set(currentInstruction[1].u.operand, result);
862             NEXT_OPCODE(op_lshift);
863         }
864
865         case op_urshift: {
866             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
867             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
868             NodeIndex result;
869             // The result of a zero-extending right shift is treated as an unsigned value.
870             // This means that if the top bit is set, the result is not in the int32 range,
871             // and as such must be stored as a double. If the shift amount is a constant,
872             // we may be able to optimize.
873             if (isInt32Constant(op2)) {
874                 // If we know we are shifting by a non-zero amount, then since the operation
875                 // zero fills we know the top bit of the result must be zero, and as such the
876                 // result must be within the int32 range. Conversely, if this is a shift by
877                 // zero, then the result may be changed by the conversion to unsigned, but it
878                 // is not necessary to perform the shift!
879                 if (valueOfInt32Constant(op2) & 0x1f)
880                     result = addToGraph(BitURShift, op1, op2);
881                 else
882                     result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), op1));
883             }  else {
884                 // Cannot optimize at this stage; shift & potentially rebox as a double.
885                 result = addToGraph(BitURShift, op1, op2);
886                 result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result));
887             }
888             set(currentInstruction[1].u.operand, result);
889             NEXT_OPCODE(op_urshift);
890         }
891
892         // === Increment/Decrement opcodes ===
893
894         case op_pre_inc: {
895             unsigned srcDst = currentInstruction[1].u.operand;
896             NodeIndex op = getToNumber(srcDst);
897             set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
898             NEXT_OPCODE(op_pre_inc);
899         }
900
901         case op_post_inc: {
902             unsigned result = currentInstruction[1].u.operand;
903             unsigned srcDst = currentInstruction[2].u.operand;
904             NodeIndex op = getToNumber(srcDst);
905             set(result, op);
906             set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
907             NEXT_OPCODE(op_post_inc);
908         }
909
910         case op_pre_dec: {
911             unsigned srcDst = currentInstruction[1].u.operand;
912             NodeIndex op = getToNumber(srcDst);
913             set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
914             NEXT_OPCODE(op_pre_dec);
915         }
916
917         case op_post_dec: {
918             unsigned result = currentInstruction[1].u.operand;
919             unsigned srcDst = currentInstruction[2].u.operand;
920             NodeIndex op = getToNumber(srcDst);
921             set(result, op);
922             set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
923             NEXT_OPCODE(op_post_dec);
924         }
925
926         // === Arithmetic operations ===
927
928         case op_add: {
929             NodeIndex op1 = get(currentInstruction[2].u.operand);
930             NodeIndex op2 = get(currentInstruction[3].u.operand);
931             if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
932                 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2))));
933             else
934                 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2)));
935             NEXT_OPCODE(op_add);
936         }
937
938         case op_sub: {
939             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
940             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
941             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2)));
942             NEXT_OPCODE(op_sub);
943         }
944
945         case op_mul: {
946             // Multiply requires that the inputs are not truncated, unfortunately.
947             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
948             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
949             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2)));
950             NEXT_OPCODE(op_mul);
951         }
952
953         case op_mod: {
954             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
955             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
956             set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, OpInfo(NodeUseBottom), op1, op2)));
957             NEXT_OPCODE(op_mod);
958         }
959
960         case op_div: {
961             NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
962             NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
963             set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2)));
964             NEXT_OPCODE(op_div);
965         }
966
967         // === Misc operations ===
968
969 #if ENABLE(DEBUG_WITH_BREAKPOINT)
970         case op_debug:
971             addToGraph(Breakpoint);
972             NEXT_OPCODE(op_debug);
973 #endif
974         case op_mov: {
975             NodeIndex op = get(currentInstruction[2].u.operand);
976             set(currentInstruction[1].u.operand, op);
977             NEXT_OPCODE(op_mov);
978         }
979
980         case op_check_has_instance:
981             addToGraph(CheckHasInstance, get(currentInstruction[1].u.operand));
982             NEXT_OPCODE(op_check_has_instance);
983
984         case op_instanceof: {
985             NodeIndex value = get(currentInstruction[2].u.operand);
986             NodeIndex baseValue = get(currentInstruction[3].u.operand);
987             NodeIndex prototype = get(currentInstruction[4].u.operand);
988             set(currentInstruction[1].u.operand, addToGraph(InstanceOf, value, baseValue, prototype));
989             NEXT_OPCODE(op_instanceof);
990         }
991
992         case op_not: {
993             NodeIndex value = get(currentInstruction[2].u.operand);
994             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
995             NEXT_OPCODE(op_not);
996         }
997             
998         case op_to_primitive: {
999             NodeIndex value = get(currentInstruction[2].u.operand);
1000             set(currentInstruction[1].u.operand, addToGraph(ToPrimitive, value));
1001             NEXT_OPCODE(op_to_primitive);
1002         }
1003             
1004         case op_strcat: {
1005             int startOperand = currentInstruction[2].u.operand;
1006             int numOperands = currentInstruction[3].u.operand;
1007             for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
1008                 addVarArgChild(get(operandIdx));
1009             set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, StrCat, OpInfo(0), OpInfo(0)));
1010             NEXT_OPCODE(op_strcat);
1011         }
1012
1013         case op_less: {
1014             NodeIndex op1 = get(currentInstruction[2].u.operand);
1015             NodeIndex op2 = get(currentInstruction[3].u.operand);
1016             set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
1017             NEXT_OPCODE(op_less);
1018         }
1019
1020         case op_lesseq: {
1021             NodeIndex op1 = get(currentInstruction[2].u.operand);
1022             NodeIndex op2 = get(currentInstruction[3].u.operand);
1023             set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
1024             NEXT_OPCODE(op_lesseq);
1025         }
1026
1027         case op_greater: {
1028             NodeIndex op1 = get(currentInstruction[2].u.operand);
1029             NodeIndex op2 = get(currentInstruction[3].u.operand);
1030             set(currentInstruction[1].u.operand, addToGraph(CompareGreater, op1, op2));
1031             NEXT_OPCODE(op_greater);
1032         }
1033
1034         case op_greatereq: {
1035             NodeIndex op1 = get(currentInstruction[2].u.operand);
1036             NodeIndex op2 = get(currentInstruction[3].u.operand);
1037             set(currentInstruction[1].u.operand, addToGraph(CompareGreaterEq, op1, op2));
1038             NEXT_OPCODE(op_greatereq);
1039         }
1040
1041         case op_eq: {
1042             NodeIndex op1 = get(currentInstruction[2].u.operand);
1043             NodeIndex op2 = get(currentInstruction[3].u.operand);
1044             set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
1045             NEXT_OPCODE(op_eq);
1046         }
1047
1048         case op_eq_null: {
1049             NodeIndex value = get(currentInstruction[2].u.operand);
1050             set(currentInstruction[1].u.operand, addToGraph(CompareEq, value, constantNull()));
1051             NEXT_OPCODE(op_eq_null);
1052         }
1053
1054         case op_stricteq: {
1055             NodeIndex op1 = get(currentInstruction[2].u.operand);
1056             NodeIndex op2 = get(currentInstruction[3].u.operand);
1057             set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
1058             NEXT_OPCODE(op_stricteq);
1059         }
1060
1061         case op_neq: {
1062             NodeIndex op1 = get(currentInstruction[2].u.operand);
1063             NodeIndex op2 = get(currentInstruction[3].u.operand);
1064             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
1065             NEXT_OPCODE(op_neq);
1066         }
1067
1068         case op_neq_null: {
1069             NodeIndex value = get(currentInstruction[2].u.operand);
1070             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, value, constantNull())));
1071             NEXT_OPCODE(op_neq_null);
1072         }
1073
1074         case op_nstricteq: {
1075             NodeIndex op1 = get(currentInstruction[2].u.operand);
1076             NodeIndex op2 = get(currentInstruction[3].u.operand);
1077             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareStrictEq, op1, op2)));
1078             NEXT_OPCODE(op_nstricteq);
1079         }
1080
1081         // === Property access operations ===
1082
1083         case op_get_by_val: {
1084             PredictedType prediction = getPrediction();
1085             
1086             NodeIndex base = get(currentInstruction[2].u.operand);
1087             NodeIndex property = get(currentInstruction[3].u.operand);
1088
1089             NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property);
1090             set(currentInstruction[1].u.operand, getByVal);
1091
1092             NEXT_OPCODE(op_get_by_val);
1093         }
1094
1095         case op_put_by_val: {
1096             NodeIndex base = get(currentInstruction[1].u.operand);
1097             NodeIndex property = get(currentInstruction[2].u.operand);
1098             NodeIndex value = get(currentInstruction[3].u.operand);
1099
1100             addToGraph(PutByVal, base, property, value);
1101
1102             NEXT_OPCODE(op_put_by_val);
1103         }
1104             
1105         case op_method_check: {
1106             Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
1107             
1108             PredictedType prediction = getPrediction();
1109             
1110             ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
1111             
1112             NodeIndex base = get(getInstruction[2].u.operand);
1113             unsigned identifier = getInstruction[3].u.operand;
1114                 
1115             // Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
1116             // node, which is a lot more efficient.
1117             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1118             MethodCallLinkInfo& methodCall = m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
1119             
1120             if (methodCall.seen && !!methodCall.cachedStructure && !stubInfo.seen) {
1121                 // It's monomorphic as far as we can tell, since the method_check was linked
1122                 // but the slow path (i.e. the normal get_by_id) never fired.
1123             
1124                 NodeIndex checkMethod = addToGraph(CheckMethod, OpInfo(identifier), OpInfo(m_graph.m_methodCheckData.size()), base);
1125                 set(getInstruction[1].u.operand, checkMethod);
1126                 
1127                 MethodCheckData methodCheckData;
1128                 methodCheckData.structure = methodCall.cachedStructure.get();
1129                 methodCheckData.prototypeStructure = methodCall.cachedPrototypeStructure.get();
1130                 methodCheckData.function = methodCall.cachedFunction.get();
1131                 methodCheckData.prototype = methodCall.cachedPrototype.get();
1132                 m_graph.m_methodCheckData.append(methodCheckData);
1133             } else {
1134                 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(prediction), base);
1135                 set(getInstruction[1].u.operand, getMethod);
1136             }
1137             
1138             m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
1139             continue;
1140         }
1141         case op_get_scoped_var: {
1142             PredictedType prediction = getPrediction();
1143             int dst = currentInstruction[1].u.operand;
1144             int slot = currentInstruction[2].u.operand;
1145             int depth = currentInstruction[3].u.operand;
1146             NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
1147             NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
1148             set(dst, getScopedVar);
1149             NEXT_OPCODE(op_get_scoped_var);
1150         }
1151         case op_put_scoped_var: {
1152             int slot = currentInstruction[1].u.operand;
1153             int depth = currentInstruction[2].u.operand;
1154             int source = currentInstruction[3].u.operand;
1155             NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
1156             addToGraph(PutScopedVar, OpInfo(slot), getScopeChain, get(source));
1157             NEXT_OPCODE(op_put_scoped_var);
1158         }
1159         case op_get_by_id: {
1160             PredictedType prediction = getPrediction();
1161             
1162             NodeIndex base = get(currentInstruction[2].u.operand);
1163             unsigned identifierNumber = currentInstruction[3].u.operand;
1164             
1165             Identifier identifier = m_codeBlock->identifier(identifierNumber);
1166             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1167             
1168             size_t offset = notFound;
1169             StructureSet structureSet;
1170             if (stubInfo.seen) {
1171                 switch (stubInfo.accessType) {
1172                 case access_get_by_id_self: {
1173                     Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
1174                     offset = structure->get(*m_globalData, identifier);
1175                     
1176                     if (offset != notFound)
1177                         structureSet.add(structure);
1178
1179                     if (offset != notFound)
1180                         ASSERT(structureSet.size());
1181                     break;
1182                 }
1183                     
1184                 case access_get_by_id_self_list: {
1185                     PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
1186                     unsigned size = stubInfo.u.getByIdProtoList.listSize;
1187                     for (unsigned i = 0; i < size; ++i) {
1188                         if (!list->list[i].isDirect) {
1189                             offset = notFound;
1190                             break;
1191                         }
1192                         
1193                         Structure* structure = list->list[i].base.get();
1194                         if (structureSet.contains(structure))
1195                             continue;
1196                         
1197                         size_t myOffset = structure->get(*m_globalData, identifier);
1198                     
1199                         if (myOffset == notFound) {
1200                             offset = notFound;
1201                             break;
1202                         }
1203                     
1204                         if (!i)
1205                             offset = myOffset;
1206                         else if (offset != myOffset) {
1207                             offset = notFound;
1208                             break;
1209                         }
1210                     
1211                         structureSet.add(structure);
1212                     }
1213                     
1214                     if (offset != notFound)
1215                         ASSERT(structureSet.size());
1216                     break;
1217                 }
1218                     
1219                 default:
1220                     ASSERT(offset == notFound);
1221                     break;
1222                 }
1223             }
1224                         
1225             if (offset != notFound) {
1226                 ASSERT(structureSet.size());
1227                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), base);
1228                 set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base)));
1229                 
1230                 StorageAccessData storageAccessData;
1231                 storageAccessData.offset = offset;
1232                 storageAccessData.identifierNumber = identifierNumber;
1233                 m_graph.m_storageAccessData.append(storageAccessData);
1234             } else
1235                 set(currentInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
1236
1237             NEXT_OPCODE(op_get_by_id);
1238         }
1239
1240         case op_put_by_id: {
1241             NodeIndex value = get(currentInstruction[3].u.operand);
1242             NodeIndex base = get(currentInstruction[1].u.operand);
1243             unsigned identifierNumber = currentInstruction[2].u.operand;
1244             bool direct = currentInstruction[8].u.operand;
1245
1246             StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
1247             if (!stubInfo.seen)
1248                 addToGraph(ForceOSRExit);
1249             
1250             bool alreadyGenerated = false;
1251             
1252             if (stubInfo.seen && !m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
1253                 switch (stubInfo.accessType) {
1254                 case access_put_by_id_replace: {
1255                     Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
1256                     Identifier identifier = m_codeBlock->identifier(identifierNumber);
1257                     size_t offset = structure->get(*m_globalData, identifier);
1258                     
1259                     if (offset != notFound) {
1260                         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), base);
1261                         addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
1262                         
1263                         StorageAccessData storageAccessData;
1264                         storageAccessData.offset = offset;
1265                         storageAccessData.identifierNumber = identifierNumber;
1266                         m_graph.m_storageAccessData.append(storageAccessData);
1267                         
1268                         alreadyGenerated = true;
1269                     }
1270                     break;
1271                 }
1272                     
1273                 case access_put_by_id_transition: {
1274                     Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
1275                     Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
1276                     
1277                     if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
1278                         break;
1279                     
1280                     StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
1281                     
1282                     Identifier identifier = m_codeBlock->identifier(identifierNumber);
1283                     size_t offset = newStructure->get(*m_globalData, identifier);
1284                     
1285                     if (offset != notFound) {
1286                         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure)), base);
1287                         if (!direct) {
1288                             for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
1289                                 JSValue prototype = (*it)->storedPrototype();
1290                                 if (prototype.isNull())
1291                                     continue;
1292                                 ASSERT(prototype.isCell());
1293                                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())), cellConstant(prototype.asCell()));
1294                             }
1295                         }
1296                         addToGraph(PutStructure, OpInfo(m_graph.addStructureTransitionData(StructureTransitionData(previousStructure, newStructure))), base);
1297                         
1298                         addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
1299                         
1300                         StorageAccessData storageAccessData;
1301                         storageAccessData.offset = offset;
1302                         storageAccessData.identifierNumber = identifierNumber;
1303                         m_graph.m_storageAccessData.append(storageAccessData);
1304                         
1305                         alreadyGenerated = true;
1306                     }
1307                     break;
1308                 }
1309                     
1310                 default:
1311                     break;
1312                 }
1313             }
1314             
1315             if (!alreadyGenerated) {
1316                 if (direct)
1317                     addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
1318                 else
1319                     addToGraph(PutById, OpInfo(identifierNumber), base, value);
1320             }
1321
1322             NEXT_OPCODE(op_put_by_id);
1323         }
1324
1325         case op_get_global_var: {
1326             PredictedType prediction = getPrediction();
1327             
1328             NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
1329             set(currentInstruction[1].u.operand, getGlobalVar);
1330             m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction);
1331             NEXT_OPCODE(op_get_global_var);
1332         }
1333
1334         case op_put_global_var: {
1335             NodeIndex value = get(currentInstruction[2].u.operand);
1336             addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
1337             NEXT_OPCODE(op_put_global_var);
1338         }
1339
1340         // === Block terminators. ===
1341
1342         case op_jmp: {
1343             unsigned relativeOffset = currentInstruction[1].u.operand;
1344             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
1345             LAST_OPCODE(op_jmp);
1346         }
1347
1348         case op_loop: {
1349             unsigned relativeOffset = currentInstruction[1].u.operand;
1350             addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
1351             LAST_OPCODE(op_loop);
1352         }
1353
1354         case op_jtrue: {
1355             unsigned relativeOffset = currentInstruction[2].u.operand;
1356             NodeIndex condition = get(currentInstruction[1].u.operand);
1357             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jtrue)), condition);
1358             LAST_OPCODE(op_jtrue);
1359         }
1360
1361         case op_jfalse: {
1362             unsigned relativeOffset = currentInstruction[2].u.operand;
1363             NodeIndex condition = get(currentInstruction[1].u.operand);
1364             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jfalse)), OpInfo(m_currentIndex + relativeOffset), condition);
1365             LAST_OPCODE(op_jfalse);
1366         }
1367
1368         case op_loop_if_true: {
1369             unsigned relativeOffset = currentInstruction[2].u.operand;
1370             NodeIndex condition = get(currentInstruction[1].u.operand);
1371             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_true)), condition);
1372             LAST_OPCODE(op_loop_if_true);
1373         }
1374
1375         case op_loop_if_false: {
1376             unsigned relativeOffset = currentInstruction[2].u.operand;
1377             NodeIndex condition = get(currentInstruction[1].u.operand);
1378             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_false)), OpInfo(m_currentIndex + relativeOffset), condition);
1379             LAST_OPCODE(op_loop_if_false);
1380         }
1381
1382         case op_jeq_null: {
1383             unsigned relativeOffset = currentInstruction[2].u.operand;
1384             NodeIndex value = get(currentInstruction[1].u.operand);
1385             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
1386             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
1387             LAST_OPCODE(op_jeq_null);
1388         }
1389
1390         case op_jneq_null: {
1391             unsigned relativeOffset = currentInstruction[2].u.operand;
1392             NodeIndex value = get(currentInstruction[1].u.operand);
1393             NodeIndex condition = addToGraph(CompareEq, value, constantNull());
1394             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
1395             LAST_OPCODE(op_jneq_null);
1396         }
1397
1398         case op_jless: {
1399             unsigned relativeOffset = currentInstruction[3].u.operand;
1400             NodeIndex op1 = get(currentInstruction[1].u.operand);
1401             NodeIndex op2 = get(currentInstruction[2].u.operand);
1402             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1403             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jless)), condition);
1404             LAST_OPCODE(op_jless);
1405         }
1406
1407         case op_jlesseq: {
1408             unsigned relativeOffset = currentInstruction[3].u.operand;
1409             NodeIndex op1 = get(currentInstruction[1].u.operand);
1410             NodeIndex op2 = get(currentInstruction[2].u.operand);
1411             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1412             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jlesseq)), condition);
1413             LAST_OPCODE(op_jlesseq);
1414         }
1415
1416         case op_jgreater: {
1417             unsigned relativeOffset = currentInstruction[3].u.operand;
1418             NodeIndex op1 = get(currentInstruction[1].u.operand);
1419             NodeIndex op2 = get(currentInstruction[2].u.operand);
1420             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1421             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreater)), condition);
1422             LAST_OPCODE(op_jgreater);
1423         }
1424
1425         case op_jgreatereq: {
1426             unsigned relativeOffset = currentInstruction[3].u.operand;
1427             NodeIndex op1 = get(currentInstruction[1].u.operand);
1428             NodeIndex op2 = get(currentInstruction[2].u.operand);
1429             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1430             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreatereq)), condition);
1431             LAST_OPCODE(op_jgreatereq);
1432         }
1433
1434         case op_jnless: {
1435             unsigned relativeOffset = currentInstruction[3].u.operand;
1436             NodeIndex op1 = get(currentInstruction[1].u.operand);
1437             NodeIndex op2 = get(currentInstruction[2].u.operand);
1438             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1439             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnless)), OpInfo(m_currentIndex + relativeOffset), condition);
1440             LAST_OPCODE(op_jnless);
1441         }
1442
1443         case op_jnlesseq: {
1444             unsigned relativeOffset = currentInstruction[3].u.operand;
1445             NodeIndex op1 = get(currentInstruction[1].u.operand);
1446             NodeIndex op2 = get(currentInstruction[2].u.operand);
1447             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1448             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnlesseq)), OpInfo(m_currentIndex + relativeOffset), condition);
1449             LAST_OPCODE(op_jnlesseq);
1450         }
1451
1452         case op_jngreater: {
1453             unsigned relativeOffset = currentInstruction[3].u.operand;
1454             NodeIndex op1 = get(currentInstruction[1].u.operand);
1455             NodeIndex op2 = get(currentInstruction[2].u.operand);
1456             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1457             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreater)), OpInfo(m_currentIndex + relativeOffset), condition);
1458             LAST_OPCODE(op_jngreater);
1459         }
1460
1461         case op_jngreatereq: {
1462             unsigned relativeOffset = currentInstruction[3].u.operand;
1463             NodeIndex op1 = get(currentInstruction[1].u.operand);
1464             NodeIndex op2 = get(currentInstruction[2].u.operand);
1465             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1466             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreatereq)), OpInfo(m_currentIndex + relativeOffset), condition);
1467             LAST_OPCODE(op_jngreatereq);
1468         }
1469
1470         case op_loop_if_less: {
1471             unsigned relativeOffset = currentInstruction[3].u.operand;
1472             NodeIndex op1 = get(currentInstruction[1].u.operand);
1473             NodeIndex op2 = get(currentInstruction[2].u.operand);
1474             NodeIndex condition = addToGraph(CompareLess, op1, op2);
1475             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_less)), condition);
1476             LAST_OPCODE(op_loop_if_less);
1477         }
1478
1479         case op_loop_if_lesseq: {
1480             unsigned relativeOffset = currentInstruction[3].u.operand;
1481             NodeIndex op1 = get(currentInstruction[1].u.operand);
1482             NodeIndex op2 = get(currentInstruction[2].u.operand);
1483             NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
1484             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_lesseq)), condition);
1485             LAST_OPCODE(op_loop_if_lesseq);
1486         }
1487
1488         case op_loop_if_greater: {
1489             unsigned relativeOffset = currentInstruction[3].u.operand;
1490             NodeIndex op1 = get(currentInstruction[1].u.operand);
1491             NodeIndex op2 = get(currentInstruction[2].u.operand);
1492             NodeIndex condition = addToGraph(CompareGreater, op1, op2);
1493             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greater)), condition);
1494             LAST_OPCODE(op_loop_if_greater);
1495         }
1496
1497         case op_loop_if_greatereq: {
1498             unsigned relativeOffset = currentInstruction[3].u.operand;
1499             NodeIndex op1 = get(currentInstruction[1].u.operand);
1500             NodeIndex op2 = get(currentInstruction[2].u.operand);
1501             NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
1502             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greatereq)), condition);
1503             LAST_OPCODE(op_loop_if_greatereq);
1504         }
1505
1506         case op_ret:
1507             addToGraph(Return, get(currentInstruction[1].u.operand));
1508             LAST_OPCODE(op_ret);
1509             
1510         case op_end:
1511             addToGraph(Return, get(currentInstruction[1].u.operand));
1512             LAST_OPCODE(op_end);
1513
1514         case op_throw:
1515             addToGraph(Throw, get(currentInstruction[1].u.operand));
1516             LAST_OPCODE(op_throw);
1517             
1518         case op_throw_reference_error:
1519             addToGraph(ThrowReferenceError);
1520             LAST_OPCODE(op_throw_reference_error);
1521             
1522         case op_call: {
1523             NodeIndex callTarget = get(currentInstruction[1].u.operand);
1524             if (m_graph.isFunctionConstant(m_codeBlock, callTarget)) {
1525                 int argCount = currentInstruction[2].u.operand;
1526                 int registerOffset = currentInstruction[3].u.operand;
1527                 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
1528                 int lastArg = firstArg + argCount - 1;
1529                 
1530                 // Do we have a result?
1531                 bool usesResult = false;
1532                 int resultOperand = 0; // make compiler happy
1533                 Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
1534                 if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
1535                     resultOperand = putInstruction[1].u.operand;
1536                     usesResult = true;
1537                 }
1538                 
1539                 DFG::Intrinsic intrinsic = m_graph.valueOfFunctionConstant(m_codeBlock, callTarget)->executable()->intrinsic();
1540                 
1541                 if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg)) {
1542                     // NEXT_OPCODE() has to be inside braces.
1543                     NEXT_OPCODE(op_call);
1544                 }
1545             }
1546             
1547             addCall(interpreter, currentInstruction, Call);
1548             NEXT_OPCODE(op_call);
1549         }
1550             
1551         case op_construct: {
1552             addCall(interpreter, currentInstruction, Construct);
1553             NEXT_OPCODE(op_construct);
1554         }
1555             
1556         case op_call_put_result:
1557             NEXT_OPCODE(op_call_put_result);
1558
1559         case op_resolve: {
1560             PredictedType prediction = getPrediction();
1561             
1562             unsigned identifier = currentInstruction[2].u.operand;
1563
1564             NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(prediction));
1565             set(currentInstruction[1].u.operand, resolve);
1566
1567             NEXT_OPCODE(op_resolve);
1568         }
1569
1570         case op_resolve_base: {
1571             PredictedType prediction = getPrediction();
1572             
1573             unsigned identifier = currentInstruction[2].u.operand;
1574
1575             NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(prediction));
1576             set(currentInstruction[1].u.operand, resolve);
1577
1578             NEXT_OPCODE(op_resolve_base);
1579         }
1580             
1581         case op_resolve_global: {
1582             PredictedType prediction = getPrediction();
1583             
1584             NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
1585             m_graph.m_resolveGlobalData.append(ResolveGlobalData());
1586             ResolveGlobalData& data = m_graph.m_resolveGlobalData.last();
1587             data.identifierNumber = currentInstruction[2].u.operand;
1588             data.resolveInfoIndex = m_globalResolveNumber++;
1589             set(currentInstruction[1].u.operand, resolve);
1590
1591             NEXT_OPCODE(op_resolve_global);
1592         }
1593
1594         case op_loop_hint: {
1595             // Baseline->DFG OSR jumps between loop hints. The DFG assumes that Baseline->DFG
1596             // OSR can only happen at basic block boundaries. Assert that these two statements
1597             // are compatible.
1598             ASSERT_UNUSED(blockBegin, m_currentIndex == blockBegin);
1599             
1600             m_currentBlock->isOSRTarget = true;
1601             
1602             NEXT_OPCODE(op_loop_hint);
1603         }
1604
1605         default:
1606             // Parse failed! This should not happen because the capabilities checker
1607             // should have caught it.
1608             ASSERT_NOT_REACHED();
1609             return false;
1610         }
1611         
1612         ASSERT(canCompileOpcode(opcodeID));
1613     }
1614 }
1615
1616 template<ByteCodeParser::PhiStackType stackType>
1617 void ByteCodeParser::processPhiStack()
1618 {
1619     Vector<PhiStackEntry, 16>& phiStack = (stackType == ArgumentPhiStack) ? m_argumentPhiStack : m_localPhiStack;
1620
1621     while (!phiStack.isEmpty()) {
1622         PhiStackEntry entry = phiStack.last();
1623         phiStack.removeLast();
1624         
1625         PredecessorList& predecessors = entry.m_block->m_predecessors;
1626         unsigned varNo = entry.m_varNo;
1627         VariableAccessData* dataForPhi = m_graph[entry.m_phi].variableAccessData();
1628
1629         for (size_t i = 0; i < predecessors.size(); ++i) {
1630             BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
1631
1632             VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_argumentsAtTail[varNo] : predecessorBlock->m_localsAtTail[varNo];
1633
1634             NodeIndex valueInPredecessor = var.value;
1635             if (valueInPredecessor == NoNode) {
1636                 valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo)));
1637                 var.setFirstTime(valueInPredecessor);
1638                 if (stackType == ArgumentPhiStack)
1639                     predecessorBlock->m_argumentsAtHead[varNo].setFirstTime(valueInPredecessor);
1640                 else
1641                     predecessorBlock->m_localsAtHead[varNo].setFirstTime(valueInPredecessor);
1642                 phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
1643             } else if (m_graph[valueInPredecessor].op == GetLocal) {
1644                 // We want to ensure that the VariableAccessDatas are identical between the
1645                 // GetLocal and its block-local Phi. Strictly speaking we only need the two
1646                 // to be unified. But for efficiency, we want the code that creates GetLocals
1647                 // and Phis to try to reuse VariableAccessDatas as much as possible.
1648                 ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1()].variableAccessData());
1649                 
1650                 valueInPredecessor = m_graph[valueInPredecessor].child1();
1651             }
1652             ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi || (m_graph[valueInPredecessor].op == SetArgument && stackType == ArgumentPhiStack));
1653             
1654             VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData();
1655             
1656             dataForPredecessor->unify(dataForPhi);
1657
1658             Node* phiNode = &m_graph[entry.m_phi];
1659             if (phiNode->refCount())
1660                 m_graph.ref(valueInPredecessor);
1661
1662             if (phiNode->child1() == NoNode) {
1663                 phiNode->children.fixed.child1 = valueInPredecessor;
1664                 continue;
1665             }
1666             if (phiNode->child2() == NoNode) {
1667                 phiNode->children.fixed.child2 = valueInPredecessor;
1668                 continue;
1669             }
1670             if (phiNode->child3() == NoNode) {
1671                 phiNode->children.fixed.child3 = valueInPredecessor;
1672                 continue;
1673             }
1674             
1675             NodeIndex newPhi = addToGraph(Phi, OpInfo(dataForPhi));
1676             
1677             phiNode = &m_graph[entry.m_phi]; // reload after vector resize
1678             Node& newPhiNode = m_graph[newPhi];
1679             if (phiNode->refCount())
1680                 m_graph.ref(newPhi);
1681
1682             newPhiNode.children.fixed.child1 = phiNode->child1();
1683             newPhiNode.children.fixed.child2 = phiNode->child2();
1684             newPhiNode.children.fixed.child3 = phiNode->child3();
1685
1686             phiNode->children.fixed.child1 = newPhi;
1687             phiNode->children.fixed.child1 = valueInPredecessor;
1688             phiNode->children.fixed.child3 = NoNode;
1689         }
1690     }
1691 }
1692
1693 void ByteCodeParser::setupPredecessors()
1694 {
1695     for (BlockIndex index = 0; index < m_graph.m_blocks.size(); ++index) {
1696         BasicBlock* block = m_graph.m_blocks[index].get();
1697         ASSERT(block->end != NoNode);
1698         Node& node = m_graph[block->end - 1];
1699         ASSERT(node.isTerminal());
1700
1701         if (node.isJump())
1702             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1703         else if (node.isBranch()) {
1704             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
1705             m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
1706         }
1707     }
1708 }
1709
1710 bool ByteCodeParser::parse()
1711 {
1712     // Set during construction.
1713     ASSERT(!m_currentIndex);
1714
1715     for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
1716         // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions.
1717         unsigned limit = jumpTargetIndex < m_codeBlock->numberOfJumpTargets() ? m_codeBlock->jumpTarget(jumpTargetIndex) : m_codeBlock->instructions().size();
1718         ASSERT(m_currentIndex < limit);
1719
1720         // Loop until we reach the current limit (i.e. next jump target).
1721         do {
1722             OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
1723             m_currentBlock = block.get();
1724             m_graph.m_blocks.append(block.release());
1725
1726             if (!parseBlock(limit))
1727                 return false;
1728             // We should not have gone beyond the limit.
1729             ASSERT(m_currentIndex <= limit);
1730
1731             m_currentBlock->end = m_graph.size();
1732         } while (m_currentIndex < limit);
1733     }
1734
1735     // Should have reached the end of the instructions.
1736     ASSERT(m_currentIndex == m_codeBlock->instructions().size());
1737
1738     setupPredecessors();
1739     processPhiStack<LocalPhiStack>();
1740     processPhiStack<ArgumentPhiStack>();
1741     
1742     m_graph.m_preservedVars = m_preservedVars;
1743     m_graph.m_localVars = m_numLocals;
1744     m_graph.m_parameterSlots = m_parameterSlots;
1745
1746     return true;
1747 }
1748
1749 bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
1750 {
1751 #if DFG_DEBUG_LOCAL_DISBALE
1752     UNUSED_PARAM(graph);
1753     UNUSED_PARAM(globalData);
1754     UNUSED_PARAM(codeBlock);
1755     return false;
1756 #else
1757     return ByteCodeParser(globalData, codeBlock, codeBlock->alternative(), graph).parse();
1758 #endif
1759 }
1760
1761 } } // namespace JSC::DFG
1762
1763 #endif