Title: [190146] trunk
Revision
190146
Author
sbar...@apple.com
Date
2015-09-22 17:39:09 -0700 (Tue, 22 Sep 2015)

Log Message

Web Inspector: [ES6] Improve Type Profiler Support for Arrow Functions
https://bugs.webkit.org/show_bug.cgi?id=143171

Reviewed by Joseph Pecoraro.

Source/_javascript_Core:

We now need to take into account TypeProfilerSearchDescriptor when
hashing results for type profiler queries. Before, we've gotten
away with not doing this because before we would never have a text 
collision between a return type text offset and a normal _expression_ text
offset. But, with arrow functions, we will have collisions when
the arrow function doesn't have parens around its single parameter.
I.e: "param => { ... };"

* runtime/TypeProfiler.cpp:
(JSC::TypeProfiler::findLocation):
* runtime/TypeProfiler.h:
(JSC::QueryKey::QueryKey):
(JSC::QueryKey::isHashTableDeletedValue):
(JSC::QueryKey::operator==):
(JSC::QueryKey::hash):
* tests/typeProfiler/arrow-functions.js: Added.

Source/WebInspectorUI:

Esprima and JSC both support arrow functions. We just
need to support it in our AST and do the right things
to include support in the type profiler bits.

* UserInterface/Controllers/TypeTokenAnnotator.js:
(WebInspector.TypeTokenAnnotator.prototype._insertTypeToken):
(WebInspector.TypeTokenAnnotator.prototype._translateToOffsetAfterFunctionParameterList.isLineTerminator):
(WebInspector.TypeTokenAnnotator.prototype._translateToOffsetAfterFunctionParameterList):
* UserInterface/Models/ScriptSyntaxTree.js:
(WebInspector.ScriptSyntaxTree.prototype.containsNonEmptyReturnStatement.removeFunctionsFilter):
(WebInspector.ScriptSyntaxTree.prototype.containsNonEmptyReturnStatement):
(WebInspector.ScriptSyntaxTree.functionReturnDivot):
(WebInspector.ScriptSyntaxTree.prototype._recurse):
(WebInspector.ScriptSyntaxTree.prototype._createInternalSyntaxTree):
(WebInspector.ScriptSyntaxTree):

LayoutTests:

* inspector/model/parse-script-syntax-tree-expected.txt:
* inspector/model/parse-script-syntax-tree.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (190145 => 190146)


--- trunk/LayoutTests/ChangeLog	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/LayoutTests/ChangeLog	2015-09-23 00:39:09 UTC (rev 190146)
@@ -1,3 +1,13 @@
+2015-09-22  Saam barati  <sbar...@apple.com>
+
+        Web Inspector: [ES6] Improve Type Profiler Support for Arrow Functions
+        https://bugs.webkit.org/show_bug.cgi?id=143171
+
+        Reviewed by Joseph Pecoraro.
+
+        * inspector/model/parse-script-syntax-tree-expected.txt:
+        * inspector/model/parse-script-syntax-tree.html:
+
 2015-09-22  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r190134.

Modified: trunk/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt (190145 => 190146)


--- trunk/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt	2015-09-23 00:39:09 UTC (rev 190146)
@@ -40,5 +40,6 @@
 passed WithStatement
 passed ClassStatement, Super, MetaProperty
 passed AssignmentPattern
+passed ArrowFunctionExpression
 passed ALL TESTS
 

Modified: trunk/LayoutTests/inspector/model/parse-script-syntax-tree.html (190145 => 190146)


--- trunk/LayoutTests/inspector/model/parse-script-syntax-tree.html	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/LayoutTests/inspector/model/parse-script-syntax-tree.html	2015-09-23 00:39:09 UTC (rev 190146)
@@ -476,6 +476,26 @@
     InspectorTest.assert(node.declarations[0].id.elements[0].right.value === 20);
     InspectorTest.log("passed AssignmentPattern");
 
