Title: [136276] trunk/Source/_javascript_Core
Revision
136276
Author
[email protected]
Date
2012-11-30 13:56:24 -0800 (Fri, 30 Nov 2012)

Log Message

Rationalize and clean up DFG handling of scoped accesses
https://bugs.webkit.org/show_bug.cgi?id=103715

Reviewed by Oliver Hunt.

Previously, we had a GetScope node that specified the depth to which you wanted
to travel to get a JSScope, and the backend implementation of the node would
perform all of the necessary footwork, including potentially skipping the top
scope if necessary, and doing however many loads were needed. But there were
strange things. First, if you had accesses at different scope depths, then the
loads to get to the common depth could not be CSE'd - CSE would match only
GetScope's that had identical depth. Second, GetScope would be emitted even if
we already had the scope, for example in put_to_base. And finally, even though
the ResolveOperations could tell us whether or not we had to skip the top scope,
the backend would recompute this information itself, often pessimistically.
        
This eliminates GetScope and replaces it with the following:
        
GetMyScope: just get the JSScope from the call frame header. This will forever
mean getting the JSScope associated with the machine call frame; it will not
mean getting the scope of an inlined function. Or at least that's the intent.
        
SkipTopScope: check if there is an activation, and if so, skip a scope. This
takes a scope as a child and returns a scope.
        
SkipScope: skip one scope level.
        
The bytecode parser now emits the right combination of the above, and
potentially emits multiple SkipScope's, based on the ResolveOperations.
        
This change also includes some fixups to debug logging. We now always print
the ExecutableBase* in addition to the CodeBlock* in the CodeBlock's dump,
and we are now more verbose when dumping CodeOrigins and InlineCallFrames.
        
This is performance-neutral. It's just meant to be a clean-up.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpAssumingJITType):
* bytecode/CodeOrigin.cpp:
(JSC::CodeOrigin::inlineStack):
(JSC::CodeOrigin::dump):
(JSC):
(JSC::InlineCallFrame::dump):
* bytecode/CodeOrigin.h:
(CodeOrigin):
(InlineCallFrame):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGByteCodeParser.cpp:
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::getScope):
(DFG):
(JSC::DFG::ByteCodeParser::parseResolveOperations):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::scopedVarLoadElimination):
(JSC::DFG::CSEPhase::scopedVarStoreElimination):
(JSC::DFG::CSEPhase::getMyScopeLoadElimination):
(JSC::DFG::CSEPhase::setLocalStoreElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGDisassembler.cpp:
(JSC::DFG::Disassembler::dump):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dumpCodeOrigin):
(JSC::DFG::Graph::dumpBlockHeader):
* dfg/DFGNode.h:
(Node):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JITDisassembler.cpp:
(JSC::JITDisassembler::dump):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (136275 => 136276)


