2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 #include "CodeBlock.h"
33 #include "PredictionTracker.h"
34 #include "RegisterFile.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/Vector.h>
37 #include <wtf/StdLibExtras.h>
46 typedef uint32_t BlockIndex;
48 // For every local variable we track any existing get or set of the value.
49 // We track the get so that these may be shared, and we track the set to
50 // retrieve the current value, and to reference the final definition.
51 struct VariableRecord {
60 struct MethodCheckData {
61 // It is safe to refer to these directly because they are shadowed by
62 // the old JIT's CodeBlock's MethodCallLinkInfo.
64 Structure* prototypeStructure;
68 bool operator==(const MethodCheckData& other) const
70 if (structure != other.structure)
72 if (prototypeStructure != other.prototypeStructure)
74 if (function != other.function)
76 if (prototype != other.prototype)
81 bool operator!=(const MethodCheckData& other) const
83 return !(*this == other);
87 typedef Vector <BlockIndex, 2> PredecessorList;
90 BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals)
91 : bytecodeBegin(bytecodeBegin)
95 , m_arguments(numArguments)
100 static inline BlockIndex getBytecodeBegin(OwnPtr<BasicBlock>* block)
102 return (*block)->bytecodeBegin;
105 unsigned bytecodeBegin;
110 PredecessorList m_predecessors;
111 Vector <VariableRecord, 8> m_arguments;
112 Vector <VariableRecord, 16> m_locals;
118 // The dataflow graph is an ordered vector of nodes.
119 // The order may be significant for nodes with side-effects (property accesses, value conversions).
120 // Nodes that are 'dead' remain in the vector with refCount 0.
121 class Graph : public Vector<Node, 64> {
123 Graph(unsigned numArguments, unsigned numVariables)
124 : m_predictions(numArguments, numVariables)
128 // Mark a node as being referenced.
129 void ref(NodeIndex nodeIndex)
131 Node& node = at(nodeIndex);
132 // If the value (before incrementing) was at refCount zero then we need to ref its children.
134 refChildren(nodeIndex);
138 // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
139 void dump(CodeBlock* = 0);
140 void dump(NodeIndex, CodeBlock* = 0);
143 BlockIndex blockIndexForBytecodeOffset(unsigned bytecodeBegin)
145 OwnPtr<BasicBlock>* begin = m_blocks.begin();
146 OwnPtr<BasicBlock>* block = binarySearch<OwnPtr<BasicBlock>, unsigned, BasicBlock::getBytecodeBegin>(begin, m_blocks.size(), bytecodeBegin);
147 ASSERT(block >= m_blocks.begin() && block < m_blocks.end());
148 return static_cast<BlockIndex>(block - begin);
151 BasicBlock& blockForBytecodeOffset(unsigned bytecodeBegin)
153 return *m_blocks[blockIndexForBytecodeOffset(bytecodeBegin)];
156 PredictionTracker& predictions()
158 return m_predictions;
161 bool predict(int operand, PredictedType prediction, PredictionSource source)
163 return m_predictions.predict(operand, prediction, source);
166 bool predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source)
168 return m_predictions.predictGlobalVar(varNumber, prediction, source);
171 bool predict(Node& node, PredictedType prediction, PredictionSource source)
175 return predict(node.local(), prediction, source);
178 return predictGlobalVar(node.varNumber(), prediction, source);
185 return node.predict(prediction, source);
191 PredictedType getPrediction(int operand)
193 return m_predictions.getPrediction(operand);
196 PredictedType getGlobalVarPrediction(unsigned varNumber)
198 return m_predictions.getGlobalVarPrediction(varNumber);
201 PredictedType getMethodCheckPrediction(Node& node)
203 return makePrediction(predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function), StrongPrediction);
206 PredictedType getPrediction(Node& node)
208 Node* nodePtr = &node;
210 if (nodePtr->op == ValueToNumber)
211 nodePtr = &(*this)[nodePtr->child1()];
213 if (nodePtr->op == ValueToInt32)
214 nodePtr = &(*this)[nodePtr->child1()];
216 switch (nodePtr->op) {
218 return getPrediction(nodePtr->local());
220 return getGlobalVarPrediction(nodePtr->varNumber());
226 return nodePtr->getPrediction();
228 return getMethodCheckPrediction(*nodePtr);
234 // Helper methods to check nodes for constants.
235 bool isConstant(NodeIndex nodeIndex)
237 return at(nodeIndex).hasConstant();
239 bool isJSConstant(NodeIndex nodeIndex)
241 return at(nodeIndex).hasConstant();
243 bool isInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex)
245 return at(nodeIndex).isInt32Constant(codeBlock);
247 bool isDoubleConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
249 return at(nodeIndex).isDoubleConstant(codeBlock);
251 bool isNumberConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
253 return at(nodeIndex).isNumberConstant(codeBlock);
255 bool isBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
257 return at(nodeIndex).isBooleanConstant(codeBlock);
259 bool isFunctionConstant(CodeBlock* codeBlock, JSGlobalData& globalData, NodeIndex nodeIndex)
261 if (!isJSConstant(nodeIndex))
263 if (!getJSFunction(globalData, valueOfJSConstant(codeBlock, nodeIndex)))
267 // Helper methods get constant values from nodes.
268 JSValue valueOfJSConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
270 if (at(nodeIndex).hasMethodCheckData())
271 return JSValue(m_methodCheckData[at(nodeIndex).methodCheckDataIndex()].function);
272 return valueOfJSConstantNode(codeBlock, nodeIndex);
274 int32_t valueOfInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex)
276 return valueOfJSConstantNode(codeBlock, nodeIndex).asInt32();
278 double valueOfNumberConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
280 return valueOfJSConstantNode(codeBlock, nodeIndex).uncheckedGetNumber();
282 bool valueOfBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
284 return valueOfJSConstantNode(codeBlock, nodeIndex).getBoolean();
286 JSFunction* valueOfFunctionConstant(CodeBlock* codeBlock, JSGlobalData& globalData, NodeIndex nodeIndex)
288 JSCell* function = getJSFunction(globalData, valueOfJSConstant(codeBlock, nodeIndex));
290 return asFunction(function);
294 static const char *opName(NodeType);
297 void predictArgumentTypes(ExecState*, CodeBlock*);
299 Vector< OwnPtr<BasicBlock> , 8> m_blocks;
300 Vector<NodeIndex, 16> m_varArgChildren;
301 Vector<MethodCheckData> m_methodCheckData;
302 unsigned m_preservedVars;
303 unsigned m_parameterSlots;
306 JSValue valueOfJSConstantNode(CodeBlock* codeBlock, NodeIndex nodeIndex)
308 return codeBlock->constantRegister(FirstConstantRegisterIndex + at(nodeIndex).constantNumber()).get();
311 // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa.
312 void refChildren(NodeIndex);
314 PredictionTracker m_predictions;
317 } } // namespace JSC::DFG