DFG static prediction code is no longer needed and should be removed
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Sep 2011 02:25:02 +0000 (02:25 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Sep 2011 02:25:02 +0000 (02:25 +0000)
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):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95930 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/PredictedType.cpp
Source/JavaScriptCore/bytecode/PredictedType.h
Source/JavaScriptCore/bytecode/PredictionTracker.h
Source/JavaScriptCore/bytecode/ValueProfile.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGPropagator.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/jit/JIT.cpp

index 156cd7a..d245de9 100644 (file)
@@ -1,5 +1,94 @@
 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
index 655f961..a210985 100644 (file)
@@ -1999,7 +1999,7 @@ bool CodeBlock::shouldOptimizeNow()
 #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++;
@@ -2026,7 +2026,7 @@ void CodeBlock::dumpValueProfiles()
         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) {
index c3a4c09..4898dac 100644 (file)
@@ -498,10 +498,10 @@ namespace JSC {
         }
         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;
index 637a7ec..d19019f 100644 (file)
@@ -37,13 +37,13 @@ namespace JSC {
 #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");
index 8284e4c..d1a0c6e 100644 (file)
@@ -51,60 +51,50 @@ static const PredictedType PredictNumber        = 0x0300; // It's either an Int3
 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
@@ -113,25 +103,16 @@ const char* predictionToString(PredictedType value);
 
 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>
@@ -143,15 +124,6 @@ inline bool mergePrediction(T& left, PredictedType right)
     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*);
index baa1c1c..7197464 100644 (file)
@@ -73,33 +73,33 @@ public:
     
     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)
index 0922645..6dad6ef 100644 (file)
@@ -94,25 +94,25 @@ PredictedType ValueProfile::computeUpdatedPrediction()
     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);
index 0e971a0..e09f555 100644 (file)
@@ -101,10 +101,8 @@ private:
         // 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);
@@ -436,7 +434,7 @@ private:
 
         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;
@@ -452,42 +450,7 @@ private:
         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);
         
@@ -507,9 +470,9 @@ private:
         return prediction;
     }
     
-    PredictedType getStrongPrediction()
+    PredictedType getPrediction()
     {
-        return getStrongPrediction(m_graph.size(), m_currentIndex);
+        return getPrediction(m_graph.size(), m_currentIndex);
     }
 
     NodeIndex makeSafe(NodeIndex nodeIndex)
@@ -771,65 +734,53 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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,
@@ -850,7 +801,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 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);
         }
 
@@ -859,7 +810,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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);
         }
@@ -868,7 +818,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             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);
@@ -877,7 +826,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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);
         }
@@ -886,7 +834,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             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);
@@ -897,13 +844,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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
@@ -914,11 +854,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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);
         }
@@ -1062,12 +997,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         // === 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);
@@ -1079,8 +1012,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             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);
 
@@ -1090,7 +1021,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         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);
             
@@ -1124,7 +1055,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             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;
@@ -1142,7 +1073,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             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;
@@ -1188,11 +1119,11 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         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);
         }
 
@@ -1424,7 +1355,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_call_put_result);
 
         case op_resolve: {
-            PredictedType prediction = getStrongPrediction();
+            PredictedType prediction = getPrediction();
             
             unsigned identifier = currentInstruction[2].u.operand;
 
@@ -1435,7 +1366,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_resolve_base: {
-            PredictedType prediction = getStrongPrediction();
+            PredictedType prediction = getPrediction();
             
             unsigned identifier = currentInstruction[2].u.operand;
 
@@ -1446,7 +1377,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
             
         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());
index b4a5b31..8507a0c 100644 (file)
@@ -206,13 +206,8 @@ void Graph::predictArgumentTypes(ExecState* exec, CodeBlock* codeBlock)
     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);
@@ -220,12 +215,12 @@ void Graph::predictArgumentTypes(ExecState* exec, CodeBlock* 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)));
index c754128..7f79fe8 100644 (file)
@@ -176,24 +176,24 @@ public:
         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:
@@ -206,7 +206,7 @@ public:
         case ResolveBase:
         case ResolveBaseStrictPut:
         case ResolveGlobal:
-            return node.predict(prediction, source);
+            return node.predict(prediction);
         default:
             return false;
         }
