https://bugs.webkit.org/show_bug.cgi?id=63218
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jun 2011 21:04:40 +0000 (21:04 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jun 2011 21:04:40 +0000 (21:04 +0000)
DFG JIT - remove machine type guarantees from graph

Reviewed by Sam Weinig.

The DFG JIT currently makes assumptions about the types of machine registers
that certain nodes will be loaded into. This will be broken as we generate
nodes to produce both integer and double code paths. Remove int<->double
conversions nodes. This design decision also gave rise to multiple types of
constant nodes, requiring separate handling for each type. Merge these back
into JSConstant.

* dfg/DFGAliasTracker.h:
(JSC::DFG::AliasTracker::equalIgnoringLaterNumericConversion):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getToInt32):
(JSC::DFG::ByteCodeParser::getToNumber):
(JSC::DFG::ByteCodeParser::toInt32):
(JSC::DFG::ByteCodeParser::toNumber):
(JSC::DFG::ByteCodeParser::isInt32Constant):
(JSC::DFG::ByteCodeParser::isDoubleConstant):
(JSC::DFG::ByteCodeParser::valueOfInt32Constant):
(JSC::DFG::ByteCodeParser::valueOfDoubleConstant):
(JSC::DFG::ByteCodeParser::one):
(JSC::DFG::ByteCodeParser::predictInt32):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::silentFillGPR):
(JSC::DFG::JITCodeGenerator::silentFillFPR):
(JSC::DFG::JITCodeGenerator::isJSConstant):
(JSC::DFG::JITCodeGenerator::isDoubleConstant):
(JSC::DFG::JITCodeGenerator::valueOfJSConstantAsImmPtr):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::fillNumericToDouble):
(JSC::DFG::JITCompiler::fillInt32ToInteger):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::isJSConstant):
(JSC::DFG::JITCompiler::isInt32Constant):
(JSC::DFG::JITCompiler::isDoubleConstant):
(JSC::DFG::JITCompiler::valueOfJSConstant):
(JSC::DFG::JITCompiler::valueOfInt32Constant):
(JSC::DFG::JITCompiler::valueOfDoubleConstant):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::isConstant):
(JSC::DFG::Node::notTakenBytecodeOffset):
* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::isKnownInteger):
(JSC::DFG::NonSpeculativeJIT::isKnownNumeric):
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
(JSC::DFG::SpeculativeJIT::compile):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGAliasTracker.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