--- trunk/Source/_javascript_Core/ChangeLog	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-11-30 21:56:24 UTC (rev 136276)
@@ -1,3 +1,83 @@
+2012-11-30  Filip Pizlo  <[email protected]>
+
+        Rationalize and clean up DFG handling of scoped accesses
+        https://bugs.webkit.org/show_bug.cgi?id=103715
+
+        Reviewed by Oliver Hunt.
+
+        Previously, we had a GetScope node that specified the depth to which you wanted
+        to travel to get a JSScope, and the backend implementation of the node would
+        perform all of the necessary footwork, including potentially skipping the top
+        scope if necessary, and doing however many loads were needed. But there were
+        strange things. First, if you had accesses at different scope depths, then the
+        loads to get to the common depth could not be CSE'd - CSE would match only
+        GetScope's that had identical depth. Second, GetScope would be emitted even if
+        we already had the scope, for example in put_to_base. And finally, even though
+        the ResolveOperations could tell us whether or not we had to skip the top scope,
+        the backend would recompute this information itself, often pessimistically.
+        
+        This eliminates GetScope and replaces it with the following:
+        
+        GetMyScope: just get the JSScope from the call frame header. This will forever
+        mean getting the JSScope associated with the machine call frame; it will not
+        mean getting the scope of an inlined function. Or at least that's the intent.
+        
+        SkipTopScope: check if there is an activation, and if so, skip a scope. This
+        takes a scope as a child and returns a scope.
+        
+        SkipScope: skip one scope level.
+        
+        The bytecode parser now emits the right combination of the above, and
+        potentially emits multiple SkipScope's, based on the ResolveOperations.
+        
+        This change also includes some fixups to debug logging. We now always print
+        the ExecutableBase* in addition to the CodeBlock* in the CodeBlock's dump,
+        and we are now more verbose when dumping CodeOrigins and InlineCallFrames.
+        
+        This is performance-neutral. It's just meant to be a clean-up.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpAssumingJITType):
+        * bytecode/CodeOrigin.cpp:
+        (JSC::CodeOrigin::inlineStack):
+        (JSC::CodeOrigin::dump):
+        (JSC):
+        (JSC::InlineCallFrame::dump):
+        * bytecode/CodeOrigin.h:
+        (CodeOrigin):
+        (InlineCallFrame):
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGByteCodeParser.cpp:
+        (ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::getScope):
+        (DFG):
+        (JSC::DFG::ByteCodeParser::parseResolveOperations):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::scopedVarLoadElimination):
+        (JSC::DFG::CSEPhase::scopedVarStoreElimination):
+        (JSC::DFG::CSEPhase::getMyScopeLoadElimination):
+        (JSC::DFG::CSEPhase::setLocalStoreElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGDisassembler.cpp:
+        (JSC::DFG::Disassembler::dump):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dumpCodeOrigin):
+        (JSC::DFG::Graph::dumpBlockHeader):
+        * dfg/DFGNode.h:
+        (Node):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JITDisassembler.cpp:
+        (JSC::JITDisassembler::dump):
+
 2012-11-30  Oliver Hunt  <[email protected]>
 
         Add direct string->function code cache

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -69,7 +69,7 @@
 
 void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
 {
-    out.print("#", hash(), ":[", RawPointer(this), ", ", jitType, codeType());
+    out.print("#", hash(), ":[", RawPointer(this), "->", RawPointer(ownerExecutable()), ", ", jitType, codeType());
     if (codeType() == FunctionCode)
         out.print(specializationKind());
     out.print("]");

Modified: trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/bytecode/CodeOrigin.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -50,13 +50,33 @@
     unsigned index = result.size() - 2;
     for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
         result[index--] = current->caller;
+    ASSERT(!result[0].inlineCallFrame);
     return result;
 }
 
+void CodeOrigin::dump(PrintStream& out) const
+{
+    Vector<CodeOrigin> stack = inlineStack();
+    for (unsigned i = 0; i < stack.size(); ++i) {
+        if (i)
+            out.print(" --> ");
+        
+        if (InlineCallFrame* frame = stack[i].inlineCallFrame)
+            out.print("#", frame->hash(), ":<", RawPointer(frame->executable.get()), "> ");
+        
+        out.print("bc#", stack[i].bytecodeIndex);
+    }
+}
+
 CodeBlockHash InlineCallFrame::hash() const
 {
     return executable->hashFor(specializationKind());
 }
 
+void InlineCallFrame::dump(PrintStream& out) const
+{
+    out.print("#", hash(), ":<", RawPointer(executable.get()), ", bc#", caller.bytecodeIndex, ", ", specializationKind(), ">");
+}
+
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/bytecode/CodeOrigin.h (136275 => 136276)


--- trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	2012-11-30 21:56:24 UTC (rev 136276)
@@ -31,6 +31,7 @@
 #include "ValueRecovery.h"
 #include "WriteBarrier.h"
 #include <wtf/BitVector.h>
+#include <wtf/PrintStream.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
 
@@ -90,6 +91,8 @@
     
     // Get the inline stack. This is slow, and is intended for debugging only.
     Vector<CodeOrigin> inlineStack() const;
