Title: [96962] trunk/Source/_javascript_Core
Revision
96962
Author
[email protected]
Date
2011-10-07 11:39:45 -0700 (Fri, 07 Oct 2011)

Log Message

Support direct calls to intrinsic functions
https://bugs.webkit.org/show_bug.cgi?id=69646

Reviewed by Gavin Barraclough.

Add support for optimising non-method_check calls
to intrinsic functions (eg. when Math.abs, etc are
cached in local variables).

* bytecode/CodeBlock.h:
(JSC::getCallLinkInfoBytecodeIndex):
    Support searching CallLinkInfos by bytecode index
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
    Add support for linked calls in addition to method_check
    when searching for intrinsics
* dfg/DFGNode.h:
(JSC::DFG::Node::hasFunctionCheckData):
(JSC::DFG::Node::function):
    Add ability to store a JSFunction* in a node - this is safe
    as the function will be marked by the codeblock we're compiling
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::checkFunctionElimination):
(JSC::DFG::Propagator::performNodeCSE):
    Add support for new CheckFunction node, and implement CSE pass.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
    Rather trivial implementation of CheckFunction
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileOpCall):
    Need to propagate bytecode index for calls now.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (96961 => 96962)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-07 18:39:45 UTC (rev 96962)
@@ -1,3 +1,45 @@
+2011-10-07  Oliver Hunt  <[email protected]>
+
+        Support direct calls to intrinsic functions
+        https://bugs.webkit.org/show_bug.cgi?id=69646
+
+        Reviewed by Gavin Barraclough.
+
+        Add support for optimising non-method_check calls
+        to intrinsic functions (eg. when Math.abs, etc are
+        cached in local variables). 
+
+        * bytecode/CodeBlock.h:
+        (JSC::getCallLinkInfoBytecodeIndex):
+            Support searching CallLinkInfos by bytecode index
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+            Add support for linked calls in addition to method_check
+            when searching for intrinsics
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasFunctionCheckData):
+        (JSC::DFG::Node::function):
+            Add ability to store a JSFunction* in a node - this is safe
+            as the function will be marked by the codeblock we're compiling
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        (JSC::DFG::Propagator::checkFunctionElimination):
+        (JSC::DFG::Propagator::performNodeCSE):
+            Add support for new CheckFunction node, and implement CSE pass.
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+            Rather trivial implementation of CheckFunction
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileOpCall):
+            Need to propagate bytecode index for calls now.
+
 2011-10-07  Dominic Cooney  <[email protected]>
 
         [JSC] Disable ThreadRestrictionVerifier for JIT ExecutableMemoryHandles

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (96961 => 96962)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-10-07 18:39:45 UTC (rev 96962)
@@ -124,6 +124,7 @@
         bool hasSeenShouldRepatch : 1;
         bool isCall : 1;
         bool isDFG : 1;
+        unsigned bytecodeIndex;
 
         bool isLinked() { return callee; }
         void unlink(JSGlobalData&, RepatchBuffer&);
@@ -210,6 +211,11 @@
         return callLinkInfo->callReturnLocation.executableAddress();
     }
 