index 2edd1d2..5770728 100644 (file)
@@ -1,3 +1,62 @@
+2011-06-22  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        https://bugs.webkit.org/show_bug.cgi?id=63218
+        DFG JIT - remove machine type guarantees from graph
+
+        The DFG JIT currently makes assumptions about the types of machine registers
+        that certain nodes will be loaded into. This will be broken as we generate
+        nodes to produce both integer and double code paths. Remove int<->double
+        conversions nodes. This design decision also gave rise to multiple types of
+        constant nodes, requiring separate handling for each type. Merge these back
+        into JSConstant.
+
+        * dfg/DFGAliasTracker.h:
+        (JSC::DFG::AliasTracker::equalIgnoringLaterNumericConversion):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getToInt32):
+        (JSC::DFG::ByteCodeParser::getToNumber):
+        (JSC::DFG::ByteCodeParser::toInt32):
+        (JSC::DFG::ByteCodeParser::toNumber):
+        (JSC::DFG::ByteCodeParser::isInt32Constant):
+        (JSC::DFG::ByteCodeParser::isDoubleConstant):
+        (JSC::DFG::ByteCodeParser::valueOfInt32Constant):
+        (JSC::DFG::ByteCodeParser::valueOfDoubleConstant):
+        (JSC::DFG::ByteCodeParser::one):
+        (JSC::DFG::ByteCodeParser::predictInt32):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGJITCodeGenerator.h:
+        (JSC::DFG::JITCodeGenerator::silentFillGPR):
+        (JSC::DFG::JITCodeGenerator::silentFillFPR):
+        (JSC::DFG::JITCodeGenerator::isJSConstant):
+        (JSC::DFG::JITCodeGenerator::isDoubleConstant):
+        (JSC::DFG::JITCodeGenerator::valueOfJSConstantAsImmPtr):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::fillNumericToDouble):
+        (JSC::DFG::JITCompiler::fillInt32ToInteger):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::isJSConstant):
+        (JSC::DFG::JITCompiler::isInt32Constant):
+        (JSC::DFG::JITCompiler::isDoubleConstant):
+        (JSC::DFG::JITCompiler::valueOfJSConstant):
+        (JSC::DFG::JITCompiler::valueOfInt32Constant):
+        (JSC::DFG::JITCompiler::valueOfDoubleConstant):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::Node):
+        (JSC::DFG::Node::isConstant):
+        (JSC::DFG::Node::notTakenBytecodeOffset):
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::isKnownInteger):
+        (JSC::DFG::NonSpeculativeJIT::isKnownNumeric):
+        (JSC::DFG::NonSpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-06-23  Jungshik Shin  <jshin@chromium.org>
 
         Reviewed by Alexey Proskuryakov.
index 8710169..ae55ea6 100644 (file)
@@ -106,7 +106,7 @@ private:
         if (op1 == op2)
             return true;
         Node& node2 = m_graph[op2];
-        return (node2.op == ValueToNumber || node2.op == ValueToInt32 || node2.op == NumberToInt32) && op1 == node2.child1;
+        return (node2.op == ValueToNumber || node2.op == ValueToInt32) && op1 == node2.child1;
     }
 
     // The graph, to look up potentially aliasing nodes.
index 86f62e5..e898fb2 100644 (file)
@@ -175,26 +175,10 @@ private:
     // Get an operand, and perform a ToInt32/ToNumber conversion on it.
     NodeIndex getToInt32(int operand)
     {
-        // Avoid wastefully adding a JSConstant node to the graph, only to
-        // replace it with a Int32Constant (which is what would happen if
-        // we called 'toInt32(get(operand))' in this case).
-        if (operand >= FirstConstantRegisterIndex) {
-            JSValue v = m_codeBlock->getConstant(operand);
-            if (v.isInt32())
-                return getInt32Constant(v.asInt32(), operand - FirstConstantRegisterIndex);
-        }
         return toInt32(get(operand));
     }
     NodeIndex getToNumber(int operand)
     {
-        // Avoid wastefully adding a JSConstant node to the graph, only to
-        // replace it with a DoubleConstant (which is what would happen if
-        // we called 'toNumber(get(operand))' in this case).
-        if (operand >= FirstConstantRegisterIndex) {
-            JSValue v = m_codeBlock->getConstant(operand);
-            if (v.isNumber())
-                return getDoubleConstant(v.uncheckedGetNumber(), operand - FirstConstantRegisterIndex);
-        }
         return toNumber(get(operand));
     }
 
@@ -206,29 +190,16 @@ private:
         if (node.hasInt32Result())
             return index;
 
-        if (node.hasDoubleResult()) {
-            if (node.op == DoubleConstant)
-                return getInt32Constant(JSC::toInt32(valueOfDoubleConstant(index)), node.constantNumber());
-            // 'NumberToInt32(Int32ToNumber(X))' == X, and 'NumberToInt32(UInt32ToNumber(X)) == X'
-            if (node.op == Int32ToNumber || node.op == UInt32ToNumber)
-                return node.child1;
-
-            // We unique NumberToInt32 nodes in a map to prevent duplicate conversions.
-            pair<UnaryOpMap::iterator, bool> result = m_numberToInt32Nodes.add(index, NoNode);
-            // Either we added a new value, or the existing value in the map is non-zero.
-            ASSERT(result.second == (result.first->second == NoNode));
-            if (result.second)
-                result.first->second = addToGraph(NumberToInt32, index);
-            return result.first->second;
-        }
+        if (node.op == UInt32ToNumber)
+            return node.child1;
 
         // Check for numeric constants boxed as JSValues.
         if (node.op == JSConstant) {
             JSValue v = valueOfJSConstant(index);
             if (v.isInt32())
-                return getInt32Constant(v.asInt32(), node.constantNumber());
+                return getJSConstant(node.constantNumber());
             if (v.isNumber())
-                return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber());
+                return getJSConstant(node.constantNumber());
         }
 
         return addToGraph(ValueToInt32, index);