+    
+    void dump(PrintStream&) const;
 };
 
 struct InlineCallFrame {
@@ -104,6 +107,8 @@
     CodeSpecializationKind specializationKind() const { return specializationFromIsCall(isCall); }
     
     CodeBlockHash hash() const;
+    
+    void dump(PrintStream&) const;
 };
 
 struct CodeOriginAtCallReturnOffset {

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -1383,7 +1383,9 @@
         forNode(nodeIndex).set(SpecFunction);
         break;
             
-    case GetScope:
+    case GetMyScope:
+    case SkipTopScope:
+    case SkipScope:
         node.setCanExit(false);
         forNode(nodeIndex).set(SpecCellOther);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -176,6 +176,8 @@
         int destinationOperand, SpeculatedType, NodeIndex base, unsigned identifierNumber,
         const GetByIdStatus&);
 
+    NodeIndex getScope(bool skipTop, unsigned skipCount);
+    
     // Convert a set of ResolveOperations into graph nodes
     bool parseResolveOperations(SpeculatedType, unsigned identifierNumber, unsigned operations, unsigned putToBaseOperation, NodeIndex* base, NodeIndex* value);
 
@@ -1882,6 +1884,16 @@
     m_cellConstantNodes.clear();
 }
 
+NodeIndex ByteCodeParser::getScope(bool skipTop, unsigned skipCount)
+{
+    NodeIndex localBase = addToGraph(GetMyScope);
+    if (skipTop)
+        localBase = addToGraph(SkipTopScope, localBase);
+    for (unsigned n = skipCount; n--;)
+        localBase = addToGraph(SkipScope, localBase);
+    return localBase;
+}
+
 bool ByteCodeParser::parseResolveOperations(SpeculatedType prediction, unsigned identifier, unsigned operations, unsigned putToBaseOperation, NodeIndex* base, NodeIndex* value)
 {
     ResolveOperations* resolveOperations = m_codeBlock->resolveOperations(operations);
@@ -1891,6 +1903,7 @@
     }
     JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
     int skipCount = 0;
+    bool skipTop = false;
     bool skippedScopes = false;
     bool setBase = false;
     ResolveOperation* pc = resolveOperations->data();
@@ -1918,7 +1931,7 @@
             break;
 
         case ResolveOperation::SetBaseToScope:
-            localBase = addToGraph(GetScope, OpInfo(skipCount));
+            localBase = getScope(skipTop, skipCount);
             *base = localBase;
             setBase = true;
 
@@ -1929,21 +1942,19 @@
             ++pc;
             break;
         case ResolveOperation::ReturnScopeAsBase:
-            *base = addToGraph(GetScope, OpInfo(skipCount));
+            *base = getScope(skipTop, skipCount);
             ASSERT(!value);
             return true;
 
         case ResolveOperation::SkipTopScopeNode:
-            if (m_inlineStackTop->m_inlineCallFrame)
-                return false;
-            skipCount = 1;
+            ASSERT(!m_inlineStackTop->m_inlineCallFrame);
+            skipTop = true;
             skippedScopes = true;
             ++pc;
             break;
 
         case ResolveOperation::SkipScopes:
-            if (m_inlineStackTop->m_inlineCallFrame)
-                return false;
+            ASSERT(!m_inlineStackTop->m_inlineCallFrame);
             skipCount += pc->m_scopesToSkip;
             skippedScopes = true;
             ++pc;
@@ -1960,7 +1971,7 @@
         }
     }
     if (skippedScopes)
-        localBase = addToGraph(GetScope, OpInfo(skipCount));
+        localBase = getScope(skipTop, skipCount);
 
     if (base && !setBase)
         *base = localBase;
@@ -3050,10 +3061,9 @@
                            get(value));
                 break;
             case PutToBaseOperation::VariablePut: {
-                addToGraph(Phantom, get(base));
-                NodeIndex getScope = addToGraph(GetScope, OpInfo(putToBase->m_scopeDepth));
-                NodeIndex getScopeRegisters = addToGraph(GetScopeRegisters, getScope);
-                addToGraph(PutScopedVar, OpInfo(putToBase->m_offset), getScope, getScopeRegisters, get(value));
+                NodeIndex scope = get(base);
+                NodeIndex scopeRegisters = addToGraph(GetScopeRegisters, scope);
+                addToGraph(PutScopedVar, OpInfo(putToBase->m_offset), scope, scopeRegisters, get(value));
                 break;
             }
             case PutToBaseOperation::GlobalPropertyPut: {

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -213,7 +213,7 @@
         return NoNode;
     }
     