+    node = makeNode("(x) => x;", true);
+    InspectorTest.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression);
+    InspectorTest.assert(node.params.length === 1);
+    InspectorTest.assert(node.params[0].type === WebInspector.ScriptSyntaxTree.NodeType.Identifier);
+    InspectorTest.assert(node.params[0].name === "x");
+    InspectorTest.assert(node._expression_ === true);
+    InspectorTest.assert(node.defaults.length === 0);
+    InspectorTest.assert(node.body.type === WebInspector.ScriptSyntaxTree.NodeType.Identifier);
+
+    node = makeNode("(x = 20) => { return x; };", true);
+    InspectorTest.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression);
+    InspectorTest.assert(node.params.length === 1);
+    InspectorTest.assert(node.params[0].type === WebInspector.ScriptSyntaxTree.NodeType.Identifier);
+    InspectorTest.assert(node.params[0].name === "x");
+    InspectorTest.assert(node._expression_ === false);
+    InspectorTest.assert(node.defaults.length === 1);
+    InspectorTest.assert(node.defaults[0].type === WebInspector.ScriptSyntaxTree.NodeType.Literal);
+    InspectorTest.assert(node.body.type === WebInspector.ScriptSyntaxTree.NodeType.BlockStatement);
+    InspectorTest.log("passed ArrowFunctionExpression");
+
     InspectorTest.log("passed ALL TESTS");
     InspectorTest.completeTest();
 }

Modified: trunk/Source/_javascript_Core/ChangeLog (190145 => 190146)


--- trunk/Source/_javascript_Core/ChangeLog	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-09-23 00:39:09 UTC (rev 190146)
@@ -1,3 +1,27 @@
+2015-09-22  Saam barati  <sbar...@apple.com>
+
+        Web Inspector: [ES6] Improve Type Profiler Support for Arrow Functions
+        https://bugs.webkit.org/show_bug.cgi?id=143171
+
+        Reviewed by Joseph Pecoraro.
+
+        We now need to take into account TypeProfilerSearchDescriptor when
+        hashing results for type profiler queries. Before, we've gotten
+        away with not doing this because before we would never have a text 
+        collision between a return type text offset and a normal _expression_ text
+        offset. But, with arrow functions, we will have collisions when
+        the arrow function doesn't have parens around its single parameter.
+        I.e: "param => { ... };"
+
+        * runtime/TypeProfiler.cpp:
+        (JSC::TypeProfiler::findLocation):
+        * runtime/TypeProfiler.h:
+        (JSC::QueryKey::QueryKey):
+        (JSC::QueryKey::isHashTableDeletedValue):
+        (JSC::QueryKey::operator==):
+        (JSC::QueryKey::hash):
+        * tests/typeProfiler/arrow-functions.js: Added.
+
 2015-09-22  Filip Pizlo  <fpi...@apple.com>
 
         Get rid of ENABLE(PARALLEL_GC)

Modified: trunk/Source/_javascript_Core/runtime/TypeProfiler.cpp (190145 => 190146)