@@ -239,53 +210,18 @@ private:
     {
         Node& node = m_graph[index];
 
-        if (node.hasDoubleResult())
+        if (node.hasDoubleResult() || node.hasInt32Result())
             return index;
 
-        if (node.hasInt32Result()) {
-            if (node.op == Int32Constant)
-                return getDoubleConstant(valueOfInt32Constant(index), node.constantNumber());
-
-            // We unique Int32ToNumber nodes in a map to prevent duplicate conversions.
-            pair<UnaryOpMap::iterator, bool> result = m_int32ToNumberNodes.add(index, NoNode);
-            // Either we added a new value, or the existing value in the map is non-zero.
-            ASSERT(result.second == (result.first->second == NoNode));
-            if (result.second)
-                result.first->second = addToGraph(Int32ToNumber, index);
-            return result.first->second;
-        }
-
         if (node.op == JSConstant) {
             JSValue v = valueOfJSConstant(index);
             if (v.isNumber())
-                return getDoubleConstant(v.uncheckedGetNumber(), node.constantNumber());
+                return getJSConstant(node.constantNumber());
         }
 
         return addToGraph(ValueToNumber, index);
     }
 
-
-    // Used in implementing get, above, where the operand is a constant.
-    NodeIndex getInt32Constant(int32_t value, unsigned constant)
-    {
-        NodeIndex index = m_constants[constant].asInt32;
-        if (index != NoNode)
-            return index;
-        NodeIndex resultIndex = addToGraph(Int32Constant, OpInfo(constant));
-        m_graph[resultIndex].setInt32Constant(value);
-        m_constants[constant].asInt32 = resultIndex;
-        return resultIndex;
-    }
-    NodeIndex getDoubleConstant(double value, unsigned constant)
-    {
-        NodeIndex index = m_constants[constant].asNumeric;
-        if (index != NoNode)
-            return index;
-        NodeIndex resultIndex = addToGraph(DoubleConstant, OpInfo(constant));
-        m_graph[resultIndex].setDoubleConstant(value);
-        m_constants[constant].asNumeric = resultIndex;
-        return resultIndex;
-    }
     NodeIndex getJSConstant(unsigned constant)
     {
         NodeIndex index = m_constants[constant].asJSValue;
@@ -308,35 +244,37 @@ private:
     }
 
     // Convenience methods for checking nodes for constants.
-    bool isInt32Constant(NodeIndex index)
-    {
-        return m_graph[index].op == Int32Constant;
-    }
-    bool isDoubleConstant(NodeIndex index)
-    {
-        return m_graph[index].op == DoubleConstant;
-    }
     bool isJSConstant(NodeIndex index)
     {
         return m_graph[index].op == JSConstant;
     }
-
-    // Convenience methods for getting constant values.
-    int32_t valueOfInt32Constant(NodeIndex index)
+    bool isInt32Constant(NodeIndex nodeIndex)
     {
-        ASSERT(isInt32Constant(index));
-        return m_graph[index].int32Constant();
+        return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
     }
-    double valueOfDoubleConstant(NodeIndex index)
+    bool isDoubleConstant(NodeIndex nodeIndex)
     {
-        ASSERT(isDoubleConstant(index));
-        return m_graph[index].numericConstant();
+        return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isNumber();
     }