+    inline unsigned getCallLinkInfoBytecodeIndex(CallLinkInfo* callLinkInfo)
+    {
+        return callLinkInfo->bytecodeIndex;
+    }
+
     inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo)
     {
         return methodCallLinkInfo->callReturnLocation.executableAddress();
@@ -290,6 +296,11 @@
         {
             return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
         }
+        
+        CallLinkInfo& getCallLinkInfo(unsigned bytecodeIndex)
+        {
+            return *(binarySearch<CallLinkInfo, unsigned, getCallLinkInfoBytecodeIndex>(m_callLinkInfos.begin(), m_callLinkInfos.size(), bytecodeIndex));
+        }
 
         MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress)
         {

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -1543,7 +1543,15 @@
             
         case op_call: {
             NodeIndex callTarget = get(currentInstruction[1].u.operand);
-            if (m_graph.isFunctionConstant(m_codeBlock, callTarget)) {
+            enum { ConstantFunction, LinkedFunction, UnknownFunction } callType;
+            
+            if (m_graph.isFunctionConstant(m_codeBlock, callTarget))
+                callType = ConstantFunction;
+            else if (m_profiledBlock->getCallLinkInfo(m_currentIndex).isLinked())
+                callType = LinkedFunction;
+            else
+                callType = UnknownFunction;
+            if (callType != UnknownFunction) {
                 int argCount = currentInstruction[2].u.operand;
                 int registerOffset = currentInstruction[3].u.operand;
                 int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
@@ -1559,9 +1567,17 @@
                     usesResult = true;
                     prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
                 }
+                DFG::Intrinsic intrinsic;
+                if (callType == ConstantFunction)
+                    intrinsic = m_graph.valueOfFunctionConstant(m_codeBlock, callTarget)->executable()->intrinsic();
+                else {
+                    ASSERT(callType == LinkedFunction);
+                    JSFunction* function = m_profiledBlock->getCallLinkInfo(m_currentIndex).callee.get();
+                    intrinsic = function->executable()->intrinsic();
+                    if (intrinsic != NoIntrinsic)
+                        addToGraph(CheckFunction, OpInfo(function), callTarget);
+                }
                 
-                DFG::Intrinsic intrinsic = m_graph.valueOfFunctionConstant(m_codeBlock, callTarget)->executable()->intrinsic();
-                
                 if (handleIntrinsic(usesResult, resultOperand, intrinsic, firstArg, lastArg, prediction)) {
                     // NEXT_OPCODE() has to be inside braces.
                     NEXT_OPCODE(op_call);

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (96961 => 96962)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-07 18:39:45 UTC (rev 96962)
@@ -341,6 +341,7 @@
     macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
     macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
+    macro(CheckFunction, NodeMustGenerate) \
     \
     /* Optimizations for array mutation. */\
     macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
@@ -807,7 +808,18 @@
         ASSERT(hasMethodCheckData());
         return m_opInfo2;
     }
-    
+
+    bool hasFunctionCheckData()
+    {
+        return op == CheckFunction;
+    }
+
+    JSFunction* function()
+    {
+        ASSERT(hasFunctionCheckData());
+        return reinterpret_cast<JSFunction*>(m_opInfo);
+    }
+
     bool hasStructureTransitionData()
     {
         return op == PutStructure;

Modified: trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -587,6 +587,7 @@
         case PutById:
         case PutByIdDirect:
         case CheckStructure:
+        case CheckFunction:
         case PutStructure:
         case PutByOffset:
             break;
@@ -984,7 +985,7 @@
         }
         return NoNode;
     }
-    
+
     NodeIndex getMethodLoadElimination(const MethodCheckData& methodCheckData, unsigned identifierNumber, NodeIndex child1)
     {
         NodeIndex start = startIndexForChildren(child1);
@@ -1022,7 +1023,27 @@
         }
         return NoNode;
     }
-    
+
+    bool checkFunctionElimination(JSFunction* function, NodeIndex child1)
+    {
+        NodeIndex start = startIndexForChildren(child1);
+        for (NodeIndex index = m_compileIndex; index-- > start;) {
+            Node& node = m_graph[index];
+            switch (node.op) {
+            case CheckFunction:
+                if (node.child1() == child1 && node.function() == function)
+                    return true;
+                break;
+                
+            default:
+                if (clobbersWorld(index))
+                    return false;
+                break;
+            }
+        }
+        return false;
+    }
+
     bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1)
     {
         NodeIndex start = startIndexForChildren(child1);
@@ -1308,7 +1329,12 @@
             if (checkStructureLoadElimination(node.structureSet(), node.child1()))
                 eliminate();
             break;
-            
+
+        case CheckFunction:
+            if (checkFunctionElimination(node.function(), node.child1()))
+                eliminate();
+            break;
+
         case GetPropertyStorage:
             setReplacement(getPropertyStorageLoadElimination(node.child1()));
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -1943,6 +1943,13 @@
         break;
     }
 
+    case CheckFunction: {
+        SpeculateCellOperand function(this, node.child1());
+        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, function.gpr(), JITCompiler::TrustedImmPtr(node.function())));
+        noResult(m_compileIndex);
+        break;
+    }
+
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
         

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -2007,7 +2007,12 @@
         integerResult(resultGPR, m_compileIndex);
         break;
     }
-
+    case CheckFunction: {
+        SpeculateCellOperand function(this, node.child1());
+        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, function.gpr(), JITCompiler::TrustedImmPtr(node.function())));
+        noResult(m_compileIndex);
+        break;
+    }
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
         

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -678,6 +678,7 @@
     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
         info.isCall = m_callStructureStubCompilationInfo[i].isCall;
+        info.bytecodeIndex = m_callStructureStubCompilationInfo[i].bytecodeIndex;
         info.callReturnLocation = CodeLocationLabel(patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation));
         info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
         info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);

Modified: trunk/Source/_javascript_Core/jit/JIT.h (96961 => 96962)


--- trunk/Source/_javascript_Core/jit/JIT.h	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2011-10-07 18:39:45 UTC (rev 96962)
@@ -165,6 +165,7 @@
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
         bool isCall;
+        unsigned bytecodeIndex;
     };
 
     struct MethodCallCompilationInfo {

Modified: trunk/Source/_javascript_Core/jit/JITCall.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/jit/JITCall.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/jit/JITCall.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -138,6 +138,7 @@
     m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
     m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
 
     // The following is the fast case, only used whan a callee can be linked.
 

Modified: trunk/Source/_javascript_Core/jit/JITCall32_64.cpp (96961 => 96962)


--- trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2011-10-07 18:16:03 UTC (rev 96961)
+++ trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2011-10-07 18:39:45 UTC (rev 96962)
@@ -223,6 +223,7 @@
     m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
     m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeIndex;
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to