@@ -224,10 +224,15 @@ public:
     
     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;
         
@@ -251,6 +256,8 @@ public:
             return nodePtr->getPrediction();
         case CheckMethod:
             return getMethodCheckPrediction(*nodePtr);
+        case JSConstant:
+            return getJSConstantPrediction(*nodePtr, codeBlock);
         default:
             return PredictNone;
         }
index 5df549d..e8f60ee 100644 (file)
@@ -1229,7 +1229,7 @@ void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex
 #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);
     }
@@ -1270,7 +1270,7 @@ void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex va
 #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);
     }
@@ -1796,7 +1796,7 @@ void JITCodeGenerator::emitBranch(Node& node)
         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);
index 15ebc46..095f224 100644 (file)
@@ -272,6 +272,10 @@ public:
     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)
index 1bc57b8..a4a86e6 100644 (file)
@@ -426,14 +426,20 @@ struct Node {
         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;
@@ -441,14 +447,14 @@ struct Node {
     
     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()
@@ -655,22 +661,11 @@ struct Node {
         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()
@@ -803,14 +798,6 @@ struct Node {
     } 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).
index 1a4963d..ae299e0 100644 (file)
@@ -47,25 +47,11 @@ public:
         // 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;
         }
         
@@ -306,13 +292,6 @@ private:
         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());
@@ -335,23 +314,19 @@ private:
         
         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;
         }
             
@@ -362,7 +337,7 @@ private:
         case BitLShift:
         case BitURShift:
         case ValueToInt32: {
-            changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction));
+            changed |= setPrediction(PredictInt32);
             break;
         }
 
@@ -370,31 +345,31 @@ private:
             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;
@@ -411,17 +386,17 @@ private:
             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;
         }
@@ -435,27 +410,27 @@ private:
             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;
         }
@@ -468,69 +443,55 @@ private:
         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;
         }
             
@@ -539,56 +500,46 @@ private:
         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);
             }
@@ -611,6 +562,10 @@ private:
             
         // This gets ignored because it doesn't do anything.
         case Phantom:
+        case PutByVal:
+        case PutByValAlias:
+        case PutById:
+        case PutByIdDirect:
             break;
 #else
         default:
@@ -619,8 +574,7 @@ private:
         }
 
 #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;
@@ -676,7 +630,7 @@ private:
             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)
@@ -701,7 +655,7 @@ private:
             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)
@@ -717,7 +671,7 @@ private:
             }
             
             PredictedType prediction = m_predictions[node.child1()];
-            if (isStrongPrediction(prediction) && (prediction & PredictDouble))
+            if (prediction & PredictDouble)
                 toDouble(node.child1());
             break;
         }
@@ -866,14 +820,13 @@ private:
     {
         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)
@@ -1232,9 +1185,6 @@ private:
     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;
index 6158ef2..d461a0a 100644 (file)
@@ -695,8 +695,15 @@ void SpeculativeJIT::compile(Node& node)
         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());
 
@@ -1300,8 +1307,8 @@ void SpeculativeJIT::compile(Node& node)
             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).
             
index 5b4fe1b..53ede6f 100644 (file)
@@ -370,7 +370,7 @@ private:
         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;
@@ -389,7 +389,7 @@ private:
         if (info.isJSDouble())
             return true;
         
-        if (isDoublePrediction(m_jit.graph().getPrediction(node)))
+        if (isDoublePrediction(m_jit.getPrediction(nodeIndex)))
             return true;
         
         return false;
@@ -411,7 +411,7 @@ private:
         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;
@@ -432,7 +432,7 @@ private:
         if (info.isJSDouble())
             return true;
         
-        if (m_jit.graph().getPrediction(node) & PredictDouble)
+        if (m_jit.getPrediction(nodeIndex) & PredictDouble)
             return true;
         
         return false;
@@ -444,7 +444,7 @@ private:
         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);
     }
     
@@ -454,7 +454,7 @@ private:
         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);
     }
     
@@ -467,7 +467,7 @@ private:
         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);
     }
     
@@ -478,7 +478,7 @@ private:
         
         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();
index aa2effb..ef06031 100644 (file)
@@ -554,9 +554,18 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
 
 #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