--- trunk/Source/_javascript_Core/runtime/TypeProfiler.cpp	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/_javascript_Core/runtime/TypeProfiler.cpp	2015-09-23 00:39:09 UTC (rev 190146)
@@ -108,7 +108,7 @@
 
 TypeLocation* TypeProfiler::findLocation(unsigned divot, intptr_t sourceID, TypeProfilerSearchDescriptor descriptor, VM& vm)
 {
-    QueryKey queryKey(sourceID, divot);
+    QueryKey queryKey(sourceID, divot, descriptor);
     auto iter = m_queryCache.find(queryKey);
     if (iter != m_queryCache.end())
         return iter->value;
@@ -129,7 +129,7 @@
         if (descriptor == TypeProfilerSearchDescriptorFunctionReturn && location->m_globalVariableID == TypeProfilerReturnStatement && location->m_divotForFunctionOffsetIfReturnStatement == divot)
             return location;
 
-        if (descriptor != TypeProfilerSearchDescriptorFunctionReturn && location->m_divotStart <= divot && divot <= location->m_divotEnd && location->m_divotEnd - location->m_divotStart <= distance) {
+        if (descriptor != TypeProfilerSearchDescriptorFunctionReturn && location->m_globalVariableID != TypeProfilerReturnStatement && location->m_divotStart <= divot && divot <= location->m_divotEnd && location->m_divotEnd - location->m_divotStart <= distance) {
             distance = location->m_divotEnd - location->m_divotStart;
             bestMatch = location;
         }

Modified: trunk/Source/_javascript_Core/runtime/TypeProfiler.h (190145 => 190146)


--- trunk/Source/_javascript_Core/runtime/TypeProfiler.h	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/_javascript_Core/runtime/TypeProfiler.h	2015-09-23 00:39:09 UTC (rev 190146)
@@ -40,28 +40,53 @@
 
 namespace JSC {
 
+enum TypeProfilerSearchDescriptor {
+    TypeProfilerSearchDescriptorNormal = 1,
+    TypeProfilerSearchDescriptorFunctionReturn = 2
+};
+
 struct QueryKey {
     QueryKey()
         : m_sourceID(0)
         , m_divot(0)
+        , m_searchDescriptor(TypeProfilerSearchDescriptorFunctionReturn)
     { }
 
-    QueryKey(intptr_t sourceID, unsigned divot)
+    QueryKey(intptr_t sourceID, unsigned divot, TypeProfilerSearchDescriptor searchDescriptor)
         : m_sourceID(sourceID)
         , m_divot(divot)
+        , m_searchDescriptor(searchDescriptor)
     { }
 
     QueryKey(WTF::HashTableDeletedValueType)
         : m_sourceID(INTPTR_MAX)
         , m_divot(UINT_MAX)
+        , m_searchDescriptor(TypeProfilerSearchDescriptorFunctionReturn)
     { }
 
-    bool isHashTableDeletedValue() const { return m_sourceID == INTPTR_MAX && m_divot == UINT_MAX; }
-    bool operator==(const QueryKey& other) const { return m_sourceID == other.m_sourceID && m_divot == other.m_divot; }
-    unsigned hash() const { return m_sourceID + m_divot; }
+    bool isHashTableDeletedValue() const 
+    { 
+        return m_sourceID == INTPTR_MAX 
+            && m_divot == UINT_MAX
+            && m_searchDescriptor == TypeProfilerSearchDescriptorFunctionReturn;
+    }
 
+    bool operator==(const QueryKey& other) const
+    {
+        return m_sourceID == other.m_sourceID 
+            && m_divot == other.m_divot
+            && m_searchDescriptor == other.m_searchDescriptor;
+    }
+
+    unsigned hash() const 
+    { 
+        unsigned hash = m_sourceID + m_divot * m_searchDescriptor;
+        return hash;
+    }
+
     intptr_t m_sourceID;
     unsigned m_divot;
+    TypeProfilerSearchDescriptor m_searchDescriptor;
 };
 
 struct QueryKeyHash {
@@ -80,7 +105,9 @@
 };
 
 template<typename T> struct HashTraits;
-template<> struct HashTraits<JSC::QueryKey> : SimpleClassHashTraits<JSC::QueryKey> { };
+template<> struct HashTraits<JSC::QueryKey> : SimpleClassHashTraits<JSC::QueryKey> {
+    static const bool emptyValueIsZero = false;
+};
 
 } // namespace WTF
 
@@ -88,11 +115,6 @@
 
 class VM;
 
-enum TypeProfilerSearchDescriptor {
-    TypeProfilerSearchDescriptorNormal = 1,
-    TypeProfilerSearchDescriptorFunctionReturn = 2
-};
-
 class TypeProfiler {
     WTF_MAKE_FAST_ALLOCATED;
 public:

Added: trunk/Source/_javascript_Core/tests/typeProfiler/arrow-functions.js (0 => 190146)


--- trunk/Source/_javascript_Core/tests/typeProfiler/arrow-functions.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/typeProfiler/arrow-functions.js	2015-09-23 00:39:09 UTC (rev 190146)
@@ -0,0 +1,39 @@
+load("./driver/driver.js");
+
+let foo = (x) => x;
+let bar = abc => abc;
+let baz = abc => { return abc; };
+let jaz = abc => { };
+
+function wrapper(b) {
+    let baz = (x) => x;
+    baz(b);
+
+    let foo = yyy => yyy;
+    foo(b);
+}
+
+// ====== End test cases ======
+
+foo(20);
+var types = returnTypeFor(foo);
+assert(types.globalTypeSet.displayTypeName === T.Integer, "Function 'foo' should return 'Integer'");
+
+bar("hello");
+types = returnTypeFor(bar);
+assert(types.globalTypeSet.displayTypeName === T.String, "Function 'bar' should return 'String'");
+
+baz("hello");
+types = returnTypeFor(baz);
+assert(types.globalTypeSet.displayTypeName === T.String, "Function 'baz' should return 'String'");
+
+jaz("hello");
+types = returnTypeFor(jaz);
+assert(types.globalTypeSet.displayTypeName === T.Undefined, "Function 'jaz' should return 'Undefined'");
+
+wrapper("hello");
+types = findTypeForExpression(wrapper, "x)"); 
+assert(types.instructionTypeSet.displayTypeName === T.String, "Parameter 'x' should be 'String'");
+
+types = findTypeForExpression(wrapper, "yyy =>");
+assert(types.instructionTypeSet.displayTypeName === T.String, "Parameter 'yyy' should be 'String'");

Modified: trunk/Source/WebInspectorUI/ChangeLog (190145 => 190146)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-09-23 00:39:09 UTC (rev 190146)
@@ -1,5 +1,28 @@
 2015-09-22  Saam barati  <sbar...@apple.com>
 
+        Web Inspector: [ES6] Improve Type Profiler Support for Arrow Functions
+        https://bugs.webkit.org/show_bug.cgi?id=143171
+
+        Reviewed by Joseph Pecoraro.
+
+        Esprima and JSC both support arrow functions. We just
+        need to support it in our AST and do the right things
+        to include support in the type profiler bits.
+
+        * UserInterface/Controllers/TypeTokenAnnotator.js:
+        (WebInspector.TypeTokenAnnotator.prototype._insertTypeToken):
+        (WebInspector.TypeTokenAnnotator.prototype._translateToOffsetAfterFunctionParameterList.isLineTerminator):
+        (WebInspector.TypeTokenAnnotator.prototype._translateToOffsetAfterFunctionParameterList):
+        * UserInterface/Models/ScriptSyntaxTree.js:
+        (WebInspector.ScriptSyntaxTree.prototype.containsNonEmptyReturnStatement.removeFunctionsFilter):
+        (WebInspector.ScriptSyntaxTree.prototype.containsNonEmptyReturnStatement):
+        (WebInspector.ScriptSyntaxTree.functionReturnDivot):
+        (WebInspector.ScriptSyntaxTree.prototype._recurse):
+        (WebInspector.ScriptSyntaxTree.prototype._createInternalSyntaxTree):
+        (WebInspector.ScriptSyntaxTree):
+
+2015-09-22  Saam barati  <sbar...@apple.com>
+
         Web Inspector: update Esprima to latest version
         https://bugs.webkit.org/show_bug.cgi?id=148960
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/TypeTokenAnnotator.js (190145 => 190146)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/TypeTokenAnnotator.js	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/TypeTokenAnnotator.js	2015-09-23 00:39:09 UTC (rev 190146)
@@ -95,7 +95,7 @@
             return;
         }
 
-        console.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration || node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression);
+        console.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration || node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression || node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression);
 
         var functionReturnType = node.attachments.returnTypes;
         if (!functionReturnType || !functionReturnType.valid)
