Title: [120974] trunk/Source/_javascript_Core
Revision
120974
Author
[email protected]
Date
2012-06-21 15:55:42 -0700 (Thu, 21 Jun 2012)

Log Message

DFG should inline 'new Array()'
https://bugs.webkit.org/show_bug.cgi?id=89632

Reviewed by Geoffrey Garen.
        
This adds support for treating InternalFunction like intrinsics. The code
to do so is actually quite clean, so I don't feel bad about perpetuating
the InternalFunction vs. JSFunction-with-NativeExecutable dichotomy.
        
Currently this newfound power is only used to inline 'new Array()'.
        
* dfg/DFGByteCodeParser.cpp:
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(DFG):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::isInternalFunctionConstant):
(JSC::DFG::Graph::valueOfInternalFunctionConstant):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (120973 => 120974)


--- trunk/Source/_javascript_Core/ChangeLog	2012-06-21 22:47:45 UTC (rev 120973)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-06-21 22:55:42 UTC (rev 120974)
@@ -1,3 +1,25 @@
+2012-06-20  Filip Pizlo  <[email protected]>
+
+        DFG should inline 'new Array()'
+        https://bugs.webkit.org/show_bug.cgi?id=89632
+
+        Reviewed by Geoffrey Garen.
+        
+        This adds support for treating InternalFunction like intrinsics. The code
+        to do so is actually quite clean, so I don't feel bad about perpetuating
+        the InternalFunction vs. JSFunction-with-NativeExecutable dichotomy.
+        
+        Currently this newfound power is only used to inline 'new Array()'.
+        
+        * dfg/DFGByteCodeParser.cpp:
+        (ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (DFG):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::isInternalFunctionConstant):
+        (JSC::DFG::Graph::valueOfInternalFunctionConstant):
+
 2012-06-21  Mark Hahnenberg  <[email protected]>
 
         Adding copyrights to new files.

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (120973 => 120974)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-06-21 22:47:45 UTC (rev 120973)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-06-21 22:55:42 UTC (rev 120974)
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "ArrayConstructor.h"
 #include "CallLinkStatus.h"
 #include "CodeBlock.h"
 #include "DFGByteCodeCache.h"
@@ -95,6 +96,7 @@
     void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex);
     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
     bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction);
+    bool handleConstantInternalFunction(bool usesResult, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind);
     void handleGetByOffset(
         int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
         bool useInlineStorage, size_t offset);
@@ -1128,7 +1130,12 @@
     ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
     
     NodeIndex callTarget = get(currentInstruction[1].u.operand);
-    enum { ConstantFunction, LinkedFunction, UnknownFunction } callType;
+    enum {
+        ConstantFunction,
+        ConstantInternalFunction,
+        LinkedFunction,
+        UnknownFunction
+    } callType;
             
     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
         m_inlineStackTop->m_profiledBlock, m_currentIndex);
@@ -1151,6 +1158,13 @@
                 m_graph.valueOfFunctionConstant(callTarget),
                 m_graph.valueOfFunctionConstant(callTarget)->executable());
 #endif
+    } else if (m_graph.isInternalFunctionConstant(callTarget)) {
+        callType = ConstantInternalFunction;
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Call at [@%lu, bc#%u] has an internal function constant: %p.\n",
+                m_graph.size(), m_currentIndex,
+                m_graph.valueOfInternalFunctionConstant(callTarget));
+#endif
     } else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
         callType = LinkedFunction;
@@ -1183,6 +1197,16 @@
             prediction = getPrediction();
             nextOffset += OPCODE_LENGTH(op_call_put_result);
         }
+
+        if (callType == ConstantInternalFunction) {
+            if (handleConstantInternalFunction(usesResult, resultOperand, m_graph.valueOfInternalFunctionConstant(callTarget), registerOffset, argumentCountIncludingThis, prediction, kind))
+                return;
+            
+            // Can only handle this using the generic call handler.
+            addCall(interpreter, currentInstruction, op);
+            return;
+        }
+        
         JSFunction* expectedFunction;
         Intrinsic intrinsic;
         bool certainAboutExpectedFunction;
@@ -1214,7 +1238,7 @@
         } else if (handleInlining(usesResult, currentInstruction[1].u.operand, callTarget, resultOperand, certainAboutExpectedFunction, expectedFunction, registerOffset, argumentCountIncludingThis, nextOffset, kind))
             return;
     }
-            
+    
     addCall(interpreter, currentInstruction, op);
 }
 
@@ -1571,6 +1595,35 @@
     }
 }
 
+bool ByteCodeParser::handleConstantInternalFunction(
+    bool usesResult, int resultOperand, InternalFunction* function, int registerOffset,
+    int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind kind)
+{
+    // If we ever find that we have a lot of internal functions that we specialize for,
+    // then we should probably have some sort of hashtable dispatch, or maybe even
+    // dispatch straight through the MethodTable of the InternalFunction. But for now,
+    // it seems that this case is hit infrequently enough, and the number of functions
+    // we know about is small enough, that having just a linear cascade of if statements
+    // is good enough.
+    
+    UNUSED_PARAM(registerOffset); // Remove this once we do more things to the arguments.
+    UNUSED_PARAM(prediction); // Remove this once we do more things.
+    UNUSED_PARAM(kind); // Remove this once we do more things.
+    
+    if (function->classInfo() == &ArrayConstructor::s_info) {
+        // We could handle this but don't for now.
+        if (argumentCountIncludingThis != 1)
+            return false;
+        
+        setIntrinsicResult(
+            usesResult, resultOperand,
+            addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
+        return true;
+    }
+    
+    return false;
+}
+
 void ByteCodeParser::handleGetByOffset(
     int destinationOperand, SpeculatedType prediction, NodeIndex base, unsigned identifierNumber,
     bool useInlineStorage, size_t offset)

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (120973 => 120974)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2012-06-21 22:47:45 UTC (rev 120973)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2012-06-21 22:55:42 UTC (rev 120974)
@@ -277,6 +277,18 @@
             return false;
         return true;
     }
+    bool isInternalFunctionConstant(NodeIndex nodeIndex)
+    {
+        if (!isJSConstant(nodeIndex))
+            return false;
+        JSValue value = valueOfJSConstant(nodeIndex);
+        if (!value.isCell() || !value)
+            return false;
+        JSCell* cell = value.asCell();
+        if (!cell->inherits(&InternalFunction::s_info))
+            return false;
+        return true;
+    }
     // Helper methods get constant values from nodes.
     JSValue valueOfJSConstant(NodeIndex nodeIndex)
     {
@@ -300,6 +312,10 @@
         ASSERT(function);
         return jsCast<JSFunction*>(function);
     }
+    InternalFunction* valueOfInternalFunctionConstant(NodeIndex nodeIndex)
+    {
+        return jsCast<InternalFunction*>(valueOfJSConstant(nodeIndex).asCell());
+    }
 
     static const char *opName(NodeType);
     
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to