+2011-09-24 Filip Pizlo <fpizlo@apple.com>
+
+ The DFG should not attempt to guess types in the absence of value
+ profiles
+ https://bugs.webkit.org/show_bug.cgi?id=68677
+
+ Reviewed by Oliver Hunt.
+
+ This adds the ForceOSRExit node, which is ignored by the propagator
+ and virtual register allocator (and hence ensuring that liveness analysis
+ works correctly), but forces terminateSpeculativeExecution() in the
+ back-end. This appears to be a slight speed-up on benchmark averages,
+ with ~5% swings on individual benchmarks, in both directions. But it's
+ never a regression on any average, and appears to be a ~1% progression
+ in the SunSpider average.
+
+ This also adds a bit better debugging support in the old JIT and in DFG,
+ as this was necessary to debug the much more frequent OSR transitions
+ that occur with this change.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::addCall):
+ (JSC::DFG::ByteCodeParser::getStrongPrediction):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
+ * dfg/DFGNode.h:
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ (JSC::JIT::privateCompile):
+ * jit/JIT.h:
+
2011-09-24 Geoffrey Garen <ggaren@apple.com>
Some Windows build fixage.
NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
{
+ Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
+
+ PredictedType prediction = PredictNone;
+ if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
+ prediction = getStrongPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
+
addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand;
int registerOffset = currentInstruction[3].u.operand;
int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
addVarArgChild(get(argIdx));
- NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(PredictNone));
- Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
- if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+ NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
+ if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
set(putInstruction[1].u.operand, call);
- stronglyPredict(call, m_currentIndex + OPCODE_LENGTH(op_call));
- }
if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
return call;
PredictedType getStrongPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
UNUSED_PARAM(nodeIndex);
- UNUSED_PARAM(bytecodeIndex);
ValueProfile* profile = m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
ASSERT(profile);
#if ENABLE(DFG_DEBUG_VERBOSE)
printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
#endif
+
+ if (prediction == PredictNone) {
+ // We have no information about what values this node generates. Give up
+ // on executing this code, since we're likely to do more damage than good.
+ addToGraph(ForceOSRExit);
+ }
+
return prediction;
}
- void stronglyPredict(NodeIndex nodeIndex, unsigned bytecodeIndex)
- {
- m_graph[nodeIndex].predict(getStrongPrediction(nodeIndex, bytecodeIndex) & ~PredictionTagMask, StrongPrediction);
- }
-
- void stronglyPredict(NodeIndex nodeIndex)
+ PredictedType getStrongPrediction()
{
- stronglyPredict(nodeIndex, m_currentIndex);
+ return getStrongPrediction(m_graph.size(), m_currentIndex);
}
-
+
NodeIndex makeSafe(NodeIndex nodeIndex)
{
if (!m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
// === Property access operations ===
case op_get_by_val: {
+ PredictedType prediction = getStrongPrediction();
+
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
weaklyPredictArray(base);
weaklyPredictInt32(property);
- NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(PredictNone), base, property);
+ NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property);
set(currentInstruction[1].u.operand, getByVal);
- stronglyPredict(getByVal);
NEXT_OPCODE(op_get_by_val);
}
case op_method_check: {
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
+ PredictedType prediction = getStrongPrediction();
+
ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
NodeIndex base = get(getInstruction[2].u.operand);
methodCheckData.prototype = methodCall.cachedPrototype.get();
m_graph.m_methodCheckData.append(methodCheckData);
} else {
- NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base);
+ NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(prediction), base);
set(getInstruction[1].u.operand, getMethod);
- stronglyPredict(getMethod);
}
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
}
case op_get_scoped_var: {
+ PredictedType prediction = getStrongPrediction();
int dst = currentInstruction[1].u.operand;
int slot = currentInstruction[2].u.operand;
int depth = currentInstruction[3].u.operand;
NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
- NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(PredictNone), getScopeChain);
+ NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
set(dst, getScopedVar);
- stronglyPredict(getScopedVar);
NEXT_OPCODE(op_get_scoped_var);
}
case op_put_scoped_var: {
NEXT_OPCODE(op_put_scoped_var);
}
case op_get_by_id: {
+ PredictedType prediction = getStrongPrediction();
+
NodeIndex base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = currentInstruction[3].u.operand;
size_t offset = structure->get(*m_globalData, identifier);
if (offset != notFound) {
- getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(PredictNone), addToGraph(CheckStructure, OpInfo(structure), base));
+ getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(CheckStructure, OpInfo(structure), base));
StorageAccessData storageAccessData;
storageAccessData.offset = offset;
}
if (getById == NoNode)
- getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(PredictNone), base);
+ getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base);
set(currentInstruction[1].u.operand, getById);
- stronglyPredict(getById);
NEXT_OPCODE(op_get_by_id);
}
}
case op_get_global_var: {
+ PredictedType prediction = getStrongPrediction();
+
NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
set(currentInstruction[1].u.operand, getGlobalVar);
- m_graph.predictGlobalVar(currentInstruction[2].u.operand, getStrongPrediction(getGlobalVar, m_currentIndex) & ~PredictionTagMask, StrongPrediction);
+ m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction & ~PredictionTagMask, StrongPrediction);
NEXT_OPCODE(op_get_global_var);
}
NEXT_OPCODE(op_call_put_result);
case op_resolve: {
+ PredictedType prediction = getStrongPrediction();
+
unsigned identifier = currentInstruction[2].u.operand;
- NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(PredictNone));
+ NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(prediction));
set(currentInstruction[1].u.operand, resolve);
- stronglyPredict(resolve);
NEXT_OPCODE(op_resolve);
}
case op_resolve_base: {
+ PredictedType prediction = getStrongPrediction();
+
unsigned identifier = currentInstruction[2].u.operand;
- NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(PredictNone));
+ NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(prediction));
set(currentInstruction[1].u.operand, resolve);
- stronglyPredict(resolve);
NEXT_OPCODE(op_resolve_base);
}
case op_resolve_global: {
- NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(PredictNone));
+ PredictedType prediction = getStrongPrediction();
+
+ NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
m_graph.m_resolveGlobalData.append(ResolveGlobalData());
ResolveGlobalData& data = m_graph.m_resolveGlobalData.last();
data.identifierNumber = currentInstruction[2].u.operand;
data.resolveInfoIndex = m_globalResolveNumber++;
set(currentInstruction[1].u.operand, resolve);
- stronglyPredict(resolve);
NEXT_OPCODE(op_resolve_global);
}