@@ -148,6 +148,7 @@
         var isMultiLineComment = false;
         var isSingleLineComment = false;
         var shouldIgnore = false;
+        const isArrowFunction = node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression;
 
         function isLineTerminator(char)
         {
@@ -157,7 +158,10 @@
             return char === "\n" || char === "\r" || char === "\u2028" || char === "\u2029";
         }
 
-        while ((sourceString[offset] !== ")" || shouldIgnore) && offset < sourceString.length) {
+        while (((!isArrowFunction && sourceString[offset] !== ")")
+                || (isArrowFunction && sourceString[offset] !== ">")
+                || shouldIgnore)
+               && offset < sourceString.length) {
             if (isSingleLineComment && isLineTerminator(sourceString[offset])) {
                 isSingleLineComment = false;
                 shouldIgnore = false;

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js (190145 => 190146)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js	2015-09-23 00:33:21 UTC (rev 190145)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js	2015-09-23 00:39:09 UTC (rev 190146)
@@ -128,7 +128,8 @@
         function removeFunctionsFilter(node)
         {
             return node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression
-                && node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration;
+                && node.type !== WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration
+                && node.type !== WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression;
         }
 
         var nodes = this.filter(removeFunctionsFilter, startNode);
@@ -148,10 +149,7 @@
 
     static functionReturnDivot(node)
     {
-        console.assert(
-            node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration 
-            || node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression 
-            || node.type === WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition);
+        console.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration || node.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression || node.type === WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition || node.type === WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression); 
 
         // COMPATIBILITY (iOS 9): Legacy Backends view the return type as being the opening "{" of the function body. 
         // After iOS 9, this is to move to the start of the function statement/_expression_. See below:
@@ -179,6 +177,7 @@
             switch (node.type) {
             case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
             case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
+            case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
                 for (var param of node.params) {
                     for (var identifier of this._gatherIdentifiersInDeclaration(param)) {
                         allRequests.push({
@@ -190,7 +189,6 @@
                     }
                 }
 
-
                 allRequests.push({
                     typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.FunctionReturn,
                     sourceID,
@@ -368,6 +366,7 @@
             break;
         case WebInspector.ScriptSyntaxTree.NodeType.FunctionDeclaration:
         case WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression:
+        case WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression:
             callback(node, state);
             this._recurse(node.id, callback, state);
             this._recurseArray(node.params, callback, state);
@@ -527,6 +526,29 @@
 
         var result = null;
         switch (node.type) {
+        case "ArrayExpression":
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression,
+                elements: node.elements.map(this._createInternalSyntaxTree.bind(this))
+            };
+            break;
+        case "ArrayPattern":
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern,
+                elements: node.elements.map(this._createInternalSyntaxTree.bind(this))
+            };
+            break;
+        case "ArrowFunctionExpression":
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.ArrowFunctionExpression,
+                id: this._createInternalSyntaxTree(node.id),
+                params: node.params.map(this._createInternalSyntaxTree.bind(this)),
+                defaults: node.defaults.map(this._createInternalSyntaxTree.bind(this)),
+                body: this._createInternalSyntaxTree(node.body),
+                _expression_: node._expression_, // Boolean indicating if the body a single _expression_ or a block statement.
+                isGetterOrSetter: false
+            };
+            break;
         case "AssignmentExpression":
             result = {
                 type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentExpression,
@@ -542,18 +564,6 @@
                 right: this._createInternalSyntaxTree(node.right),
             };
             break;
-        case "ArrayExpression":
-            result = {
-                type: WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression,
-                elements: node.elements.map(this._createInternalSyntaxTree.bind(this))
-            };
-            break;
-        case "ArrayPattern":
-            result = {
-                type: WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern,
-                elements: node.elements.map(this._createInternalSyntaxTree.bind(this))
-            };
-            break;
         case "BlockStatement":
             result = {
                 type: WebInspector.ScriptSyntaxTree.NodeType.BlockStatement,
@@ -942,6 +952,7 @@
 WebInspector.ScriptSyntaxTree.NodeType = {
     ArrayExpression: Symbol("array-_expression_"),
     ArrayPattern: Symbol("array-pattern"),
+    ArrowFunctionExpression: Symbol("arrow-function-_expression_"),
     AssignmentExpression: Symbol("assignment-_expression_"),
     AssignmentPattern: Symbol("assignment-pattern"),
     BinaryExpression: Symbol("binary-_expression_"),
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to