Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (94448 => 94449)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2011-09-02 21:08:27 UTC (rev 94448)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2011-09-02 21:16:25 UTC (rev 94449)
@@ -102,9 +102,9 @@
// Must be a local.
return getLocal((unsigned)operand);
}
- void set(int operand, NodeIndex value, PredictedType prediction = PredictNone)
+ void set(int operand, NodeIndex value, PredictedType staticPrediction = PredictNone)
{
- m_graph.predict(operand, prediction);
+ m_graph.predict(operand, staticPrediction, StaticPrediction);
// Is this an argument?
if (operandIsArgument(operand)) {
@@ -428,12 +428,12 @@
return call;
}
- void predictArray(NodeIndex nodeIndex)
+ void staticallyPredictArray(NodeIndex nodeIndex)
{
- m_graph.predict(m_graph[nodeIndex], PredictArray);
+ m_graph.predict(m_graph[nodeIndex], PredictArray, StaticPrediction);
}
- void predictInt32(NodeIndex nodeIndex)
+ void staticallyPredictInt32(NodeIndex nodeIndex)
{
ASSERT(m_reusableNodeStack.isEmpty());
m_reusableNodeStack.append(&m_graph[nodeIndex]);
@@ -457,7 +457,7 @@
m_reusableNodeStack.append(&m_graph[nodePtr->child2()]);
break;
default:
- m_graph.predict(*nodePtr, PredictInt32);
+ m_graph.predict(*nodePtr, PredictInt32, StaticPrediction);
break;
}
} while (!m_reusableNodeStack.isEmpty());
@@ -587,8 +587,8 @@
case op_bitand: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitand);
}
@@ -596,8 +596,8 @@
case op_bitor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitor);
}
@@ -605,8 +605,8 @@
case op_bitxor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitxor);
}
@@ -614,8 +614,8 @@
case op_rshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
@@ -629,8 +629,8 @@
case op_lshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
@@ -644,8 +644,8 @@
case op_urshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
NodeIndex result;
// The result of a zero-extending right shift is treated as an unsigned value.
// This means that if the top bit is set, the result is not in the int32 range,
@@ -675,7 +675,7 @@
case op_pre_inc: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
- predictInt32(op);
+ staticallyPredictInt32(op);
set(srcDst, addToGraph(ArithAdd, op, one()));
NEXT_OPCODE(op_pre_inc);
}
@@ -684,7 +684,7 @@
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
- predictInt32(op);
+ staticallyPredictInt32(op);
set(result, op);
set(srcDst, addToGraph(ArithAdd, op, one()));
NEXT_OPCODE(op_post_inc);
@@ -693,7 +693,7 @@
case op_pre_dec: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
- predictInt32(op);
+ staticallyPredictInt32(op);
set(srcDst, addToGraph(ArithSub, op, one()));
NEXT_OPCODE(op_pre_dec);
}
@@ -702,7 +702,7 @@
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
- predictInt32(op);
+ staticallyPredictInt32(op);
set(result, op);
set(srcDst, addToGraph(ArithSub, op, one()));
NEXT_OPCODE(op_post_dec);
@@ -717,8 +717,8 @@
// If both operands can statically be determined to the numbers, then this is an arithmetic add.
// Otherwise, we must assume this may be performing a concatenation to a string.
if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
}
if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult())
set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2)));
@@ -732,8 +732,8 @@
NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
- predictInt32(op1);
- predictInt32(op2);
+ staticallyPredictInt32(op1);
+ staticallyPredictInt32(op2);
}
set(currentInstruction[1].u.operand, addToGraph(ArithSub, op1, op2));
NEXT_OPCODE(op_sub);
@@ -878,8 +878,8 @@
case op_get_by_val: {
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
- predictArray(base);
- predictInt32(property);
+ staticallyPredictArray(base);
+ staticallyPredictInt32(property);
NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(PredictNone), base, property, aliases.lookupGetByVal(base, property));
set(currentInstruction[1].u.operand, getByVal);
@@ -892,8 +892,8 @@
NodeIndex base = get(currentInstruction[1].u.operand);
NodeIndex property = get(currentInstruction[2].u.operand);
NodeIndex value = get(currentInstruction[3].u.operand);
- predictArray(base);
- predictInt32(property);
+ staticallyPredictArray(base);
+ staticallyPredictInt32(property);
NodeIndex aliasedGet = aliases.lookupGetByVal(base, property);
NodeIndex putByVal = addToGraph(aliasedGet != NoNode ? PutByValAlias : PutByVal, base, property, value);
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (94448 => 94449)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2011-09-02 21:08:27 UTC (rev 94448)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2011-09-02 21:16:25 UTC (rev 94449)
@@ -135,35 +135,41 @@
return *m_blocks[blockIndexForBytecodeOffset(bytecodeBegin)];
}
- void predict(int operand, PredictedType prediction)
+ void predict(int operand, PredictedType prediction, PredictionSource source)
{
if (operandIsArgument(operand)) {
unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize;
- m_argumentPredictions[argument].m_value |= prediction;
+ mergePrediction(m_argumentPredictions[argument].m_value, makePrediction(prediction, source));
} else if ((unsigned)operand < m_variablePredictions.size())
- m_variablePredictions[operand].m_value |= prediction;
+ mergePrediction(m_variablePredictions[operand].m_value, makePrediction(prediction, source));
}
- void predictGlobalVar(unsigned varNumber, PredictedType prediction)
+ void predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source)
{
HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVarPredictions.find(varNumber + 1);
if (iter == m_globalVarPredictions.end()) {
PredictionSlot predictionSlot;
- predictionSlot.m_value |= prediction;
+ mergePrediction(predictionSlot.m_value, makePrediction(prediction, source));
m_globalVarPredictions.add(varNumber + 1, predictionSlot);
} else
- iter->second.m_value |= prediction;
+ mergePrediction(iter->second.m_value, makePrediction(prediction, source));
}
- void predict(Node& node, PredictedType prediction)
+ void predict(Node& node, PredictedType prediction, PredictionSource source)
{
switch (node.op) {
case GetLocal:
- predict(node.local(), prediction);
+ predict(node.local(), prediction, source);
break;
case GetGlobalVar:
- predictGlobalVar(node.varNumber(), prediction);
+ predictGlobalVar(node.varNumber(), prediction, source);
break;
+ case GetById:
+ case GetMethod:
+ case GetByVal:
+ case Call:
+ case Construct:
+ node.predict(prediction, source);
default:
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (94448 => 94449)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2011-09-02 21:08:27 UTC (rev 94448)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2011-09-02 21:16:25 UTC (rev 94449)
@@ -195,7 +195,11 @@
static const PredictedType PredictInt32 = 0x04;
static const PredictedType PredictDouble = 0x08;
static const PredictedType PredictNumber = 0x0c;
+static const PredictedType DynamicPredictionTag = 0x80;
+static const PredictedType PredictionTagMask = 0x80;
+enum PredictionSource { StaticPrediction, DynamicPrediction };
+
inline bool isCellPrediction(PredictedType value)
{
return (value & PredictCell) == PredictCell && !(value & ~PredictArray);
@@ -203,17 +207,17 @@
inline bool isArrayPrediction(PredictedType value)
{
- return value == PredictArray;
+ return (value & ~PredictionTagMask) == PredictArray;
}
inline bool isInt32Prediction(PredictedType value)
{
- return value == PredictInt32;
+ return (value & ~PredictionTagMask) == PredictInt32;
}
inline bool isDoublePrediction(PredictedType value)
{
- return value == PredictDouble;
+ return (value & ~PredictionTagMask) == PredictDouble;
}
inline bool isNumberPrediction(PredictedType value)
@@ -221,6 +225,40 @@
return !!(value & PredictNumber) && !(value & ~PredictNumber);
}
+inline bool isDynamicPrediction(PredictedType value)
+{
+ ASSERT(value != (PredictNone | DynamicPredictionTag));
+ return !!(value & DynamicPredictionTag);
+}
+
+inline PredictedType mergePredictions(PredictedType left, PredictedType right)
+{
+ if (isDynamicPrediction(left) == isDynamicPrediction(right))
+ return left | right;
+ if (isDynamicPrediction(left)) {
+ ASSERT(!isDynamicPrediction(right));
+ return left;
+ }
+ ASSERT(!isDynamicPrediction(left));
+ ASSERT(isDynamicPrediction(right));
+ return right;
+}
+
+template<typename T>
+inline void mergePrediction(T& left, PredictedType right)
+{
+ left = static_cast<T>(mergePredictions(static_cast<PredictedType>(left), right));
+}
+
+inline PredictedType makePrediction(PredictedType type, PredictionSource source)
+{
+ ASSERT(!(type & DynamicPredictionTag));
+ ASSERT(source == DynamicPrediction || source == StaticPrediction);
+ if (type == PredictNone)
+ return PredictNone;
+ return type | (source == DynamicPrediction ? DynamicPredictionTag : 0);
+}
+
#ifndef NDEBUG
inline const char* predictionToString(PredictedType value)
{
@@ -432,10 +470,22 @@
return static_cast<PredictedType>(m_opInfo2);
}
- void predict(PredictedType prediction)
+ void predict(PredictedType prediction, PredictionSource source)
{
ASSERT(hasPrediction());
- m_opInfo2 |= prediction;
+
+ // We have previously found empirically that ascribing static predictions
+ // to heap loads as well as calls is not profitable, as these predictions
+ // are wrong too often. Hence, this completely ignores static predictions.
+ if (source == StaticPrediction)
+ return;
+
+ if (prediction == PredictNone)
+ return;
+
+ ASSERT(source == DynamicPrediction);
+
+ m_opInfo2 |= DynamicPredictionTag | prediction;
}
VirtualRegister virtualRegister()