+    // Convenience methods for getting constant values.
     JSValue valueOfJSConstant(NodeIndex index)
     {
         ASSERT(isJSConstant(index));
         return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
     }
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex)
+    {
+        ASSERT(isInt32Constant(nodeIndex));
+        return valueOfJSConstant(nodeIndex).asInt32();
+    }
+    double valueOfDoubleConstant(NodeIndex nodeIndex)
+    {
+        ASSERT(isDoubleConstant(nodeIndex));
+        double value;
+        bool okay = valueOfJSConstant(nodeIndex).getNumber(value);
+        ASSERT_UNUSED(okay, okay);
+        return value;
+    }
 
     // This method returns a JSConstant with the value 'undefined'.
     NodeIndex constantUndefined()
@@ -398,7 +336,7 @@ private:
             for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
                 if (testMe.isInt32() && testMe.asInt32() == 1)
-                    return getDoubleConstant(1, m_constant1);
+                    return getJSConstant(m_constant1);
             }
 
             // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
@@ -411,7 +349,7 @@ private:
         // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
         ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
-        return getDoubleConstant(1, m_constant1);
+        return getJSConstant(m_constant1);
     }
 
 
@@ -463,9 +401,6 @@ private:
         if (nodePtr->op == ValueToInt32)
             nodePtr = &m_graph[nodePtr->child1];
 
-        if (nodePtr->op == NumberToInt32)
-            nodePtr = &m_graph[nodePtr->child1];
-
         if (nodePtr->op == GetLocal)
             m_graph.predict(nodePtr->local(), PredictInt32);
     }
@@ -533,11 +468,6 @@ private:
     };
     Vector<PhiStackEntry, 16> m_argumentPhiStack;
     Vector<PhiStackEntry, 16> m_localPhiStack;
-
-    // These maps are used to unique ToNumber and ToInt32 operations.
-    typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
-    UnaryOpMap m_int32ToNumberNodes;
-    UnaryOpMap m_numberToInt32Nodes;
 };
 
 #define NEXT_OPCODE(name) \
index b1e6991..7741bbd 100644 (file)
@@ -103,14 +103,6 @@ void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
             printf("%sr%u", hasPrinted ? ", " : "", local);
         hasPrinted = true;
     }
-    if (op == Int32Constant) {
-        printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant());
-        hasPrinted = true;
-    }
-    if (op == DoubleConstant) {
-        printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant());
-        hasPrinted = true;
-    }
     if (op == JSConstant) {
         printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
         hasPrinted = true;
index 781edbb..3a40961 100644 (file)
@@ -190,13 +190,8 @@ FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
         FPRReg fpr = fprAllocate();
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
-
         m_jit.convertInt32ToDouble(gpr, fpr);
-
-        m_gprs.release(gpr);
         m_gprs.unlock(gpr);
-        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
-        info.fillDouble(fpr);
         return fpr;
     }
 
index 1b4ad46..f4fc342 100644 (file)
@@ -203,15 +203,15 @@ protected:
 
         if (registerFormat == DataFormatInteger) {
             if (node.isConstant()) {
-                ASSERT(isIntegerConstant(nodeIndex));
-                m_jit.move(Imm32(valueOfIntegerConstant(nodeIndex)), info.gpr());
+                ASSERT(isInt32Constant(nodeIndex));
+                m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
             } else
                 m_jit.load32(JITCompiler::addressFor(spillMe), info.gpr());
             return;
         }
 
         if (node.isConstant())
-            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), info.gpr());
+            m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), info.gpr());
         else {
             ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell);
             m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr());
@@ -227,9 +227,11 @@ protected:
         Node& node = m_jit.graph()[nodeIndex];
         ASSERT(info.registerFormat() == DataFormatDouble);
 
