2011-09-25 Filip Pizlo <fpizlo@apple.com>
+ DFG static prediction code is no longer needed and should be removed
+ https://bugs.webkit.org/show_bug.cgi?id=68784
+
+ Reviewed by Oliver Hunt.
+
+ This gets rid of static prediction code, and ensures that we do not
+ try to compile code where dynamic predictions are not available.
+ This is accomplished by immediately performing an OSR exit wherever
+ a value is retrieved for which no predictions exist.
+
+ This also adds value profiling for this on functions used for calls.
+
+ The heuristics for deciding when to optimize code are also tweaked,
+ since it is now profitable to optimize sooner. This may need to be
+ tweaked further, but this patch only makes minimal changes.
+
+ This results in a 16% speed-up on Kraken/ai-astar, leading to a 3%
+ overall win on Kraken. It's neutral elsewhere.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::shouldOptimizeNow):
+ (JSC::CodeBlock::dumpValueProfiles):
+ * bytecode/CodeBlock.h:
+ * bytecode/PredictedType.cpp:
+ (JSC::predictionToString):
+ * bytecode/PredictedType.h:
+ (JSC::isCellPrediction):
+ (JSC::isObjectPrediction):
+ (JSC::isFinalObjectPrediction):
+ (JSC::isStringPrediction):
+ (JSC::isArrayPrediction):
+ (JSC::isInt32Prediction):
+ (JSC::isDoublePrediction):
+ (JSC::isNumberPrediction):
+ (JSC::isBooleanPrediction):
+ (JSC::mergePredictions):
+ * bytecode/PredictionTracker.h:
+ (JSC::PredictionTracker::predictArgument):
+ (JSC::PredictionTracker::predict):
+ (JSC::PredictionTracker::predictGlobalVar):
+ * bytecode/ValueProfile.cpp:
+ (JSC::ValueProfile::computeUpdatedPrediction):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::set):
+ (JSC::DFG::ByteCodeParser::addCall):
+ (JSC::DFG::ByteCodeParser::getPrediction):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::predictArgumentTypes):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::predict):
+ (JSC::DFG::Graph::predictGlobalVar):
+ (JSC::DFG::Graph::getMethodCheckPrediction):
+ (JSC::DFG::Graph::getJSConstantPrediction):
+ (JSC::DFG::Graph::getPrediction):
+ * dfg/DFGJITCodeGenerator.cpp:
+ (JSC::DFG::JITCodeGenerator::writeBarrier):
+ (JSC::DFG::JITCodeGenerator::emitBranch):
+ * dfg/DFGJITCompiler.h:
+ (JSC::DFG::JITCompiler::getPrediction):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::valueOfJSConstantNode):
+ (JSC::DFG::Node::isInt32Constant):
+ (JSC::DFG::Node::isDoubleConstant):
+ (JSC::DFG::Node::isNumberConstant):
+ (JSC::DFG::Node::isBooleanConstant):
+ (JSC::DFG::Node::predict):
+ * dfg/DFGPropagator.cpp:
+ (JSC::DFG::Propagator::Propagator):
+ (JSC::DFG::Propagator::propagateNodePredictions):
+ (JSC::DFG::Propagator::fixupNode):
+ (JSC::DFG::Propagator::isPredictedNumerical):
+ (JSC::DFG::Propagator::logicalNotIsPure):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateInteger):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateDouble):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateNumber):
+ (JSC::DFG::SpeculativeJIT::shouldNotSpeculateInteger):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateFinalObject):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateArray):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateObject):
+ (JSC::DFG::SpeculativeJIT::shouldSpeculateCell):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompile):
+
+2011-09-25 Filip Pizlo <fpizlo@apple.com>
+
DFG JIT Construct opcode takes a this argument even though it's
not passed
https://bugs.webkit.org/show_bug.cgi?id=68782
#endif
if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75)
- && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5))
+ && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.25))
return true;
m_optimizationDelayCounter++;
ValueProfile* profile = valueProfile(i);
if (profile->m_bytecodeOffset < 0) {
ASSERT(profile->m_bytecodeOffset == -1);
- fprintf(stderr, " arg = %u: ", i + 1);
+ fprintf(stderr, " arg = %u: ", i);
} else
fprintf(stderr, " bc = %d: ", profile->m_bytecodeOffset);
if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
}
ValueProfile* valueProfileForArgument(int argumentIndex)
{
- int index = argumentIndex - 1;
+ int index = argumentIndex;
if (static_cast<unsigned>(index) >= m_valueProfiles.size())
return 0;
- ValueProfile* result = valueProfile(argumentIndex - 1);
+ ValueProfile* result = valueProfile(argumentIndex);
if (result->m_bytecodeOffset != -1)
return 0;
return result;
#ifndef NDEBUG
const char* predictionToString(PredictedType value)
{
+ if (value == PredictNone)
+ return "None";
+
static const int size = 96;
static char description[size];
BoundsCheckedPointer<char> ptr(description, size);
- if (!(value & StrongPredictionTag))
- ptr.strcat("Weak");
-
if (value & PredictObjectUnknown) {
ASSERT(!(value & (PredictObjectMask & ~PredictObjectUnknown)));
ptr.strcat("Object");
static const PredictedType PredictBoolean = 0x0400; // It's definitely a Boolean.
static const PredictedType PredictOther = 0x4000; // It's definitely none of the above.
static const PredictedType PredictTop = 0x7fff; // It can be any of the above.
-static const PredictedType StrongPredictionTag = 0x8000; // It's a strong prediction (all strong predictions trump all weak ones).
-static const PredictedType PredictionTagMask = 0x8000;
-
-enum PredictionSource { WeakPrediction, StrongPrediction };
inline bool isCellPrediction(PredictedType value)
{
- return !!(value & PredictCell) && !(value & ~(PredictCell | PredictionTagMask));
+ return !!(value & PredictCell) && !(value & ~PredictCell);
}
inline bool isObjectPrediction(PredictedType value)
{
- return !!(value & PredictObjectMask) && !(value & ~(PredictObjectMask | PredictionTagMask));
+ return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask);
}
inline bool isFinalObjectPrediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictFinalObject;
+ return value == PredictFinalObject;
}
inline bool isStringPrediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictString;
+ return value == PredictString;
}
inline bool isArrayPrediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictArray;
+ return value == PredictArray;
}
inline bool isInt32Prediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictInt32;
+ return value == PredictInt32;
}
inline bool isDoublePrediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictDouble;
+ return value == PredictDouble;
}
inline bool isNumberPrediction(PredictedType value)
{
- return !!(value & PredictNumber) && !(value & ~(PredictNumber | PredictionTagMask));
+ return !!(value & PredictNumber) && !(value & ~PredictNumber);
}
inline bool isBooleanPrediction(PredictedType value)
{
- return (value & ~PredictionTagMask) == PredictBoolean;
-}
-
-inline bool isStrongPrediction(PredictedType value)
-{
- ASSERT(value != (PredictNone | StrongPredictionTag));
- return !!(value & StrongPredictionTag);
+ return value == PredictBoolean;
}
#ifndef NDEBUG
inline PredictedType mergePredictions(PredictedType left, PredictedType right)
{
- if (isStrongPrediction(left) == isStrongPrediction(right)) {
- if (left & PredictObjectUnknown) {
- ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
- if (right & PredictObjectMask)
- return (left & ~PredictObjectUnknown) | right;
- } else if (right & PredictObjectUnknown) {
- ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
- if (left & PredictObjectMask)
- return (right & ~PredictObjectUnknown) | left;
- }
- return left | right;
+ if (left & PredictObjectUnknown) {
+ ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
+ if (right & PredictObjectMask)
+ return (left & ~PredictObjectUnknown) | right;
+ } else if (right & PredictObjectUnknown) {
+ ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
+ if (left & PredictObjectMask)
+ return (right & ~PredictObjectUnknown) | left;
}
- if (isStrongPrediction(left)) {
- ASSERT(!isStrongPrediction(right));
- return left;
- }
- ASSERT(!isStrongPrediction(left));
- ASSERT(isStrongPrediction(right));
- return right;
+ return left | right;
}
template<typename T>
return result;
}
-inline PredictedType makePrediction(PredictedType type, PredictionSource source)
-{
- ASSERT(!(type & StrongPredictionTag));
- ASSERT(source == StrongPrediction || source == WeakPrediction);
- if (type == PredictNone)
- return PredictNone;
- return type | (source == StrongPrediction ? StrongPredictionTag : 0);
-}
-
PredictedType predictionFromClassInfo(const ClassInfo*);
PredictedType predictionFromStructure(Structure*);
PredictedType predictionFromCell(JSCell*);
unsigned argumentIndexForOperand(int operand) const { return operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize; }
- bool predictArgument(unsigned argument, PredictedType prediction, PredictionSource source)
+ bool predictArgument(unsigned argument, PredictedType prediction)
{
- return mergePrediction(m_arguments[argument].m_value, makePrediction(prediction, source));
+ return mergePrediction(m_arguments[argument].m_value, prediction);
}
- bool predict(int operand, PredictedType prediction, PredictionSource source)
+ bool predict(int operand, PredictedType prediction)
{
if (operandIsArgument(operand))
- return predictArgument(argumentIndexForOperand(operand), prediction, source);
+ return predictArgument(argumentIndexForOperand(operand), prediction);
if ((unsigned)operand >= m_variables.size()) {
ASSERT(operand >= 0);
m_variables.resize(operand + 1);
}
- return mergePrediction(m_variables[operand].m_value, makePrediction(prediction, source));
+ return mergePrediction(m_variables[operand].m_value, prediction);
}
- bool predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source)
+ bool predictGlobalVar(unsigned varNumber, PredictedType prediction)
{
HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVars.find(varNumber + 1);
if (iter == m_globalVars.end()) {
PredictionSlot predictionSlot;
- bool result = mergePrediction(predictionSlot.m_value, makePrediction(prediction, source));
+ bool result = mergePrediction(predictionSlot.m_value, prediction);
m_globalVars.add(varNumber + 1, predictionSlot);
return result;
}
- return mergePrediction(iter->second.m_value, makePrediction(prediction, source));
+ return mergePrediction(iter->second.m_value, prediction);
}
PredictedType getArgumentPrediction(unsigned argument)
if (!statistics.samples)
prediction = PredictNone;
else if (statistics.int32s == statistics.samples)
- prediction = StrongPredictionTag | PredictInt32;
+ prediction = PredictInt32;
else if (statistics.doubles == statistics.samples)
- prediction = StrongPredictionTag | PredictDouble;
+ prediction = PredictDouble;
else if (statistics.int32s + statistics.doubles == statistics.samples)
- prediction = StrongPredictionTag | PredictNumber;
+ prediction = PredictNumber;
else if (statistics.arrays == statistics.samples)
- prediction = StrongPredictionTag | PredictArray;
+ prediction = PredictArray;
else if (statistics.finalObjects == statistics.samples)
- prediction = StrongPredictionTag | PredictFinalObject;
+ prediction = PredictFinalObject;
else if (statistics.strings == statistics.samples)
- prediction = StrongPredictionTag | PredictString;
+ prediction = PredictString;
else if (statistics.objects == statistics.samples)
- prediction = StrongPredictionTag | PredictObjectOther;
+ prediction = PredictObjectOther;
else if (statistics.cells == statistics.samples)
- prediction = StrongPredictionTag | PredictCellOther;
+ prediction = PredictCellOther;
else if (statistics.booleans == statistics.samples)
- prediction = StrongPredictionTag | PredictBoolean;
+ prediction = PredictBoolean;
else
- prediction = StrongPredictionTag | PredictOther;
+ prediction = PredictOther;
m_numberOfSamplesInPrediction += statistics.samples;
mergePrediction(m_prediction, prediction);
// Must be a local.
return getLocal((unsigned)operand);
}
- void set(int operand, NodeIndex value, PredictedType weakPrediction = PredictNone)
+ void set(int operand, NodeIndex value)
{
- m_graph.predict(operand, weakPrediction, WeakPrediction);
-
// Is this an argument?
if (operandIsArgument(operand)) {
setArgument(operand, value);
PredictedType prediction = PredictNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
- prediction = getStrongPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
+ prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand;
return call;
}
- void weaklyPredictArray(NodeIndex nodeIndex)
- {
- m_graph.predict(m_graph[nodeIndex], PredictArray, WeakPrediction);
- }
-
- void weaklyPredictInt32(NodeIndex nodeIndex)
- {
- ASSERT(m_reusableNodeStack.isEmpty());
- m_reusableNodeStack.append(&m_graph[nodeIndex]);
-
- do {
- Node* nodePtr = m_reusableNodeStack.last();
- m_reusableNodeStack.removeLast();
-
- if (nodePtr->op == ValueToNumber)
- nodePtr = &m_graph[nodePtr->child1()];
-
- if (nodePtr->op == ValueToInt32)
- nodePtr = &m_graph[nodePtr->child1()];
-
- switch (nodePtr->op) {
- case ArithAdd:
- case ArithSub:
- case ArithMul:
- case ValueAdd:
- m_reusableNodeStack.append(&m_graph[nodePtr->child1()]);
- m_reusableNodeStack.append(&m_graph[nodePtr->child2()]);
- break;
- default:
- m_graph.predict(*nodePtr, PredictInt32, WeakPrediction);
- break;
- }
- } while (!m_reusableNodeStack.isEmpty());
- }
-
- PredictedType getStrongPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
+ PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
UNUSED_PARAM(nodeIndex);
return prediction;
}
- PredictedType getStrongPrediction()
+ PredictedType getPrediction()
{
- return getStrongPrediction(m_graph.size(), m_currentIndex);
+ return getPrediction(m_graph.size(), m_currentIndex);
}
NodeIndex makeSafe(NodeIndex nodeIndex)
case op_bitand: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
- set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2), PredictInt32);
+ set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
NEXT_OPCODE(op_bitand);
}
case op_bitor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
- set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2), PredictInt32);
+ set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
NEXT_OPCODE(op_bitor);
}
case op_bitxor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
- set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2), PredictInt32);
+ set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
NEXT_OPCODE(op_bitxor);
}
case op_rshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
result = op1;
else
result = addToGraph(BitRShift, op1, op2);
- set(currentInstruction[1].u.operand, result, PredictInt32);
+ set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_rshift);
}
case op_lshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
result = op1;
else
result = addToGraph(BitLShift, op1, op2);
- set(currentInstruction[1].u.operand, result, PredictInt32);
+ set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_lshift);
}
case op_urshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
- weaklyPredictInt32(op1);
- weaklyPredictInt32(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,
result = addToGraph(BitURShift, op1, op2);
result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result));
}
- set(currentInstruction[1].u.operand, result, PredictInt32);
+ set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_urshift);
}
case op_pre_inc: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
- weaklyPredictInt32(op);
set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_pre_inc);
}
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
- weaklyPredictInt32(op);
set(result, op);
set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_post_inc);
case op_pre_dec: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
- weaklyPredictInt32(op);
set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_pre_dec);
}
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
- weaklyPredictInt32(op);
set(result, op);
set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_post_dec);
case op_add: {
NodeIndex op1 = get(currentInstruction[2].u.operand);
NodeIndex op2 = get(currentInstruction[3].u.operand);
- // 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)) {
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
- }
-
if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2))));
else
case op_sub: {
NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
- if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
- weaklyPredictInt32(op1);
- weaklyPredictInt32(op2);
- }
-
set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2)));
NEXT_OPCODE(op_sub);
}
// === Property access operations ===
case op_get_by_val: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
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(prediction), base, property);
set(currentInstruction[1].u.operand, getByVal);
NodeIndex base = get(currentInstruction[1].u.operand);
NodeIndex property = get(currentInstruction[2].u.operand);
NodeIndex value = get(currentInstruction[3].u.operand);
- weaklyPredictArray(base);
- weaklyPredictInt32(property);
addToGraph(PutByVal, base, property, value);
case op_method_check: {
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
continue;
}
case op_get_scoped_var: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
int dst = currentInstruction[1].u.operand;
int slot = currentInstruction[2].u.operand;
int depth = currentInstruction[3].u.operand;
NEXT_OPCODE(op_put_scoped_var);
}
case op_get_by_id: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
NodeIndex base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = currentInstruction[3].u.operand;
}
case op_get_global_var: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
set(currentInstruction[1].u.operand, getGlobalVar);
- m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction & ~PredictionTagMask, StrongPrediction);
+ m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction);
NEXT_OPCODE(op_get_global_var);
}
NEXT_OPCODE(op_call_put_result);
case op_resolve: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
unsigned identifier = currentInstruction[2].u.operand;
}
case op_resolve_base: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
unsigned identifier = currentInstruction[2].u.operand;
}
case op_resolve_global: {
- PredictedType prediction = getStrongPrediction();
+ PredictedType prediction = getPrediction();
NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
m_graph.m_resolveGlobalData.append(ResolveGlobalData());
if (exec) {
size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_predictions.numberOfArguments());
- for (size_t arg = 1; arg < numberOfArguments; ++arg) {
- JSValue argumentValue = exec->argument(arg - 1);
- if (argumentValue.isInt32())
- m_predictions.predictArgument(arg, PredictInt32, WeakPrediction);
- else if (argumentValue.isDouble())
- m_predictions.predictArgument(arg, PredictDouble, WeakPrediction);
- }
+ for (size_t arg = 1; arg < numberOfArguments; ++arg)
+ m_predictions.predictArgument(arg, predictionFromValue(exec->argument(arg - 1)));
}
ASSERT(codeBlock);
CodeBlock* profiledCodeBlock = codeBlock->alternative();
ASSERT(codeBlock->m_numParameters >= 1);
- for (size_t arg = 1; arg < static_cast<size_t>(codeBlock->m_numParameters); ++arg) {
+ for (size_t arg = 0; arg < static_cast<size_t>(codeBlock->m_numParameters); ++arg) {
ValueProfile* profile = profiledCodeBlock->valueProfileForArgument(arg);
if (!profile)
continue;
- m_predictions.predictArgument(arg, profile->computeUpdatedPrediction() & ~PredictionTagMask, StrongPrediction);
+ m_predictions.predictArgument(arg, profile->computeUpdatedPrediction());
#if ENABLE(DFG_DEBUG_VERBOSE)
printf("Argument [%lu] prediction: %s\n", arg, predictionToString(m_predictions.getArgumentPrediction(arg)));
return m_predictions;
}
- bool predict(int operand, PredictedType prediction, PredictionSource source)
+ bool predict(int operand, PredictedType prediction)
{
- return m_predictions.predict(operand, prediction, source);
+ return m_predictions.predict(operand, prediction);
}
- bool predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source)
+ bool predictGlobalVar(unsigned varNumber, PredictedType prediction)
{
- return m_predictions.predictGlobalVar(varNumber, prediction, source);
+ return m_predictions.predictGlobalVar(varNumber, prediction);
}
- bool predict(Node& node, PredictedType prediction, PredictionSource source)
+ bool predict(Node& node, PredictedType prediction)
{
switch (node.op) {
case GetLocal:
- return predict(node.local(), prediction, source);
+ return predict(node.local(), prediction);
break;
case GetGlobalVar:
- return predictGlobalVar(node.varNumber(), prediction, source);
+ return predictGlobalVar(node.varNumber(), prediction);
break;
case GetById:
case GetMethod:
case ResolveBase:
case ResolveBaseStrictPut:
case ResolveGlobal:
- return node.predict(prediction, source);
+ return node.predict(prediction);
default:
return false;
}
PredictedType getMethodCheckPrediction(Node& node)
{
- return makePrediction(predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function), StrongPrediction);
+ return predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function);
}
- PredictedType getPrediction(Node& node)
+ PredictedType getJSConstantPrediction(Node& node, CodeBlock* codeBlock)
+ {
+ return predictionFromValue(node.valueOfJSConstantNode(codeBlock));
+ }
+
+ PredictedType getPrediction(Node& node, CodeBlock* codeBlock)
{
Node* nodePtr = &node;
return nodePtr->getPrediction();
case CheckMethod:
return getMethodCheckPrediction(*nodePtr);
+ case JSConstant:
+ return getJSConstantPrediction(*nodePtr, codeBlock);
default:
return PredictNone;
}
#if ENABLE(GGC)
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) {
+ if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
}
#if ENABLE(GGC)
JITCompiler::Jump rhsNotCell;
bool hadCellCheck = false;
- if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.graph().getPrediction(m_jit.graph()[valueIndex]))) {
+ if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {
hadCellCheck = true;
rhsNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
}
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- bool predictBoolean = isBooleanPrediction(m_jit.graph().getPrediction(m_jit.graph()[node.child1()]));
+ bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
if (predictBoolean) {
addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
double valueOfNumberConstant(NodeIndex nodeIndex) { return graph().valueOfNumberConstant(codeBlock(), nodeIndex); }
bool valueOfBooleanConstant(NodeIndex nodeIndex) { return graph().valueOfBooleanConstant(codeBlock(), nodeIndex); }
JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex) { return graph().valueOfFunctionConstant(codeBlock(), nodeIndex); }
+
+ // Helper methods to get predictions
+ PredictedType getPrediction(Node& node) { return graph().getPrediction(node, codeBlock()); }
+ PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); }
#if USE(JSVALUE32_64)
void* addressOfDoubleConstant(NodeIndex nodeIndex)
return m_opInfo;
}
+ // NOTE: this only works for JSConstant nodes.
+ JSValue valueOfJSConstantNode(CodeBlock* codeBlock)
+ {
+ return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
+ }
+
bool isInt32Constant(CodeBlock* codeBlock)
{
- return isConstant() && valueOfJSConstant(codeBlock).isInt32();
+ return isConstant() && valueOfJSConstantNode(codeBlock).isInt32();
}
bool isDoubleConstant(CodeBlock* codeBlock)
{
- bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
+ bool result = isConstant() && valueOfJSConstantNode(codeBlock).isDouble();
if (result)
ASSERT(!isInt32Constant(codeBlock));
return result;
bool isNumberConstant(CodeBlock* codeBlock)
{
- bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
+ bool result = isConstant() && valueOfJSConstantNode(codeBlock).isNumber();
ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
return result;
}
bool isBooleanConstant(CodeBlock* codeBlock)
{
- return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
+ return isConstant() && valueOfJSConstantNode(codeBlock).isBoolean();
}
bool hasLocal()
return static_cast<PredictedType>(m_opInfo2);
}
- bool predict(PredictedType prediction, PredictionSource source)
+ bool predict(PredictedType prediction)
{
ASSERT(hasPrediction());
- // 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 == WeakPrediction)
- return false;
-
- if (prediction == PredictNone)
- return false;
-
- ASSERT(source == StrongPrediction);
-
- return mergePrediction(m_opInfo2, makePrediction(prediction, source));
+ return mergePrediction(m_opInfo2, prediction);
}
bool hasMethodCheckData()
} children;
private:
- // This is private because it only works for the JSConstant op. The DFG is written under the
- // assumption that "valueOfJSConstant" can correctly return a constant for any DFG node for
- // which hasConstant() is true.
- JSValue valueOfJSConstant(CodeBlock* codeBlock)
- {
- return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
- }
-
// The virtual register number (spill location) associated with this .
VirtualRegister m_virtualRegister;
// The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
// speculation that does not contravene the expected values.
m_predictions.resize(m_graph.size());
- // Uses is a backward flow property that propagates the hard expectations at
- // certain uses to their value sources, ensuring that predictions about
- // values do not contravene the code itself. This comes up only in the
- // cases of obvious cell uses, like GetById and friends as well as Call.
- // We're essentially statically speculating that if the value profile indicates
- // that only booleans (for example) flow into a GetById, then the value
- // profile is simply wrong due to insufficient coverage and needs to be
- // adjusted accordingly. The alternatives would be to assume either
- // that the GetById never executes, or always executes on a boolean leading
- // to whatever bizarre behavior that's supposed to cause.
- m_uses.resize(m_graph.size());
- m_variableUses.initializeSimilarTo(m_graph.predictions());
-
// Replacements are used to implement local common subexpression elimination.
m_replacements.resize(m_graph.size());
for (unsigned i = 0; i < m_graph.size(); ++i) {
m_predictions[i] = PredictNone;
- m_uses[i] = PredictNone;
m_replacements[i] = NoNode;
}
return true;
}
- bool mergeUse(NodeIndex nodeIndex, PredictedType prediction)
- {
- ASSERT(m_graph[nodeIndex].hasResult());
-
- return JSC::mergePrediction(m_uses[nodeIndex], prediction);
- }
-
bool mergePrediction(PredictedType prediction)
{
ASSERT(m_graph[m_compileIndex].hasResult());
switch (op) {
case JSConstant: {
- changed |= setPrediction(makePrediction(predictionFromValue(m_graph.valueOfJSConstant(m_codeBlock, m_compileIndex)), StrongPrediction));
+ changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_codeBlock, m_compileIndex)));
break;
}
case GetLocal: {
- changed |= m_graph.predict(node.local(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
- changed |= m_variableUses.predict(node.local(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
-
PredictedType prediction = m_graph.getPrediction(node.local());
- if (isStrongPrediction(prediction))
+ if (prediction)
changed |= mergePrediction(prediction);
break;
}
case SetLocal: {
- changed |= m_graph.predict(node.local(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction);
- changed |= mergeUse(node.child1(), m_variableUses.getPrediction(node.local()));
+ changed |= m_graph.predict(node.local(), m_predictions[node.child1()]);
break;
}
case BitLShift:
case BitURShift:
case ValueToInt32: {
- changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= setPrediction(PredictInt32);
break;
}
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- if (isStrongPrediction(left) && isStrongPrediction(right)) {
+ if (left && right) {
if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= mergePrediction(PredictInt32);
else
- changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction));
+ changed |= mergePrediction(PredictDouble);
}
break;
}
case UInt32ToNumber: {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= setPrediction(PredictInt32);
else
- changed |= setPrediction(makePrediction(PredictNumber, StrongPrediction));
+ changed |= setPrediction(PredictNumber);
break;
}
case ValueToNumber: {
PredictedType prediction = m_predictions[node.child1()];
- if (isStrongPrediction(prediction)) {
+ if (prediction) {
if (!(prediction & PredictDouble) && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= mergePrediction(PredictInt32);
else
- changed |= mergePrediction(makePrediction(PredictNumber, StrongPrediction));
+ changed |= mergePrediction(PredictNumber);
}
break;
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- if (isStrongPrediction(left) && isStrongPrediction(right)) {
+ if (left && right) {
if (isNumberPrediction(left) && isNumberPrediction(right)) {
if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= mergePrediction(PredictInt32);
else
- changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction));
+ changed |= mergePrediction(PredictDouble);
} else if (!(left & PredictNumber) || !(right & PredictNumber)) {
// left or right is definitely something other than a number.
- changed |= mergePrediction(makePrediction(PredictString, StrongPrediction));
+ changed |= mergePrediction(PredictString);
} else
- changed |= mergePrediction(makePrediction(PredictString | PredictInt32 | PredictDouble, StrongPrediction));
+ changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
}
break;
}
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- if (isStrongPrediction(left) && isStrongPrediction(right)) {
+ if (left && right) {
if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
- changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction));
+ changed |= mergePrediction(PredictInt32);
else
- changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction));
+ changed |= mergePrediction(PredictDouble);
}
break;
}
case ArithSqrt: {
- changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
+ changed |= setPrediction(PredictDouble);
break;
}
case ArithAbs: {
PredictedType child = m_predictions[node.child1()];
- if (isStrongPrediction(child)) {
+ if (child) {
if (nodeCanSpeculateInteger(node.arithNodeFlags()))
changed |= mergePrediction(child);
else
- changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
+ changed |= setPrediction(PredictDouble);
}
break;
}
case CompareEq:
case CompareStrictEq:
case InstanceOf: {
- changed |= setPrediction(makePrediction(PredictBoolean, StrongPrediction));
+ changed |= setPrediction(PredictBoolean);
break;
}
case GetById:
case GetMethod:
case GetByVal: {
- changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
- changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
- if (isStrongPrediction(node.getPrediction()))
+ if (node.getPrediction())
changed |= mergePrediction(node.getPrediction());
break;
}
case CheckStructure: {
- // We backward propagate what this CheckStructure tells us. Maybe that's the right way
- // to go; maybe it isn't. I'm not sure. What we'd really want is flow-sensitive
- // forward propagation of what we learn from having executed CheckStructure. But for
- // now we preserve the flow-insensitive nature of this analysis, because it's cheap to
- // run and seems to work well enough.
- changed |= mergeUse(node.child1(), predictionFromStructure(node.structure()) | StrongPredictionTag);
- changed |= setPrediction(PredictOther | StrongPredictionTag);
+ changed |= setPrediction(PredictOther);
break;
}
case GetByOffset: {
- changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
- if (isStrongPrediction(node.getPrediction()))
+ if (node.getPrediction())
changed |= mergePrediction(node.getPrediction());
break;
}
case CheckMethod: {
- changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
changed |= setPrediction(m_graph.getMethodCheckPrediction(node));
break;
}
case Call:
case Construct: {
- changed |= mergeUse(m_graph.m_varArgChildren[node.firstChild()], PredictObjectUnknown | StrongPredictionTag);
- changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
- if (isStrongPrediction(node.getPrediction()))
+ if (node.getPrediction())
changed |= mergePrediction(node.getPrediction());
break;
}
case ConvertThis: {
- changed |= setPrediction(makePrediction(PredictObjectUnknown, StrongPrediction));
+ changed |= setPrediction(PredictObjectUnknown);
break;
}
case GetGlobalVar: {
- changed |= m_variableUses.predictGlobalVar(node.varNumber(), m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
PredictedType prediction = m_graph.getGlobalVarPrediction(node.varNumber());
- if (isStrongPrediction(prediction))
+ if (prediction)
changed |= mergePrediction(prediction);
break;
}
case PutGlobalVar: {
- changed |= m_graph.predictGlobalVar(node.varNumber(), m_predictions[node.child1()] & ~PredictionTagMask, StrongPrediction);
- changed |= mergeUse(node.child1(), m_variableUses.getGlobalVarPrediction(node.varNumber()));
+ changed |= m_graph.predictGlobalVar(node.varNumber(), m_predictions[node.child1()]);
break;
}
case ResolveBase:
case ResolveBaseStrictPut:
case ResolveGlobal: {
- changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction);
PredictedType prediction = node.getPrediction();
- if (isStrongPrediction(prediction))
+ if (prediction)
changed |= mergePrediction(prediction);
break;
}
case GetScopeChain: {
- changed |= setPrediction(makePrediction(PredictCellOther, StrongPrediction));
+ changed |= setPrediction(PredictCellOther);
break;
}
- case PutByVal:
- case PutByValAlias:
- case PutById:
- case PutByIdDirect: {
- changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
- break;
- }
-
case GetCallee: {
- changed |= setPrediction(makePrediction(PredictObjectOther, StrongPrediction));
+ changed |= setPrediction(PredictObjectOther);
break;
}
case CreateThis: {
- changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
- changed |= setPrediction(makePrediction(PredictFinalObject, StrongPrediction));
+ changed |= setPrediction(PredictFinalObject);
break;
}
case StrCat: {
- changed |= setPrediction(makePrediction(PredictString, StrongPrediction));
+ changed |= setPrediction(PredictString);
break;
}
case ToPrimitive: {
PredictedType child = m_predictions[node.child1()];
- if (isStrongPrediction(child)) {
+ if (child) {
if (isObjectPrediction(child)) {
// I'd love to fold this case into the case below, but I can't, because
// removing PredictObjectMask from something that only has an object
// prediction and nothing else means we have an ill-formed PredictedType
// (strong predict-none). This should be killed once we remove all traces
// of static (aka weak) predictions.
- changed |= mergePrediction(makePrediction(PredictString, StrongPrediction));
+ changed |= mergePrediction(PredictString);
} else if (child & PredictObjectMask) {
// Objects get turned into strings. So if the input has hints of objectness,
// the output will have hinsts of stringiness.
- changed |= mergePrediction(mergePredictions(child & ~PredictObjectMask, makePrediction(PredictString, StrongPrediction)));
+ changed |= mergePrediction(mergePredictions(child & ~PredictObjectMask, PredictString));
} else
changed |= mergePrediction(child);
}
// This gets ignored because it doesn't do anything.
case Phantom:
+ case PutByVal:
+ case PutByValAlias:
+ case PutById:
+ case PutByIdDirect:
break;
#else
default:
}
#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
- printf("expect(%s) ", predictionToString(m_predictions[m_compileIndex]));
- printf("use(%s) %s\n", predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : "");
+ printf("%s ", predictionToString(m_predictions[m_compileIndex]));
#endif
m_changed |= changed;
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- if (isStrongPrediction(left) && isStrongPrediction(right) && isNumberPrediction(left) && isNumberPrediction(right)) {
+ if (left && right && isNumberPrediction(left) && isNumberPrediction(right)) {
if (left & PredictDouble)
toDouble(node.child2());
if (right & PredictDouble)
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- if (isStrongPrediction(left) && isStrongPrediction(right)) {
+ if (left && right) {
if (left & PredictDouble)
toDouble(node.child2());
if (right & PredictDouble)
}
PredictedType prediction = m_predictions[node.child1()];
- if (isStrongPrediction(prediction) && (prediction & PredictDouble))
+ if (prediction & PredictDouble)
toDouble(node.child1());
break;
}
{
PredictedType left = m_predictions[node.child1()];
PredictedType right = m_predictions[node.child2()];
- return isStrongPrediction(left) && isStrongPrediction(right)
- && isNumberPrediction(left) && isNumberPrediction(right);
+ return isNumberPrediction(left) && isNumberPrediction(right);
}
bool logicalNotIsPure(Node& node)
{
PredictedType prediction = m_predictions[node.child1()];
- return isBooleanPrediction(prediction) || !isStrongPrediction(prediction);
+ return isBooleanPrediction(prediction) || !prediction;
}
bool clobbersWorld(NodeIndex nodeIndex)
NodeIndex m_compileIndex;
Vector<PredictedType, 16> m_predictions;
- Vector<PredictedType, 16> m_uses;
-
- PredictionTracker m_variableUses;
#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
unsigned m_count;
break;
case GetLocal: {
- GPRTemporary result(this);
PredictedType prediction = m_jit.graph().getPrediction(node.local());
+
+ // If we have no prediction for this local, then don't attempt to compile.
+ if (prediction == PredictNone) {
+ terminateSpeculativeExecution();
+ break;
+ }
+
+ GPRTemporary result(this);
if (isInt32Prediction(prediction)) {
m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
break;
}
- PredictedType prediction = m_jit.graph().getPrediction(m_jit.graph()[node.child1()]);
- if (isBooleanPrediction(prediction) || !isStrongPrediction(prediction)) {
+ PredictedType prediction = m_jit.getPrediction(node.child1());
+ if (isBooleanPrediction(prediction) || !prediction) {
JSValueOperand value(this, node.child1());
GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
if (isInteger(nodeIndex))
return true;
- if (isInt32Prediction(m_jit.graph().getPrediction(m_jit.graph()[nodeIndex])))
+ if (isInt32Prediction(m_jit.getPrediction(nodeIndex)))
return true;
return false;
if (info.isJSDouble())
return true;
- if (isDoublePrediction(m_jit.graph().getPrediction(node)))
+ if (isDoublePrediction(m_jit.getPrediction(nodeIndex)))
return true;
return false;
if (info.isJSInteger() || info.isJSDouble())
return true;
- PredictedType prediction = m_jit.graph().getPrediction(node);
+ PredictedType prediction = m_jit.getPrediction(nodeIndex);
if (isNumberPrediction(prediction) || prediction == PredictNone)
return true;
if (info.isJSDouble())
return true;
- if (m_jit.graph().getPrediction(node) & PredictDouble)
+ if (m_jit.getPrediction(nodeIndex) & PredictDouble)
return true;
return false;
if (isJSConstant(nodeIndex))
prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
else
- prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
+ prediction = m_jit.getPrediction(nodeIndex);
return isFinalObjectPrediction(prediction);
}
if (isJSConstant(nodeIndex))
prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
else
- prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
+ prediction = m_jit.getPrediction(nodeIndex);
return isArrayPrediction(prediction);
}
if (isJSConstant(nodeIndex))
prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
else
- prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
+ prediction = m_jit.getPrediction(nodeIndex);
return isObjectPrediction(prediction);
}
Node& node = m_jit.graph()[nodeIndex];
- if (isCellPrediction(m_jit.graph().getPrediction(node)))
+ if (isCellPrediction(m_jit.getPrediction(nodeIndex)))
return true;
VirtualRegister virtualRegister = node.virtualRegister();
#if ENABLE(VALUE_PROFILER)
ASSERT(m_bytecodeOffset == (unsigned)-1);
- for (int argumentRegister = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters + 1; argumentRegister < -RegisterFile::CallFrameHeaderSize; ++argumentRegister) {
- loadPtr(Address(callFrameRegister, argumentRegister * sizeof(Register)), regT0);
- emitValueProfilingSite(FirstProfilingSite);
+ if (shouldEmitProfiling()) {
+ for (int argumentRegister = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters; argumentRegister < -RegisterFile::CallFrameHeaderSize; ++argumentRegister) {
+ // If this is a constructor, then we want to put in a dummy profiling site (to
+ // keep things consistent) but we don't actually want to record the dummy value.
+ if (m_codeBlock->m_isConstructor
+ && argumentRegister == -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters)
+ m_codeBlock->addValueProfile(-1);
+ else {
+ loadPtr(Address(callFrameRegister, argumentRegister * sizeof(Register)), regT0);
+ emitValueProfilingSite(FirstProfilingSite);
+ }
+ }
}
#endif