Modified: trunk/Source/_javascript_Core/ChangeLog (91893 => 91894)
--- trunk/Source/_javascript_Core/ChangeLog 2011-07-28 03:00:54 UTC (rev 91893)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-07-28 03:25:19 UTC (rev 91894)
@@ -1,3 +1,36 @@
+2011-07-27 Filip Pizlo <fpi...@apple.com>
+
+ DFG graph has no notion of double prediction.
+ https://bugs.webkit.org/show_bug.cgi?id=65234
+
+ Reviewed by Gavin Barraclough.
+
+ Added the notion of PredictDouble, and PredictNumber, which is the least
+ upper bound of PredictInt32 and PredictDouble. Least upper bound is
+ defined as the bitwise-or of two predictions. Bottom is defined as 0,
+ and Top is defined as all bits being set. Added the ability to explicitly
+ distinguish between a node having had a prediction associated with it,
+ and that prediction still being valid (i.e. no conflicting predictions
+ have also been added). Used this to guard the speculative JIT from
+ speculating Int32 in cases where the graph knows that the value is
+ double, which currently only happens for GetLocal nodes on arguments
+ which were double at compile-time.
+
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::predictArgumentTypes):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::isCellPrediction):
+ (JSC::DFG::isArrayPrediction):
+ (JSC::DFG::isInt32Prediction):
+ (JSC::DFG::isDoublePrediction):
+ (JSC::DFG::isNumberPrediction):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+ (JSC::DFG::SpeculativeJIT::initializeVariableTypes):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::isRegisterDataFormatDouble):
+
2011-07-27 Gavin Barraclough <barraclo...@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=65294
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (91893 => 91894)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2011-07-28 03:00:54 UTC (rev 91893)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2011-07-28 03:25:19 UTC (rev 91894)
@@ -181,8 +181,11 @@
size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_argumentPredictions.size());
for (size_t arg = 1; arg < numberOfArguments; ++arg) {
- if (exec->argument(arg - 1).isInt32())
+ JSValue argumentValue = exec->argument(arg - 1);
+ if (argumentValue.isInt32())
m_argumentPredictions[arg].m_value |= PredictInt32;
+ else if (argumentValue.isDouble())
+ m_argumentPredictions[arg].m_value |= PredictDouble;
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (91893 => 91894)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2011-07-28 03:00:54 UTC (rev 91893)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2011-07-28 03:25:19 UTC (rev 91894)
@@ -44,11 +44,38 @@
inline bool operandIsArgument(int operand) { return operand < 0; }
typedef uint8_t PredictedType;
-static const PredictedType PredictNone = 0;
-static const PredictedType PredictCell = 0x01;
-static const PredictedType PredictArray = 0x03;
-static const PredictedType PredictInt32 = 0x04;
+static const PredictedType PredictNone = 0;
+static const PredictedType PredictCell = 0x01;
+static const PredictedType PredictArray = 0x03;
+static const PredictedType PredictInt32 = 0x04;
+static const PredictedType PredictDouble = 0x08;
+static const PredictedType PredictNumber = 0x0c;
+inline bool isCellPrediction(PredictedType value)
+{
+ return (value & PredictCell) == PredictCell && !(value & ~PredictArray);
+}
+
+inline bool isArrayPrediction(PredictedType value)
+{
+ return value == PredictArray;
+}
+
+inline bool isInt32Prediction(PredictedType value)
+{
+ return value == PredictInt32;
+}
+
+inline bool isDoublePrediction(PredictedType value)
+{
+ return value == PredictDouble;
+}
+
+inline bool isNumberPrediction(PredictedType value)
+{
+ return !!(value & PredictNumber) && !(value & ~PredictNumber);
+}
+
struct PredictionSlot {
public:
PredictionSlot()
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (91893 => 91894)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-07-28 03:00:54 UTC (rev 91893)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2011-07-28 03:25:19 UTC (rev 91894)
@@ -537,7 +537,7 @@
case GetLocal: {
GPRTemporary result(this);
PredictedType prediction = m_jit.graph().getPrediction(node.local());
- if (prediction == PredictInt32) {
+ if (isInt32Prediction(prediction)) {
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
// Like integerResult, but don't useChildren - our children are phi nodes,
@@ -552,35 +552,28 @@
// and don't represent values within this dataflow with virtual registers.
VirtualRegister virtualRegister = node.virtualRegister();
m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
- m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), (prediction == PredictArray) ? DataFormatJSCell : DataFormatJS);
+ m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), isArrayPrediction(prediction) ? DataFormatJSCell : DataFormatJS);
}
break;
}
case SetLocal: {
- switch (m_jit.graph().getPrediction(node.local())) {
- case PredictInt32: {
+ PredictedType predictedType = m_jit.graph().getPrediction(node.local());
+ if (isInt32Prediction(predictedType)) {
SpeculateIntegerOperand value(this, node.child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
- break;
- }
- case PredictArray: {
+ } else if (isArrayPrediction(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- break;
- }
-
- default: {
+ } else {
JSValueOperand value(this, node.child1());
m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
- break;
}
- }
break;
}
@@ -918,7 +911,7 @@
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
Node& baseNode = m_jit.graph()[node.child1()];
- if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
+ if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
@@ -953,7 +946,7 @@
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
Node& baseNode = m_jit.graph()[node.child1()];
- if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
+ if (baseNode.op != GetLocal || isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
base.use();
@@ -1305,22 +1298,15 @@
ASSERT(!m_compileIndex);
for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
- switch (m_jit.graph().getPrediction(virtualRegister)) {
- case PredictInt32:
+ PredictedType predictedType = m_jit.graph().getPrediction(virtualRegister);
+ if (isInt32Prediction(predictedType))
speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
- break;
-
- case PredictArray: {
+ else if (isArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
- break;
}
-
- default:
- break;
- }
}
}
@@ -1332,7 +1318,7 @@
{
ASSERT(!m_compileIndex);
for (int var = 0; var < m_jit.codeBlock()->m_numVars; ++var) {
- if (m_jit.graph().getPrediction(var) == PredictInt32)
+ if (isInt32Prediction(m_jit.graph().getPrediction(var)))
m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (91893 => 91894)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-07-28 03:00:54 UTC (rev 91893)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2011-07-28 03:25:19 UTC (rev 91894)
@@ -162,7 +162,14 @@
VirtualRegister virtualRegister = node.virtualRegister();
GenerationInfo& info = m_generationInfo[virtualRegister];
- return (info.registerFormat() | DataFormatJS) == DataFormatJSDouble;
+ if ((info.registerFormat() | DataFormatJS) == DataFormatJSDouble
+ || (info.spillFormat() | DataFormatJS) == DataFormatJSDouble)
+ return true;
+
+ if (node.op == GetLocal && isDoublePrediction(m_jit.graph().getPrediction(node.local())))
+ return true;
+
+ return false;
}
bool shouldSpeculateInteger(NodeIndex op1, NodeIndex op2)