-        if (node.isConstant())
-            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), info.gpr());
-        else {
+        if (node.isConstant()) {
+            ASSERT(isDoubleConstant(nodeIndex));
+            m_jit.move(JITCompiler::ImmPtr(bitwise_cast<void*>(valueOfDoubleConstant(nodeIndex))), canTrample);
+            m_jit.movePtrToDouble(canTrample, info.fpr());
+        } else {
             m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample);
             unboxDouble(canTrample, info.fpr());
         }
@@ -381,63 +383,13 @@ protected:
 
     // Checks/accessors for constant values.
     bool isConstant(NodeIndex nodeIndex) { return m_jit.isConstant(nodeIndex); }
+    bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); }
     bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); }
     bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); }
-    bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); }
     int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
     double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); }
     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
 
-    bool isDoubleConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
-    {
-        if (!m_jit.isDoubleConstant(nodeIndex))
-            return false;
-        double value = m_jit.valueOfDoubleConstant(nodeIndex);
-
-        int32_t asInt32 = static_cast<int32_t>(value);
-        if (value != asInt32)
-            return false;
-        if (!asInt32 && signbit(value))
-            return false;
-
-        out = asInt32;
-        return true;
-    }
-
-    bool isJSConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
-    {
-        if (!m_jit.isJSConstant(nodeIndex))
-            return false;
-        JSValue value = m_jit.valueOfJSConstant(nodeIndex);
-
-        if (!value.isInt32())
-            return false;
-        
-        out = value.asInt32();
-        return true;
-    }
-
-    bool isIntegerConstant(NodeIndex nodeIndex)
-    {
-        int32_t unused;
-        return isInt32Constant(nodeIndex)
-            || isDoubleConstantWithInt32Value(nodeIndex, unused)
-            || isJSConstantWithInt32Value(nodeIndex, unused);
-    }
-
-    int32_t valueOfIntegerConstant(NodeIndex nodeIndex)
-    {
-        if (isInt32Constant(nodeIndex))
-            return valueOfInt32Constant(nodeIndex);
-        int32_t result = 0;
-        bool okay = isDoubleConstantWithInt32Value(nodeIndex, result);
-        if (okay)
-            return result;
-        okay = isJSConstantWithInt32Value(nodeIndex, result);
-        ASSERT_UNUSED(okay, okay);
-        return result;
-    }
-
     Identifier* identifier(unsigned index)
     {
         return &m_jit.codeBlock()->identifier(index);
@@ -477,20 +429,9 @@ protected:
     }
 #endif
 
-    // Get the JSValue representation of a constant.
-    JSValue constantAsJSValue(NodeIndex nodeIndex)
-    {
-        Node& node = m_jit.graph()[nodeIndex];
-        if (isInt32Constant(nodeIndex))
-            return jsNumber(node.int32Constant());
-        if (isDoubleConstant(nodeIndex))
-            return JSValue(JSValue::EncodeAsDouble, node.numericConstant());
-        ASSERT(isJSConstant(nodeIndex));
-        return valueOfJSConstant(nodeIndex);
-    }
-    MacroAssembler::ImmPtr constantAsJSValueAsImmPtr(NodeIndex nodeIndex)
+    MacroAssembler::ImmPtr valueOfJSConstantAsImmPtr(NodeIndex nodeIndex)
     {
-        return MacroAssembler::ImmPtr(JSValue::encode(constantAsJSValue(nodeIndex)));
+        return MacroAssembler::ImmPtr(JSValue::encode(valueOfJSConstant(nodeIndex)));
     }
 
     // Helper functions to enable code sharing in implementations of bit/shift ops.
