Title: [129316] trunk/Source/_javascript_Core
Revision
129316
Author
[email protected]
Date
2012-09-23 15:48:19 -0700 (Sun, 23 Sep 2012)

Log Message

CSE for access to closure variables (get_/put_scoped_var)
https://bugs.webkit.org/show_bug.cgi?id=97414

Reviewed by Oliver Hunt.

I separated loading a scope from loading its storage pointer, so we can
CSE the storage pointer load. Then, I copied the global var CSE and adjusted
it for closure vars.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute): Renamed GetScopeChain => GetScope to
reflect renames from a few weeks ago.

Added a case for the storage pointer load, similar to object storage pointer load.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock): Added an independent node for
the storage pointer.

* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::scopedVarLoadElimination):
(CSEPhase):
(JSC::DFG::CSEPhase::scopedVarStoreElimination):
(JSC::DFG::CSEPhase::getScopeLoadElimination):
(JSC::DFG::CSEPhase::getScopeRegistersLoadElimination):
(JSC::DFG::CSEPhase::setLocalStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE): Copied globalVarLoad/StoreElimination
and adapted the same logic to closure vars.

* dfg/DFGNode.h:
(JSC::DFG::Node::hasScopeChainDepth):
(JSC::DFG::Node::scope):
(Node):
* dfg/DFGNodeType.h:
(DFG): GetScopedVar and GetGlobalVar are no longer MustGenerate. I'm not
sure why they ever were. But these are simple load operations so, if they're
unused, they're truly dead.

* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile): Updated for renames and split-out
node for getting the storage pointer.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (129315 => 129316)


--- trunk/Source/_javascript_Core/ChangeLog	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-09-23 22:48:19 UTC (rev 129316)
@@ -1,3 +1,51 @@
+2012-09-23  Geoffrey Garen  <[email protected]>
+
+        CSE for access to closure variables (get_/put_scoped_var)
+        https://bugs.webkit.org/show_bug.cgi?id=97414
+
+        Reviewed by Oliver Hunt.
+
+        I separated loading a scope from loading its storage pointer, so we can
+        CSE the storage pointer load. Then, I copied the global var CSE and adjusted
+        it for closure vars.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute): Renamed GetScopeChain => GetScope to
+        reflect renames from a few weeks ago.
+
+        Added a case for the storage pointer load, similar to object storage pointer load.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock): Added an independent node for
+        the storage pointer.
+
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::scopedVarLoadElimination):
+        (CSEPhase):
+        (JSC::DFG::CSEPhase::scopedVarStoreElimination):
+        (JSC::DFG::CSEPhase::getScopeLoadElimination):
+        (JSC::DFG::CSEPhase::getScopeRegistersLoadElimination):
+        (JSC::DFG::CSEPhase::setLocalStoreElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE): Copied globalVarLoad/StoreElimination
+        and adapted the same logic to closure vars.
+
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasScopeChainDepth):
+        (JSC::DFG::Node::scope):
+        (Node):
+        * dfg/DFGNodeType.h:
+        (DFG): GetScopedVar and GetGlobalVar are no longer MustGenerate. I'm not
+        sure why they ever were. But these are simple load operations so, if they're
+        unused, they're truly dead.
+
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile): Updated for renames and split-out
+        node for getting the storage pointer.
+
 2012-09-21  Geoffrey Garen  <[email protected]>
 
         Unreviewed, rolled out a line I committed by accident.

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -1262,11 +1262,17 @@
         forNode(nodeIndex).set(SpecFunction);
         break;
             
-    case GetScopeChain:
+    case GetScope:
         node.setCanExit(false);
         forNode(nodeIndex).set(SpecCellOther);
         break;
-            
+
+    case GetScopeRegisters:
+        node.setCanExit(false);
+        forNode(node.child1()).filter(SpecCell);
+        forNode(nodeIndex).clear(); // The result is not a JS value.
+        break;
+
     case GetScopedVar:
         node.setCanExit(false);
         forNode(nodeIndex).makeTop();

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -2265,8 +2265,9 @@
             int dst = currentInstruction[1].u.operand;
             int slot = currentInstruction[2].u.operand;
             int depth = currentInstruction[3].u.operand;
-            NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
-            NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
+            NodeIndex getScope = addToGraph(GetScope, OpInfo(depth));
+            NodeIndex getScopeRegisters = addToGraph(GetScopeRegisters, getScope);
+            NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeRegisters);
             set(dst, getScopedVar);
             NEXT_OPCODE(op_get_scoped_var);
         }
@@ -2274,8 +2275,9 @@
             int slot = currentInstruction[1].u.operand;
             int depth = currentInstruction[2].u.operand;
             int source = currentInstruction[3].u.operand;
