Support string length in the DFG
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 1 Oct 2011 21:46:51 +0000 (21:46 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 1 Oct 2011 21:46:51 +0000 (21:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=69215

Reviewed by Geoff Garen.

Adds a GetStringLength node to the DFG so that we can support
string.length inline.

* dfg/DFGNode.h:
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::performNodeCSE):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::isKnownString):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* runtime/JSString.h:
(JSC::JSString::offsetOfLength):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGPropagator.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/runtime/JSString.h

index 9f76a2c..3b2877e 100644 (file)
@@ -1,3 +1,27 @@
+2011-10-01  Oliver Hunt  <oliver@apple.com>
+
+        Support string length in the DFG
+        https://bugs.webkit.org/show_bug.cgi?id=69215
+
+        Reviewed by Geoff Garen.
+
+        Adds a GetStringLength node to the DFG so that we can support
+        string.length inline.
+
+        * dfg/DFGNode.h:
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        (JSC::DFG::Propagator::fixupNode):
+        (JSC::DFG::Propagator::performNodeCSE):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::isKnownString):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * runtime/JSString.h:
+        (JSC::JSString::offsetOfLength):
+
 2011-10-01  Yuqiang Xian  <yuqiang.xian@intel.com>
 
         JSVALUE32_64 DFG JIT - unboxed integers and cells in register file must be reboxed before exiting from DFG JIT
index 6c555d3..80626a2 100644 (file)
                86880F1914328BB900B08D42 /* DFGJITCompiler32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCompiler32_64.cpp; path = dfg/DFGJITCompiler32_64.cpp; sourceTree = "<group>"; };
                86880F1A14328BB900B08D42 /* DFGJITCompilerInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGJITCompilerInlineMethods.h; path = dfg/DFGJITCompilerInlineMethods.h; sourceTree = "<group>"; };
                86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT32_64.cpp; path = dfg/DFGSpeculativeJIT32_64.cpp; sourceTree = "<group>"; };
-               86880F311434FFAF00B08D42 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
                86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCodeGenerator64.cpp; path = dfg/DFGJITCodeGenerator64.cpp; sourceTree = "<group>"; };
                86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT64.cpp; path = dfg/DFGSpeculativeJIT64.cpp; sourceTree = "<group>"; };
                868BFA00117CEFD100B908B1 /* AtomicString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AtomicString.cpp; path = text/AtomicString.cpp; sourceTree = "<group>"; };
                0867D691FE84028FC02AAC07 /* JavaScriptCore */ = {
                        isa = PBXGroup;
                        children = (
-                               86880F311434FFAF00B08D42 /* ChangeLog */,
                                651122E5140469BA002B101D /* testRegExp.cpp */,
                                A718F8211178EB4B002465A7 /* create_regex_tables */,
                                937B63CC09E766D200A671DD /* DerivedSources.make */,
index 7ddb4cc..63b7f50 100644 (file)
@@ -319,6 +319,7 @@ static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
     macro(GetByOffset, NodeResultJS) \
     macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
     macro(GetArrayLength, NodeResultInt32) \
+    macro(GetStringLength, NodeResultInt32) \
     macro(GetMethod, NodeResultJS | NodeMustGenerate) \
     macro(CheckMethod, NodeResultJS | NodeMustGenerate) \
     macro(GetScopeChain, NodeResultJS) \
index 994ac3c..64855cc 100644 (file)
@@ -559,7 +559,8 @@ private:
         }
             
         case ValueToDouble:
-        case GetArrayLength: {
+        case GetArrayLength:
+        case GetStringLength: {
             // This node should never be visible at this stage of compilation. It is
             // inserted by fixup(), which follows this phase.
             ASSERT_NOT_REACHED();
@@ -706,7 +707,9 @@ private:
         }
             
         case GetById: {
-            if (!isArrayPrediction(m_predictions[node.child1()]))
+            bool isArray = isArrayPrediction(m_predictions[node.child1()]);
+            bool isString = isStringPrediction(m_predictions[node.child1()]);
+            if (!isArray && !isString)
                 break;
             if (!isInt32Prediction(m_predictions[m_compileIndex]))
                 break;
@@ -714,9 +717,9 @@ private:
                 break;
             
 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
-            printf("  @%u -> GetArrayLength", nodeIndex);
+            printf("  @%u -> %s", nodeIndex, isArray ? "GetArrayLength" : "GetStringLength");
 #endif
-            node.op = GetArrayLength;
+            node.op = isArray ? GetArrayLength : GetStringLength;
             break;
         }
             
@@ -1189,6 +1192,7 @@ private:
         case ArithSqrt:
         case GetCallee:
         case GetArrayLength:
+        case GetStringLength:
             setReplacement(pureCSE(node));
             break;
             
index 1086b76..65a2841 100644 (file)
@@ -579,6 +579,18 @@ private:
             return false;
         }
     }
+
+    bool isKnownString(NodeIndex op1)
+    {
+        Node& node = m_jit.graph()[op1];
+        switch (node.op) {
+        case GetLocal:
+            return isStringPrediction(node.variableAccessData()->prediction());
+
+        default:
+            return false;
+        }
+    }
     
     bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, Z_DFGOperation_EJJ);
     bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, Z_DFGOperation_EJJ);
index 155ed0c..e62f6d3 100644 (file)
@@ -1655,6 +1655,22 @@ void SpeculativeJIT::compile(Node& node)
         break;
     }
 
+    case GetStringLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        if (!isKnownString(node.child1()))
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+        
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
+
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
         
index 0aa388f..22de008 100644 (file)
@@ -1715,6 +1715,22 @@ void SpeculativeJIT::compile(Node& node)
         break;
     }
 
+    case GetStringLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        if (!isKnownString(node.child1()))
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+        
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
+
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
         
index 54afd5c..1ac84f4 100644 (file)
@@ -445,7 +445,9 @@ namespace JSC {
         {
             return Structure::create(globalData, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot), &s_info);
         }
-        
+
+        static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
+
         static const ClassInfo s_info;
 
     private: