Implement get_scoped_var in the DFG
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Sep 2011 18:51:02 +0000 (18:51 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Sep 2011 18:51:02 +0000 (18:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68640

Reviewed by Gavin Barraclough.

Naive implementation of get_scoped_var in the DFG.  Essentially this
is the bare minimum required to get correct behaviour, so there's no
load/store coalescing or type profiling involved, even though these
would be wins.  No impact on SunSpider or V8.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasVarNumber):
(JSC::DFG::Node::hasScopeChainDepth):
(JSC::DFG::Node::scopeChainDepth):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95742 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGPropagator.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

index c5c86f3..da6d288 100644 (file)
@@ -1,3 +1,28 @@
+2011-09-22  Oliver Hunt  <oliver@apple.com>
+
+        Implement get_scoped_var in the DFG
+        https://bugs.webkit.org/show_bug.cgi?id=68640
+
+        Reviewed by Gavin Barraclough.
+
+        Naive implementation of get_scoped_var in the DFG.  Essentially this
+        is the bare minimum required to get correct behaviour, so there's no
+        load/store coalescing or type profiling involved, even though these
+        would be wins.  No impact on SunSpider or V8.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.h:
+        (JSC::DFG::canCompileOpcode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasVarNumber):
+        (JSC::DFG::Node::hasScopeChainDepth):
+        (JSC::DFG::Node::scopeChainDepth):
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-09-22  Adam Roben  <aroben@apple.com>
 
         Remove FindSafari from all our .sln files
index 82737e9..8f457f2 100644 (file)
@@ -1081,7 +1081,14 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
             continue;
         }
-
+        case op_get_scoped_var: {
+            int dst = currentInstruction[1].u.operand;
+            int slot = currentInstruction[2].u.operand;
+            int depth = currentInstruction[3].u.operand;
+            NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(depth));
+            set(dst, getScopedVar);
+            NEXT_OPCODE(op_get_scoped_var);
+        }
         case op_get_by_id: {
             NodeIndex base = get(currentInstruction[2].u.operand);
             unsigned identifierNumber = currentInstruction[3].u.operand;
index 06ee321..bb39283 100644 (file)
@@ -82,6 +82,7 @@ inline bool canCompileOpcode(OpcodeID opcodeID)
     case op_get_by_val:
     case op_put_by_val:
     case op_method_check:
+    case op_get_scoped_var:
     case op_get_by_id:
     case op_put_by_id:
     case op_get_global_var:
index 80e90c5..c8a11b5 100644 (file)
@@ -268,6 +268,7 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
     macro(GetByOffset, NodeResultJS) \
     macro(GetMethod, NodeResultJS | NodeMustGenerate) \
     macro(CheckMethod, NodeResultJS | NodeMustGenerate) \
+    macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
     macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
     \
@@ -537,7 +538,7 @@ struct Node {
     
     bool hasVarNumber()
     {
-        return op == GetGlobalVar || op == PutGlobalVar;
+        return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar;
     }
 
     unsigned varNumber()
@@ -546,6 +547,17 @@ struct Node {
         return m_opInfo;
     }
 
+    bool hasScopeChainDepth()
+    {
+        return op == GetScopedVar;
+    }
+    
+    unsigned scopeChainDepth()
+    {
+        ASSERT(hasScopeChainDepth());
+        return m_opInfo2;
+    }
+
     bool hasResult()
     {
         return op & NodeResultMask;
index c624363..f3f267c 100644 (file)
@@ -560,6 +560,7 @@ private:
         case Resolve:
         case ResolveBase:
         case ResolveBaseStrictPut:
+        case GetScopedVar:
             break;
             
         // This gets ignored because it doesn't do anything.
index ee3e9fa..cf8c2e3 100644 (file)
@@ -1625,7 +1625,30 @@ void SpeculativeJIT::compile(Node& node)
         cellResult(result.gpr(), m_compileIndex);
         break;
     }
+    case GetScopedVar: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
 
+        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::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, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+            activationNotCreated.link(&m_jit);
+        }
+        while (skip--)
+            m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+        
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, JSVariableObject::offsetOfRegisters()), resultGPR);
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
     case GetById: {
         SpeculateCellOperand base(this, node.child1());
         GPRTemporary result(this, base);