-            NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
-            addToGraph(PutScopedVar, OpInfo(slot), getScopeChain, get(source));
+            NodeIndex getScope = addToGraph(GetScope, OpInfo(depth));
+            NodeIndex getScopeRegisters = addToGraph(GetScopeRegisters, getScope);
+            addToGraph(PutScopedVar, OpInfo(slot), getScope, getScopeRegisters, get(source));
             NEXT_OPCODE(op_put_scoped_var);
         }
         case op_get_by_id:

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -215,6 +215,34 @@
         return NoNode;
     }
     
+    NodeIndex scopedVarLoadElimination(unsigned scopeChainDepth, unsigned varNumber)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetScopedVar: {
+                Node& getScopeRegisters = m_graph[node.child1()];
+                Node& getScope = m_graph[getScopeRegisters.child1()];
+                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                    return index;
+                break;
+            } 
+            case PutScopedVar: {
+                Node& getScope = m_graph[node.child1()];
+                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                    return node.child3().index();
+                break;
+            }
+            default:
+                break;
+            }
+            if (m_graph.clobbersWorld(index))
+                break;
+        }
+        return NoNode;
+    }
+    
     bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer)
     {
         for (unsigned i = m_indexInBlock; i--;) {
@@ -266,6 +294,38 @@
         return NoNode;
     }
     
+    NodeIndex scopedVarStoreElimination(unsigned scopeChainDepth, unsigned varNumber)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            Node& node = m_graph[index];
+            if (!node.shouldGenerate())
+                continue;
+            switch (node.op()) {
+            case PutScopedVar: {
+                Node& getScope = m_graph[node.child1()];
+                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                    return index;
+                break;
+            }
+                
+            case GetScopedVar: {
+                Node& getScopeRegisters = m_graph[node.child1()];
+                Node& getScope = m_graph[getScopeRegisters.child1()];
+                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                    return NoNode;
+                break;
+            }
+
+            default:
+                break;
+            }
+            if (m_graph.clobbersWorld(index) || node.canExit())
+                return NoNode;
+        }
+        return NoNode;
+    }
+    
     NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2)
     {
         for (unsigned i = m_indexInBlock; i--;) {
@@ -689,19 +749,35 @@
         return NoNode;
     }
     
-    NodeIndex getScopeChainLoadElimination(unsigned depth)
+    NodeIndex getScopeLoadElimination(unsigned depth)
     {
         for (unsigned i = endIndexForPureCSE(); i--;) {
             NodeIndex index = m_currentBlock->at(i);
             Node& node = m_graph[index];
             if (!node.shouldGenerate())
                 continue;
-            if (node.op() == GetScopeChain
+            if (node.op() == GetScope
                 && node.scopeChainDepth() == depth)
                 return index;
         }
         return NoNode;
     }
+
+    NodeIndex getScopeRegistersLoadElimination(unsigned depth)
+    {
+        for (unsigned i = endIndexForPureCSE(); i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            Node& node = m_graph[index];
+            if (!node.shouldGenerate())
+                continue;
+            if (node.op() == GetScopeRegisters
+                && m_graph[node.scope()].scopeChainDepth() == depth)
+                return index;
+        }
+        return NoNode;
+    }
+
+
     
     NodeIndex getLocalLoadElimination(VirtualRegister local, NodeIndex& relevantLocalOp, bool careAboutClobbering)
     {
@@ -786,7 +862,8 @@
                 return result;
             }
                 
-            case GetScopeChain:
+            case GetScope:
+            case GetScopeRegisters:
                 if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
                     result.mayBeAccessed = true;
                 break;
@@ -1079,11 +1156,15 @@
         case GetArrayLength:
             setReplacement(getArrayLengthElimination(node.child1().index()));
             break;
-            
-        case GetScopeChain:
-            setReplacement(getScopeChainLoadElimination(node.scopeChainDepth()));
+
+        case GetScope:
+            setReplacement(getScopeLoadElimination(node.scopeChainDepth()));
             break;
 
+        case GetScopeRegisters:
+            setReplacement(getScopeRegistersLoadElimination(m_graph[node.scope()].scopeChainDepth()));
+            break;
+
         // Handle nodes that are conditionally pure: these are pure, and can
         // be CSE'd, so long as the prediction is the one we want.
         case ValueAdd:
@@ -1105,7 +1186,14 @@
         case GetGlobalVar:
             setReplacement(globalVarLoadElimination(node.registerPointer()));
             break;
-            
+
+        case GetScopedVar: {
+            Node& getScopeRegisters = m_graph[node.child1()];
+            Node& getScope = m_graph[getScopeRegisters.child1()];
+            setReplacement(scopedVarLoadElimination(getScope.scopeChainDepth(), node.varNumber()));
+            break;
+        }
+
         case GlobalVarWatchpoint:
             if (globalVarWatchpointElimination(node.registerPointer()))
                 eliminate();
@@ -1118,6 +1206,14 @@
             eliminate(globalVarStoreElimination(node.registerPointer()));
             break;
             
+        case PutScopedVar: {
+            if (m_graph.m_fixpointState == FixpointNotConverged)
+                break;
+            Node& getScope = m_graph[node.child1()];
+            eliminate(scopedVarStoreElimination(getScope.scopeChainDepth(), node.varNumber()));
+            break;
+        }
+
         case GetByVal:
             if (m_graph.byValIsPure(node))
                 setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index()));

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-09-23 22:48:19 UTC (rev 129316)
@@ -466,7 +466,7 @@
 
     bool hasScopeChainDepth()
     {
-        return op() == GetScopeChain;
+        return op() == GetScope;
     }
     
     unsigned scopeChainDepth()