-    NodeIndex scopedVarLoadElimination(unsigned scopeChainDepth, unsigned varNumber)
+    NodeIndex scopedVarLoadElimination(NodeIndex registers, unsigned varNumber)
     {
         for (unsigned i = m_indexInBlock; i--;) {
             NodeIndex index = m_currentBlock->at(i);
@@ -222,15 +222,12 @@
                 continue;
             switch (node.op()) {
             case GetScopedVar: {
-                Node& getScopeRegisters = m_graph[node.child1()];
-                Node& getScope = m_graph[getScopeRegisters.child1()];
-                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                if (node.child1() == registers && node.varNumber() == varNumber)
                     return index;
                 break;
             } 
             case PutScopedVar: {
-                Node& getScope = m_graph[node.child1()];
-                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                if (node.child2() == registers && node.varNumber() == varNumber)
                     return node.child3().index();
                 break;
             }
@@ -296,7 +293,7 @@
         return NoNode;
     }
     
-    NodeIndex scopedVarStoreElimination(unsigned scopeChainDepth, unsigned varNumber)
+    NodeIndex scopedVarStoreElimination(NodeIndex scope, NodeIndex registers, unsigned varNumber)
     {
         for (unsigned i = m_indexInBlock; i--;) {
             NodeIndex index = m_currentBlock->at(i);
@@ -305,16 +302,14 @@
                 continue;
             switch (node.op()) {
             case PutScopedVar: {
-                Node& getScope = m_graph[node.child1()];
-                if (getScope.scopeChainDepth() == scopeChainDepth && node.varNumber() == varNumber)
+                if (node.child1() == scope && node.child2() == registers && 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)
+                // Let's be conservative.
+                if (node.varNumber() == varNumber)
                     return NoNode;
                 break;
             }
@@ -779,33 +774,25 @@
         return NoNode;
     }
     
-    NodeIndex getScopeLoadElimination(unsigned depth)
+    NodeIndex getMyScopeLoadElimination()
     {
-        for (unsigned i = endIndexForPureCSE(); i--;) {
+        for (unsigned i = m_indexInBlock; i--;) {
             NodeIndex index = m_currentBlock->at(i);
             Node& node = m_graph[index];
             if (!node.shouldGenerate())
                 continue;
-            if (node.op() == GetScope
-                && node.scopeChainDepth() == depth)
+            switch (node.op()) {
+            case CreateActivation:
+                // This may cause us to return a different scope.
+                return NoNode;
+            case GetMyScope:
                 return index;
+            default:
+                break;
+            }
         }
         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)
     {
@@ -890,7 +877,8 @@
                 return result;
             }
                 
-            case GetScope:
+            case GetMyScope:
+            case SkipTopScope:
             case GetScopeRegisters:
                 if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
                     result.mayBeAccessed = true;
@@ -1076,6 +1064,9 @@
         case IsFunction:
         case DoubleAsInt32:
         case LogicalNot:
+        case SkipTopScope:
+        case SkipScope:
+        case GetScopeRegisters:
             setReplacement(pureCSE(node));
             break;
             
@@ -1189,14 +1180,10 @@
             setReplacement(getArrayLengthElimination(node.child1().index()));
             break;
 
-        case GetScope:
-            setReplacement(getScopeLoadElimination(node.scopeChainDepth()));
+        case GetMyScope:
+            setReplacement(getMyScopeLoadElimination());
             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:
@@ -1220,9 +1207,7 @@
             break;
 
         case GetScopedVar: {
-            Node& getScopeRegisters = m_graph[node.child1()];
-            Node& getScope = m_graph[getScopeRegisters.child1()];
-            setReplacement(scopedVarLoadElimination(getScope.scopeChainDepth(), node.varNumber()));
+            setReplacement(scopedVarLoadElimination(node.child1().index(), node.varNumber()));
             break;
         }
 
@@ -1241,8 +1226,7 @@
         case PutScopedVar: {
             if (m_graph.m_fixpointState == FixpointNotConverged)
                 break;
-            Node& getScope = m_graph[node.child1()];
-            eliminate(scopedVarStoreElimination(getScope.scopeChainDepth(), node.varNumber()));
+            eliminate(scopedVarStoreElimination(node.child1().index(), node.child2().index(), node.varNumber()));
             break;
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGDisassembler.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGDisassembler.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGDisassembler.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -44,7 +44,7 @@
 {
     m_graph.m_dominators.computeIfNecessary(m_graph);
     
-    out.print("Generated JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n");
+    out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n");
     out.print("    Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n");
     
     const char* prefix = "    ";

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -88,14 +88,14 @@
     for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) {
         out.print(prefix);
         printWhiteSpace(out, i * 2);
-        out.print("<-- #", previousInlineStack[i].inlineCallFrame->hash(), "\n");
+        out.print("<-- ", *previousInlineStack[i].inlineCallFrame, "\n");
     }
     
     // Print the pushes.
     for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) {
         out.print(prefix);
         printWhiteSpace(out, i * 2);
-        out.print("--> #", currentInlineStack[i].inlineCallFrame->hash(), "\n");
+        out.print("--> ", *currentInlineStack[i].inlineCallFrame, "\n");
     }
 }
 
@@ -294,7 +294,7 @@
 {
     BasicBlock* block = m_blocks[blockIndex].get();
 
-    out.print(prefix, "Block #", blockIndex, " (bc#", block->bytecodeBegin, "): ", block->isReachable ? "" : "(skipped)", block->isOSRTarget ? " (OSR target)" : "", "\n");
+    out.print(prefix, "Block #", blockIndex, " (", at(block->at(0)).codeOrigin, "): ", block->isReachable ? "" : "(skipped)", block->isOSRTarget ? " (OSR target)" : "", "\n");
     out.print(prefix, "  Predecessors:");
     for (size_t i = 0; i < block->m_predecessors.size(); ++i)
         out.print(" #", block->m_predecessors[i]);

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2012-11-30 21:56:24 UTC (rev 136276)
@@ -523,23 +523,6 @@
         return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
     }
 
-    bool hasScopeChainDepth()
-    {
-        return op() == GetScope;
-    }
-    
-    unsigned scopeChainDepth()
-    {
-        ASSERT(hasScopeChainDepth());
-        return m_opInfo;
-    }
-
-    Edge scope()
-    {
-        ASSERT(op() == GetScopeRegisters);
-        return child1();
-    }
-
     bool hasResult()
     {
         return m_flags & NodeResultMask;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-11-30 21:56:24 UTC (rev 136276)
@@ -150,7 +150,9 @@
     macro(GetByOffset, NodeResultJS) \
     macro(PutByOffset, NodeMustGenerate) \
     macro(GetArrayLength, NodeResultInt32) \
-    macro(GetScope, NodeResultJS) \
+    macro(GetMyScope, NodeResultJS) \
+    macro(SkipTopScope, NodeResultJS) \
+    macro(SkipScope, NodeResultJS) \
     macro(GetScopeRegisters, NodeResultStorage) \
     macro(GetScopedVar, NodeResultJS) \
     macro(PutScopedVar, NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -594,7 +594,9 @@
             break;
         }
             
-        case GetScope: {
+        case GetMyScope:
+        case SkipTopScope:
+        case SkipScope: {
             changed |= setPrediction(SpecCellOther);
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -3967,32 +3967,44 @@
 
     case GetCallee: {
         GPRTemporary result(this);
-        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::Callee)), result.gpr());
+        m_jit.loadPtr(JITCompiler::payloadFor(static_cast<VirtualRegister>(JSStack::Callee)), result.gpr());
         cellResult(result.gpr(), m_compileIndex);
         break;
     }
-
-    case GetScope: {
+        
+    case GetMyScope: {
         GPRTemporary result(this);
         GPRReg resultGPR = result.gpr();
 
-        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::ScopeChain)), resultGPR);
-        bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
-        int skip = node.scopeChainDepth();
-        ASSERT(skip || !checkTopLevel);
-        if (checkTopLevel && skip--) {
-            JITCompiler::Jump activationNotCreated;
-            if (checkTopLevel)
-                activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
-            m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
-            activationNotCreated.link(&m_jit);
-        }
-        while (skip--)
-            m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
+        m_jit.loadPtr(JITCompiler::payloadFor(static_cast<VirtualRegister>(JSStack::ScopeChain)), resultGPR);
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
         
+    case SkipTopScope: {
+        SpeculateCellOperand scope(this, node.child1());
+        GPRTemporary result(this, scope);
+        GPRReg resultGPR = result.gpr();
+        m_jit.move(scope.gpr(), resultGPR);
+        JITCompiler::Jump activationNotCreated =
+            m_jit.branchTestPtr(
+                JITCompiler::Zero,
+                JITCompiler::payloadFor(
+                    static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
+        activationNotCreated.link(&m_jit);
         cellResult(resultGPR, m_compileIndex);
         break;
     }
+        
+    case SkipScope: {
+        SpeculateCellOperand scope(this, node.child1());
+        GPRTemporary result(this, scope);
+        m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSScope::offsetOfNext()), result.gpr());
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
     case GetScopeRegisters: {
         SpeculateCellOperand scope(this, node.child1());
         GPRTemporary result(this);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -3923,28 +3923,40 @@
         cellResult(result.gpr(), m_compileIndex);
         break;
     }
-
-    case GetScope: {
+        
+    case GetMyScope: {
         GPRTemporary result(this);
         GPRReg resultGPR = result.gpr();
 
         m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(JSStack::ScopeChain)), resultGPR);
-        bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
-        int skip = node.scopeChainDepth();
-        ASSERT(skip || !checkTopLevel);
-        if (checkTopLevel && skip--) {
-            JITCompiler::Jump activationNotCreated;
-            if (checkTopLevel)
-                activationNotCreated = m_jit.branchTest64(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
-            m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
-            activationNotCreated.link(&m_jit);
-        }
-        while (skip--)
-            m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
         
+    case SkipTopScope: {
+        SpeculateCellOperand scope(this, node.child1());
+        GPRTemporary result(this, scope);
+        GPRReg resultGPR = result.gpr();
+        m_jit.move(scope.gpr(), resultGPR);
+        JITCompiler::Jump activationNotCreated =
+            m_jit.branchTest64(
+                JITCompiler::Zero,
+                JITCompiler::addressFor(
+                    static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR);
+        activationNotCreated.link(&m_jit);
         cellResult(resultGPR, m_compileIndex);
         break;
     }
+        
+    case SkipScope: {
+        SpeculateCellOperand scope(this, node.child1());
+        GPRTemporary result(this, scope);
+        m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSScope::offsetOfNext()), result.gpr());
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
     case GetScopeRegisters: {
         SpeculateCellOperand scope(this, node.child1());
         GPRTemporary result(this);

Modified: trunk/Source/_javascript_Core/jit/JITDisassembler.cpp (136275 => 136276)


--- trunk/Source/_javascript_Core/jit/JITDisassembler.cpp	2012-11-30 21:54:51 UTC (rev 136275)
+++ trunk/Source/_javascript_Core/jit/JITDisassembler.cpp	2012-11-30 21:56:24 UTC (rev 136276)
@@ -47,7 +47,7 @@
 
 void JITDisassembler::dump(PrintStream& out, LinkBuffer& linkBuffer)
 {
-    out.print("Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT), ", instruction count = ", m_codeBlock->instructionCount(), "\n");
+    out.print("Generated Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT), ", instruction count = ", m_codeBlock->instructionCount(), "\n");
     out.print("   Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n");
     dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]);
     
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to