Title: [136546] trunk/Source/_javascript_Core
Revision
136546
Author
fpi...@apple.com
Date
2012-12-04 12:25:24 -0800 (Tue, 04 Dec 2012)

Log Message

DFG should inline code blocks that use scoped variable access
https://bugs.webkit.org/show_bug.cgi?id=103974

Reviewed by Oliver Hunt.

This mostly just turns on something we could have done all along, but also adds a few key
necessities to make this right:
        
1) Constant folding of SkipScope, since if we inline with a known JSFunction* then the
   scope is constant.
        
2) Interference analysis for GetLocal<->PutScopedVar and SetLocal<->GetScopedVar.
        
This is not meant to be a speed-up on major benchmarks since we don't yet inline most
closure calls for entirely unrelated reasons. But on toy programs it can be >2x faster.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getScope):
(JSC::DFG::ByteCodeParser::parseResolveOperations):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::scopedVarLoadElimination):
(JSC::DFG::CSEPhase::scopedVarStoreElimination):
(JSC::DFG::CSEPhase::getLocalLoadElimination):
(JSC::DFG::CSEPhase::setLocalStoreElimination):
* dfg/DFGCapabilities.h:
(JSC::DFG::canInlineResolveOperations):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (136545 => 136546)


--- trunk/Source/_javascript_Core/ChangeLog	2012-12-04 20:17:55 UTC (rev 136545)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-12-04 20:25:24 UTC (rev 136546)
@@ -1,5 +1,36 @@
 2012-12-03  Filip Pizlo  <fpi...@apple.com>
 
+        DFG should inline code blocks that use scoped variable access
+        https://bugs.webkit.org/show_bug.cgi?id=103974
+
+        Reviewed by Oliver Hunt.
+
+        This mostly just turns on something we could have done all along, but also adds a few key
+        necessities to make this right:
+        
+        1) Constant folding of SkipScope, since if we inline with a known JSFunction* then the
+           scope is constant.
+        
+        2) Interference analysis for GetLocal<->PutScopedVar and SetLocal<->GetScopedVar.
+        
+        This is not meant to be a speed-up on major benchmarks since we don't yet inline most
+        closure calls for entirely unrelated reasons. But on toy programs it can be >2x faster.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getScope):
+        (JSC::DFG::ByteCodeParser::parseResolveOperations):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::scopedVarLoadElimination):
+        (JSC::DFG::CSEPhase::scopedVarStoreElimination):
+        (JSC::DFG::CSEPhase::getLocalLoadElimination):
+        (JSC::DFG::CSEPhase::setLocalStoreElimination):
+        * dfg/DFGCapabilities.h:
+        (JSC::DFG::canInlineResolveOperations):
+
+2012-12-03  Filip Pizlo  <fpi...@apple.com>
+
         Replace JSValue::description() with JSValue::dump(PrintStream&)
         https://bugs.webkit.org/show_bug.cgi?id=103866
 

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (136545 => 136546)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-12-04 20:17:55 UTC (rev 136545)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-12-04 20:25:24 UTC (rev 136546)
@@ -1385,11 +1385,21 @@
             
     case GetMyScope:
     case SkipTopScope:
-    case SkipScope:
         node.setCanExit(false);
         forNode(nodeIndex).set(SpecCellOther);
         break;
 