@@ -475,6 +475,12 @@
         return m_opInfo;
     }
 
+    Edge scope()
+    {
+        ASSERT(op() == GetScopeRegisters);
+        return child1();
+    }
+
     bool hasResult()
     {
         return m_flags & NodeResultMask;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-09-23 22:48:19 UTC (rev 129316)
@@ -144,10 +144,11 @@
     macro(GetByOffset, NodeResultJS) \
     macro(PutByOffset, NodeMustGenerate) \
     macro(GetArrayLength, NodeResultInt32) \
-    macro(GetScopeChain, NodeResultJS) \
-    macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
+    macro(GetScope, NodeResultJS) \
+    macro(GetScopeRegisters, NodeResultStorage) \
+    macro(GetScopedVar, NodeResultJS) \
     macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
-    macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
+    macro(GetGlobalVar, NodeResultJS) \
     macro(PutGlobalVar, NodeMustGenerate) \
     macro(GlobalVarWatchpoint, NodeMustGenerate) \
     macro(PutGlobalVarCheck, NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -447,7 +447,8 @@
             changed |= setPrediction(SpecInt32);
             break;
         }
-            
+
+        case GetScopeRegisters:            
         case GetButterfly: 
         case GetIndexedPropertyStorage:
         case AllocatePropertyStorage:
@@ -509,7 +510,7 @@
             break;
         }
             
-        case GetScopeChain: {
+        case GetScope: {
             changed |= setPrediction(SpecCellOther);
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -3371,7 +3371,7 @@
         break;
     }
 
-    case GetScopeChain: {
+    case GetScope: {
         GPRTemporary result(this);
         GPRReg resultGPR = result.gpr();
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (129315 => 129316)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-09-23 17:37:15 UTC (rev 129315)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-09-23 22:48:19 UTC (rev 129316)
@@ -3380,7 +3380,7 @@
         break;
     }
 
-    case GetScopeChain: {
+    case GetScope: {
         GPRTemporary result(this);
         GPRReg resultGPR = result.gpr();
 
@@ -3401,23 +3401,39 @@
         cellResult(resultGPR, m_compileIndex);
         break;
     }
-    case GetScopedVar: {
+    case GetScopeRegisters: {
         SpeculateCellOperand scope(this, node.child1());
         GPRTemporary result(this);
+        GPRReg scopeGPR = scope.gpr();
         GPRReg resultGPR = result.gpr();
-        m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR);
-        m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
+
+        m_jit.loadPtr(JITCompiler::Address(scopeGPR, JSVariableObject::offsetOfRegisters()), resultGPR);
+        storageResult(resultGPR, m_compileIndex);
+        break;
+    }
+    case GetScopedVar: {
+        StorageOperand registers(this, node.child1());
+        GPRTemporary result(this);
+        GPRReg registersGPR = registers.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.loadPtr(JITCompiler::Address(registersGPR, node.varNumber() * sizeof(Register)), resultGPR);
         jsValueResult(resultGPR, m_compileIndex);
         break;
     }
     case PutScopedVar: {
         SpeculateCellOperand scope(this, node.child1());
+        StorageOperand registers(this, node.child2());
+        JSValueOperand value(this, node.child3());
         GPRTemporary scratchRegister(this);
+
+        GPRReg scopeGPR = scope.gpr();
+        GPRReg registersGPR = registers.gpr();
+        GPRReg valueGPR = value.gpr();
         GPRReg scratchGPR = scratchRegister.gpr();
-        m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
-        JSValueOperand value(this, node.child2());
-        m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register)));
-        writeBarrier(scope.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
+
+        m_jit.storePtr(valueGPR, JITCompiler::Address(registersGPR, node.varNumber() * sizeof(Register)));
+        writeBarrier(scopeGPR, valueGPR, node.child3(), WriteBarrierForVariableAccess, scratchGPR);
         noResult(m_compileIndex);
         break;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to