index 0c8ffef..af070c5 100644 (file)
@@ -45,7 +45,7 @@ void JITCompiler::fillNumericToDouble(NodeIndex nodeIndex, FPRReg fpr, GPRReg te
     Node& node = graph()[nodeIndex];
 
     if (node.isConstant()) {
-        ASSERT(node.op == DoubleConstant);
+        ASSERT(isDoubleConstant(nodeIndex));
         move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), temporary);
         movePtrToDouble(temporary, fpr);
     } else {
@@ -67,7 +67,7 @@ void JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr)
     Node& node = graph()[nodeIndex];
 
     if (node.isConstant()) {
-        ASSERT(node.op == Int32Constant);
+        ASSERT(isInt32Constant(nodeIndex));
         move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
     } else {
 #if DFG_JIT_ASSERT
index 5075614..3f5926c 100644 (file)
@@ -179,35 +179,34 @@ public:
     {
         return graph()[nodeIndex].isConstant();
     }
+    bool isJSConstant(NodeIndex nodeIndex)
+    {
+        return graph()[nodeIndex].isConstant();
+    }
     bool isInt32Constant(NodeIndex nodeIndex)
     {
-        return graph()[nodeIndex].op == Int32Constant;
+        return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
     }
     bool isDoubleConstant(NodeIndex nodeIndex)
     {
-        return graph()[nodeIndex].op == DoubleConstant;
+        return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isNumber();
     }
-    bool isJSConstant(NodeIndex nodeIndex)
+    // Helper methods get constant values from nodes.
+    JSValue valueOfJSConstant(NodeIndex nodeIndex)
     {
-        return graph()[nodeIndex].op == JSConstant;
+        ASSERT(isJSConstant(nodeIndex));
+        unsigned constantIndex = graph()[nodeIndex].constantNumber();
+        return codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex).get();
     }
-
-    // Helper methods get constant values from nodes.
     int32_t valueOfInt32Constant(NodeIndex nodeIndex)
     {
         ASSERT(isInt32Constant(nodeIndex));
-        return graph()[nodeIndex].int32Constant();
+        return valueOfJSConstant(nodeIndex).asInt32();
     }
     double valueOfDoubleConstant(NodeIndex nodeIndex)
     {
         ASSERT(isDoubleConstant(nodeIndex));
-        return graph()[nodeIndex].numericConstant();
-    }
-    JSValue valueOfJSConstant(NodeIndex nodeIndex)
-    {
-        ASSERT(isJSConstant(nodeIndex));
-        unsigned constantIndex = graph()[nodeIndex].constantNumber();
-        return codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex).get();
+        return valueOfJSConstant(nodeIndex).uncheckedGetNumber();
     }
 
     // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
index 2ea6570..970cbfc 100644 (file)
@@ -85,9 +85,7 @@ typedef uint32_t ExceptionInfo;
 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
 #define FOR_EACH_DFG_OP(macro) \
     /* Nodes for constants. */\
-    macro(JSConstant, NodeResultJS | NodeIsConstant) \
-    macro(Int32Constant, NodeResultJS | NodeIsConstant) \
-    macro(DoubleConstant, NodeResultJS | NodeIsConstant) \
+    macro(JSConstant, NodeResultJS) \
     macro(ConvertThis, NodeResultJS) \
     \
     /* Nodes for local variable access. */\
@@ -103,7 +101,6 @@ typedef uint32_t ExceptionInfo;
     macro(BitRShift, NodeResultInt32) \
     macro(BitURShift, NodeResultInt32) \
     /* Bitwise operators call ToInt32 on their operands. */\
-    macro(NumberToInt32, NodeResultInt32) \
     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
     macro(UInt32ToNumber, NodeResultDouble) \
@@ -115,7 +112,6 @@ typedef uint32_t ExceptionInfo;
     macro(ArithDiv, NodeResultDouble) \
     macro(ArithMod, NodeResultDouble) \
     /* Arithmetic operators call ToNumber on their operands. */\
-    macro(Int32ToNumber, NodeResultDouble) \
     macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \
     \
     /* Add of values may either be arithmetic, or result in string concatenation. */\