+    case SkipScope: {
+        node.setCanExit(false);
+        JSValue child = forNode(node.child1()).value();
+        if (child && trySetConstant(nodeIndex, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {
+            m_foundConstants = true;
+            break;
+        }
+        forNode(nodeIndex).set(SpecCellOther);
+        break;
+    }
+
     case GetScopeRegisters:
         node.setCanExit(false);
         forNode(node.child1()).filter(SpecCell);

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (136545 => 136546)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-12-04 20:17:55 UTC (rev 136545)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-12-04 20:25:24 UTC (rev 136546)
@@ -1886,9 +1886,16 @@
 
 NodeIndex ByteCodeParser::getScope(bool skipTop, unsigned skipCount)
 {
-    NodeIndex localBase = addToGraph(GetMyScope);
-    if (skipTop)
+    NodeIndex localBase;
+    if (m_inlineStackTop->m_inlineCallFrame) {
+        ASSERT(m_inlineStackTop->m_inlineCallFrame->callee);
+        localBase = cellConstant(m_inlineStackTop->m_inlineCallFrame->callee->scope());
+    } else
+        localBase = addToGraph(GetMyScope);
+    if (skipTop) {
+        ASSERT(!m_inlineStackTop->m_inlineCallFrame);
         localBase = addToGraph(SkipTopScope, localBase);
+    }
     for (unsigned n = skipCount; n--;)
         localBase = addToGraph(SkipScope, localBase);
     return localBase;
@@ -1954,7 +1961,6 @@
             break;
 
         case ResolveOperation::SkipScopes:
-            ASSERT(!m_inlineStackTop->m_inlineCallFrame);
             skipCount += pc->m_scopesToSkip;
             skippedScopes = true;
             ++pc;

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (136545 => 136546)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-12-04 20:17:55 UTC (rev 136545)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-12-04 20:25:24 UTC (rev 136546)
@@ -236,6 +236,13 @@
                     return node.child3().index();
                 break;
             }
+            case SetLocal: {
+                VariableAccessData* variableAccessData = node.variableAccessData();
+                if (variableAccessData->isCaptured()
+                    && variableAccessData->local() == static_cast<VirtualRegister>(varNumber))
+                    return NoNode;
+                break;
+            }
             default:
                 break;
             }
@@ -318,6 +325,14 @@
                     return NoNode;
                 break;
             }
+                
+            case GetLocal: {
+                VariableAccessData* variableAccessData = node.variableAccessData();
+                if (variableAccessData->isCaptured()
+                    && variableAccessData->local() == static_cast<VirtualRegister>(varNumber))
+                    return NoNode;
+                break;
+            }
 
             default:
                 break;
@@ -830,6 +845,11 @@
                 }
                 break;
                 
+            case PutScopedVar:
+                if (static_cast<VirtualRegister>(node.varNumber()) == local)
+                    return NoNode;
+                break;
+                
             default:
                 if (careAboutClobbering && m_graph.clobbersWorld(index))
                     return NoNode;
@@ -882,9 +902,13 @@
                 return result;
             }
                 
+            case GetScopedVar:
+                if (static_cast<VirtualRegister>(node.varNumber()) == local)
+                    result.mayBeAccessed = true;
+                break;
+                
             case GetMyScope:
             case SkipTopScope:
-            case GetScopeRegisters:
                 if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
                     result.mayBeAccessed = true;
                 break;

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.h (136545 => 136546)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2012-12-04 20:17:55 UTC (rev 136545)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.h	2012-12-04 20:25:24 UTC (rev 136546)
@@ -82,6 +82,10 @@
         case ResolveOperation::GetAndReturnGlobalProperty:
         case ResolveOperation::GetAndReturnGlobalVar:
         case ResolveOperation::GetAndReturnGlobalVarWatchable:
+        case ResolveOperation::SkipScopes:
+        case ResolveOperation::SetBaseToScope:
+        case ResolveOperation::ReturnScopeAsBase:
+        case ResolveOperation::GetAndReturnScopedVar:
             continue;
 
         case ResolveOperation::Fail:
@@ -94,12 +98,8 @@
                 return false;
 
         case ResolveOperation::SkipTopScopeNode:
-        case ResolveOperation::SkipScopes:
-        case ResolveOperation::SetBaseToScope:
-        case ResolveOperation::ReturnScopeAsBase:
-        case ResolveOperation::GetAndReturnScopedVar:
-            // These opcodes would be easy to support with inlining, but we currently don't do it.
-            // The issue is that the scope chain will not be set correctly.
+            // We don't inline code blocks that create activations. Creation of
+            // activations is the only thing that leads to SkipTopScopeNode.
             return false;
 
         case ResolveOperation::CheckForDynamicEntriesBeforeGlobalScope:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to