@@ -211,8 +207,8 @@ struct Node {
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_opInfo(imm1.m_value)
+        , m_opInfo2(imm2.m_value)
     {
-        m_constantValue.opInfo2 = imm2.m_value;
     }
 
     bool mustGenerate()
@@ -222,7 +218,7 @@ struct Node {
 
     bool isConstant()
     {
-        return op & NodeIsConstant;
+        return op == JSConstant;
     }
 
     unsigned constantNumber()
@@ -292,30 +288,6 @@ struct Node {
         return !hasJSResult();
     }
 
-    int32_t int32Constant()
-    {
-        ASSERT(op == Int32Constant);
-        return m_constantValue.asInt32;
-    }
-
-    void setInt32Constant(int32_t value)
-    {
-        ASSERT(op == Int32Constant);
-        m_constantValue.asInt32 = value;
-    }
-
-    double numericConstant()
-    {
-        ASSERT(op == DoubleConstant);
-        return m_constantValue.asDouble;
-    }
-
-    void setDoubleConstant(double value)
-    {
-        ASSERT(op == DoubleConstant);
-        m_constantValue.asDouble = value;
-    }
-
     bool isJump()
     {
         return op & NodeIsJump;
@@ -340,7 +312,7 @@ struct Node {
     unsigned notTakenBytecodeOffset()
     {
         ASSERT(isBranch());
-        return m_constantValue.opInfo2;
+        return m_opInfo2;
     }
 
     VirtualRegister virtualRegister()
@@ -390,14 +362,8 @@ private:
     VirtualRegister m_virtualRegister;
     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
     unsigned m_refCount;
-    // An immediate value, accesses type-checked via accessors above.
-    unsigned m_opInfo;
-    // The value of an int32/double constant.
-    union {
-        int32_t asInt32;
-        double asDouble;
-        unsigned opInfo2;
-    } m_constantValue;
+    // Immediate values, accesses type-checked via accessors above.
+    unsigned m_opInfo, m_opInfo2;
 };
 
 } } // namespace JSC::DFG
index 7c50715..ad9d590 100644 (file)
@@ -103,7 +103,7 @@ void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
     m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
     silentFillAllRegisters(result);
     JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
-    
+
     // Then handle integers.
     isInteger.link(&m_jit);
     m_jit.zeroExtend32ToPtr(jsValueGpr, result);
@@ -127,6 +127,9 @@ void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
 
 bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
 {
+    if (isInt32Constant(nodeIndex))
+        return true;
+
     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
 
     DataFormat registerFormat = info.registerFormat();
@@ -138,11 +141,14 @@ bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
         return (spillFormat | DataFormatJS) == DataFormatJSInteger;
 
     ASSERT(isConstant(nodeIndex));
-    return isInt32Constant(nodeIndex);
+    return false;
 }
 
 bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
 {
+    if (isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex))
+        return true;
+
     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
 
     DataFormat registerFormat = info.registerFormat();
@@ -156,7 +162,7 @@ bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
             || (spillFormat | DataFormatJS) == DataFormatJSDouble;
 
     ASSERT(isConstant(nodeIndex));
-    return isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex);
+    return false;
 }
 
 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
@@ -184,8 +190,6 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
         break;
     }
 
-    case Int32Constant:
-    case DoubleConstant:
     case JSConstant:
         initConstantInfo(m_compileIndex);
         break;
@@ -279,15 +283,6 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
         break;
     }
 
-    case Int32ToNumber: {
-        IntegerOperand op1(this, node.child1);
-        FPRTemporary result(this);
-        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
-        doubleResult(result.fpr(), m_compileIndex);
-        break;
-    }
-
-    case NumberToInt32:
     case ValueToInt32: {
         ASSERT(!isInt32Constant(node.child1));
 
@@ -299,7 +294,8 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
             break;
         }
 
-        if (isKnownNumeric(node.child1)) {
+        GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister()];
+        if ((childInfo.registerFormat() || DataFormatJS) == DataFormatJSDouble) {
             DoubleOperand op1(this, node.child1);
             GPRTemporary result(this);
             numberToInt32(op1.fpr(), result.gpr());
@@ -307,9 +303,6 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
             break;
         }
 
-        // We should have handled this via isKnownInteger, or isKnownNumeric!
-        ASSERT(op != NumberToInt32);
-
         JSValueOperand op1(this, node.child1);
         GPRTemporary result(this, op1);
         valueToInt32(op1, result.gpr());
@@ -329,7 +322,8 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
             break;
         }
 
-        if (isKnownNumeric(node.child1)) {
+        GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister()];
+        if ((childInfo.registerFormat() || DataFormatJS) == DataFormatJSDouble) {
             DoubleOperand op1(this, node.child1);
             FPRTemporary result(this, op1);
             m_jit.moveDouble(op1.fpr(), result.fpr());
index 4d9e36f..f243e22 100644 (file)
@@ -49,7 +49,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
                 returnFormat = DataFormatInteger;
                 return gpr;
             }
-            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), gpr);
+            m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), gpr);
         } else {
             DataFormat spillFormat = info.spillFormat();
             ASSERT(spillFormat & DataFormatJS);
@@ -185,7 +185,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
         GPRReg gpr = allocate();
 
         if (node.isConstant()) {
-            JSValue jsValue = constantAsJSValue(nodeIndex);
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
             if (jsValue.isCell()) {
                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
@@ -248,12 +248,13 @@ void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNo
         notTaken = tmp;
     }
 
-    int32_t imm;
-    if (isJSConstantWithInt32Value(node.child1, imm)) {
+    if (isInt32Constant(node.child1)) {
+        int32_t imm = valueOfInt32Constant(node.child1);
         SpeculateIntegerOperand op2(this, node.child2);
         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
-    } else if (isJSConstantWithInt32Value(node.child2, imm)) {
+    } else if (isInt32Constant(node.child2)) {
         SpeculateIntegerOperand op1(this, node.child1);
+        int32_t imm = valueOfInt32Constant(node.child2);
         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
     } else {
         SpeculateIntegerOperand op1(this, node.child1);
@@ -302,8 +303,6 @@ void SpeculativeJIT::compile(Node& node)
     NodeType op = node.op;
 
     switch (op) {
-    case Int32Constant:
-    case DoubleConstant:
     case JSConstant:
         initConstantInfo(m_compileIndex);
         break;
@@ -422,22 +421,6 @@ void SpeculativeJIT::compile(Node& node)
         break;
     }
 
-    case NumberToInt32: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
-        m_jit.move(op1.gpr(), result.gpr());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
-        break;
-    }
-
-    case Int32ToNumber: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
-        m_jit.move(op1.gpr(), result.gpr());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
-        break;
-    }
-
     case ValueToInt32: {
         SpeculateIntegerOperand op1(this, node.child1);
         GPRTemporary result(this, op1);
@@ -456,8 +439,8 @@ void SpeculativeJIT::compile(Node& node)
 
     case ValueAdd:
     case ArithAdd: {
-        int32_t imm1;
-        if (isDoubleConstantWithInt32Value(node.child1, imm1)) {
+        if (isInt32Constant(node.child1)) {
+            int32_t imm1 = valueOfInt32Constant(node.child1);
             SpeculateIntegerOperand op2(this, node.child2);
             GPRTemporary result(this);
 
@@ -467,9 +450,9 @@ void SpeculativeJIT::compile(Node& node)
             break;
         }
             
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
+        if (isInt32Constant(node.child2)) {
             SpeculateIntegerOperand op1(this, node.child1);
+            int32_t imm2 = valueOfInt32Constant(node.child2);
             GPRTemporary result(this);
 
             speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
@@ -499,9 +482,9 @@ void SpeculativeJIT::compile(Node& node)
     }
 
     case ArithSub: {
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
+        if (isInt32Constant(node.child2)) {
             SpeculateIntegerOperand op1(this, node.child1);
+            int32_t imm2 = valueOfInt32Constant(node.child2);
             GPRTemporary result(this);
 
             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));