Add support for inferred function names
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Feb 2012 23:23:30 +0000 (23:23 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Feb 2012 23:23:30 +0000 (23:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77579

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

Add new "inferred" names to function expressions, getters, and setters.
This property is not exposed to JS, so is only visible in the debugger
and profiler.

* JavaScriptCore.exp:
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::makeFunction):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::calculatedFunctionName):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createAssignResolve):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createProperty):
(JSC::ASTBuilder::makeAssignNode):
* parser/Nodes.h:
(JSC::FunctionBodyNode::setInferredName):
(JSC::FunctionBodyNode::inferredName):
(FunctionBodyNode):
* profiler/Profiler.cpp:
(JSC):
(JSC::Profiler::createCallIdentifier):
(JSC::createCallIdentifierFromFunctionImp):
* runtime/Executable.cpp:
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::FunctionExecutable::fromGlobalCode):
* runtime/Executable.h:
(JSC::FunctionExecutable::create):
(JSC::FunctionExecutable::inferredName):
(FunctionExecutable):
* runtime/JSFunction.cpp:
(JSC::JSFunction::calculatedDisplayName):
(JSC):
(JSC::getCalculatedDisplayName):
* runtime/JSFunction.h:
(JSC):

LayoutTests:

Update test case results.

* fast/profiler/anonymous-event-handler-expected.txt:
* fast/profiler/anonymous-function-called-from-different-contexts-expected.txt:
* fast/profiler/anonymous-function-calls-built-in-functions-expected.txt:
* fast/profiler/anonymous-function-calls-eval-expected.txt:
* fast/profiler/built-in-function-calls-anonymous-expected.txt:
* fast/profiler/inline-event-handler-expected.txt:
* fast/profiler/many-calls-in-the-same-scope-expected.txt:
* fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt:
* fast/profiler/multiple-and-different-scoped-function-calls-expected.txt:
* fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt:
* fast/profiler/nested-anonymous-functon-expected.txt:
* fast/profiler/start-and-stop-profiler-multiple-times-expected.txt:

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/profiler/anonymous-event-handler-expected.txt
LayoutTests/fast/profiler/anonymous-function-called-from-different-contexts-expected.txt
LayoutTests/fast/profiler/anonymous-function-calls-built-in-functions-expected.txt
LayoutTests/fast/profiler/anonymous-function-calls-eval-expected.txt
LayoutTests/fast/profiler/built-in-function-calls-anonymous-expected.txt
LayoutTests/fast/profiler/inline-event-handler-expected.txt
LayoutTests/fast/profiler/many-calls-in-the-same-scope-expected.txt
LayoutTests/fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt
LayoutTests/fast/profiler/multiple-and-different-scoped-function-calls-expected.txt
LayoutTests/fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt
LayoutTests/fast/profiler/nested-anonymous-functon-expected.txt
LayoutTests/fast/profiler/start-and-stop-profiler-multiple-times-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/profiler/Profiler.cpp
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.h

index 6a6ed1f..06c4d1f 100644 (file)
@@ -1,3 +1,25 @@
+2012-02-01  Oliver Hunt  <oliver@apple.com>
+
+        Add support for inferred function names
+        https://bugs.webkit.org/show_bug.cgi?id=77579
+
+        Reviewed by Gavin Barraclough.
+
+        Update test case results.
+
+        * fast/profiler/anonymous-event-handler-expected.txt:
+        * fast/profiler/anonymous-function-called-from-different-contexts-expected.txt:
+        * fast/profiler/anonymous-function-calls-built-in-functions-expected.txt:
+        * fast/profiler/anonymous-function-calls-eval-expected.txt:
+        * fast/profiler/built-in-function-calls-anonymous-expected.txt:
+        * fast/profiler/inline-event-handler-expected.txt:
+        * fast/profiler/many-calls-in-the-same-scope-expected.txt:
+        * fast/profiler/multiple-and-different-scoped-anonymous-function-calls-expected.txt:
+        * fast/profiler/multiple-and-different-scoped-function-calls-expected.txt:
+        * fast/profiler/multiple-anonymous-functions-called-from-the-same-function-expected.txt:
+        * fast/profiler/nested-anonymous-functon-expected.txt:
+        * fast/profiler/start-and-stop-profiler-multiple-times-expected.txt:
+
 2012-02-01  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         Replace JSArray destructor with finalizer
index 71e3e6b..e1faf18 100644 (file)
@@ -7,7 +7,7 @@ Thread_1 (no file) (line 0)
    startTest anonymous-event-handler.html (line 11)
       getElementById (no file) (line 0)
       click (no file) (line 0)
-         (anonymous function) anonymous-event-handler.html (line 15)
+         onclick anonymous-event-handler.html (line 15)
             insertNewText profiler-test-JS-resources.js (line 17)
                createElement (no file) (line 0)
                createTextNode (no file) (line 0)
index 3d31371..afe210f 100644 (file)
@@ -5,7 +5,7 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Same anonymous function called from different contexts
 Thread_1 (no file) (line 0)
    startTest anonymous-function-called-from-different-contexts.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -13,7 +13,7 @@ Thread_1 (no file) (line 0)
             getElementById (no file) (line 0)
       eval (no file) (line 0)
          (program) (no file) (line 1)
-            (anonymous function) profiler-test-JS-resources.js (line 29)
+            anonymousFunction profiler-test-JS-resources.js (line 29)
                insertNewText profiler-test-JS-resources.js (line 17)
                   createElement (no file) (line 0)
                   createTextNode (no file) (line 0)
index 40aa57a..e66f6ac 100644 (file)
@@ -5,7 +5,7 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Anonymous function calls built-in functions
 Thread_1 (no file) (line 0)
    startTest anonymous-function-calls-built-in-functions.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
index 42ff5c9..7bd8560 100644 (file)
@@ -5,7 +5,7 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Anonymous function calles eval
 Thread_1 (no file) (line 0)
    startTest anonymous-function-calls-eval.html (line 11)
-      (anonymous function) anonymous-function-calls-eval.html (line 14)
+      variableThatPointsToAnAnonymousFunction anonymous-function-calls-eval.html (line 14)
          eval (no file) (line 0)
             (program) (no file) (line 1)
                insertNewText profiler-test-JS-resources.js (line 17)
index 4849640..7e41913 100644 (file)
@@ -7,7 +7,7 @@ Thread_1 (no file) (line 0)
    startTest built-in-function-calls-anonymous.html (line 11)
       Array (no file) (line 0)
       map (no file) (line 0)
-         (anonymous function) built-in-function-calls-anonymous.html (line 14)
+         myFunction built-in-function-calls-anonymous.html (line 14)
             arrayOperatorFunction profiler-test-JS-resources.js (line 25)
       endTest profiler-test-JS-resources.js (line 1)
 
index 7f952a0..38a3012 100644 (file)
@@ -9,7 +9,7 @@ Thread_1 (no file) (line 0)
       click (no file) (line 0)
          onclick inline-event-handler.html (line 31)
             eventListener inline-event-handler.html (line 17)
-               (anonymous function) profiler-test-JS-resources.js (line 29)
+               anonymousFunction profiler-test-JS-resources.js (line 29)
                   insertNewText profiler-test-JS-resources.js (line 17)
                      createElement (no file) (line 0)
                      createTextNode (no file) (line 0)
index 04dfb90..d66e054 100644 (file)
@@ -17,13 +17,13 @@ Thread_1 (no file) (line 0)
          getElementById (no file) (line 0)
       arrayOperatorFunction profiler-test-JS-resources.js (line 25)
       intermediaryFunction profiler-test-JS-resources.js (line 33)
-         (anonymous function) profiler-test-JS-resources.js (line 29)
+         anonymousFunction profiler-test-JS-resources.js (line 29)
             insertNewText profiler-test-JS-resources.js (line 17)
                createElement (no file) (line 0)
                createTextNode (no file) (line 0)
                appendChild (no file) (line 0)
                getElementById (no file) (line 0)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
index b7b83ac..d19c6c9 100644 (file)
@@ -5,14 +5,14 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Multiple and different scoped calls to the same anonymous function
 Thread_1 (no file) (line 0)
    startTest multiple-and-different-scoped-anonymous-function-calls.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
             appendChild (no file) (line 0)
             getElementById (no file) (line 0)
       intermediaryFunction profiler-test-JS-resources.js (line 33)
-         (anonymous function) profiler-test-JS-resources.js (line 29)
+         anonymousFunction profiler-test-JS-resources.js (line 29)
             insertNewText profiler-test-JS-resources.js (line 17)
                createElement (no file) (line 0)
                createTextNode (no file) (line 0)
index 6e8808b..5fd27d9 100644 (file)
@@ -11,7 +11,7 @@ Thread_1 (no file) (line 0)
          appendChild (no file) (line 0)
          getElementById (no file) (line 0)
       intermediaryFunction profiler-test-JS-resources.js (line 33)
-         (anonymous function) profiler-test-JS-resources.js (line 29)
+         anonymousFunction profiler-test-JS-resources.js (line 29)
             insertNewText profiler-test-JS-resources.js (line 17)
                createElement (no file) (line 0)
                createTextNode (no file) (line 0)
index 2317922..08af384 100644 (file)
@@ -5,13 +5,13 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Multiple calls to different anonymous functions
 Thread_1 (no file) (line 0)
    startTest multiple-anonymous-functions-called-from-the-same-function.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
             appendChild (no file) (line 0)
             getElementById (no file) (line 0)
-      (anonymous function) profiler-test-JS-resources.js (line 30)
+      anotherAnonymousFunction profiler-test-JS-resources.js (line 30)
          insertGivenText profiler-test-JS-resources.js (line 9)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
index 559eeb2..56a1dff 100644 (file)
@@ -5,8 +5,8 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Nested anonymous functions called
 Thread_1 (no file) (line 0)
    startTest nested-anonymous-functon.html (line 11)
-      (anonymous function) nested-anonymous-functon.html (line 14)
-         (anonymous function) profiler-test-JS-resources.js (line 29)
+      AnonymousFunctionWichCallsAnAnonymousFunction nested-anonymous-functon.html (line 14)
+         anonymousFunction profiler-test-JS-resources.js (line 29)
             insertNewText profiler-test-JS-resources.js (line 17)
                createElement (no file) (line 0)
                createTextNode (no file) (line 0)
index 62f164e..bd441b4 100644 (file)
@@ -5,7 +5,7 @@ To run this test manually, load it in the browser then load the WebInspector and
 Profile title: Start the profiler the first time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -17,7 +17,7 @@ Thread_1 (no file) (line 0)
 Profile title: Start the profiler the first time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -28,7 +28,7 @@ Thread_1 (no file) (line 0)
 Profile title: Start the profiler the second time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -40,7 +40,7 @@ Thread_1 (no file) (line 0)
 Profile title: Start the profiler the first time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -51,7 +51,7 @@ Thread_1 (no file) (line 0)
 Profile title: Start the profiler the second time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
@@ -62,7 +62,7 @@ Thread_1 (no file) (line 0)
 Profile title: Start the profiler the third time.
 Thread_1 (no file) (line 0)
    startTest start-and-stop-profiler-multiple-times.html (line 11)
-      (anonymous function) profiler-test-JS-resources.js (line 29)
+      anonymousFunction profiler-test-JS-resources.js (line 29)
          insertNewText profiler-test-JS-resources.js (line 17)
             createElement (no file) (line 0)
             createTextNode (no file) (line 0)
index 7e6ff26..6ee07a0 100644 (file)
@@ -1,3 +1,46 @@
+2012-02-01  Oliver Hunt  <oliver@apple.com>
+
+        Add support for inferred function names
+        https://bugs.webkit.org/show_bug.cgi?id=77579
+
+        Reviewed by Gavin Barraclough.
+
+        Add new "inferred" names to function expressions, getters, and setters.
+        This property is not exposed to JS, so is only visible in the debugger
+        and profiler.
+
+        * JavaScriptCore.exp:
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::makeFunction):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::calculatedFunctionName):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createAssignResolve):
+        (JSC::ASTBuilder::createGetterOrSetterProperty):
+        (JSC::ASTBuilder::createProperty):
+        (JSC::ASTBuilder::makeAssignNode):
+        * parser/Nodes.h:
+        (JSC::FunctionBodyNode::setInferredName):
+        (JSC::FunctionBodyNode::inferredName):
+        (FunctionBodyNode):
+        * profiler/Profiler.cpp:
+        (JSC):
+        (JSC::Profiler::createCallIdentifier):
+        (JSC::createCallIdentifierFromFunctionImp):
+        * runtime/Executable.cpp:
+        (JSC::FunctionExecutable::FunctionExecutable):
+        (JSC::FunctionExecutable::fromGlobalCode):
+        * runtime/Executable.h:
+        (JSC::FunctionExecutable::create):
+        (JSC::FunctionExecutable::inferredName):
+        (FunctionExecutable):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::calculatedDisplayName):
+        (JSC):
+        (JSC::getCalculatedDisplayName):
+        * runtime/JSFunction.h:
+        (JSC):
+
 2012-02-01  Filip Pizlo  <fpizlo@apple.com>
 
         DFG should fold double-to-int conversions
index 7266c4e..51032d7 100644 (file)
@@ -113,6 +113,7 @@ __ZN3JSC10Identifier4fromEPNS_9ExecStateEi
 __ZN3JSC10Identifier4fromEPNS_9ExecStateEj
 __ZN3JSC10Identifier8toUInt32ERKNS_7UStringERb
 __ZN3JSC10JSFunction11displayNameEPNS_9ExecStateE
+__ZN3JSC10JSFunction21calculatedDisplayNameEPNS_9ExecStateE
 __ZN3JSC10JSFunction4nameEPNS_9ExecStateE
 __ZN3JSC10JSFunction6s_infoE
 __ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
@@ -240,6 +241,7 @@ __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectER
 __ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
 __ZN3JSC24TerminatedExecutionError6s_infoE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSC24getCalculatedDisplayNameEPNS_9ExecStateEPNS_8JSObjectE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
 __ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
 __ZN3JSC30isTerminatedExecutionExceptionENS_7JSValueE
index 0c93c5c..c9ec5d8 100644 (file)
@@ -594,12 +594,12 @@ namespace JSC {
         
         FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
         {
-            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
         FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
         {
-            return FunctionExecutable::create(*globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
         JSString* addStringConstant(const Identifier&);
index 08fba4a..6a8cdb2 100644 (file)
@@ -56,10 +56,11 @@ UString DebuggerCallFrame::calculatedFunctionName() const
         return UString();
 
     JSObject* function = m_callFrame->callee();
-    if (!function || !function->inherits(&JSFunction::s_info))
+
+    if (!function)
         return UString();
 
-    return asFunction(function)->calculatedDisplayName(m_callFrame);
+    return getCalculatedDisplayName(m_callFrame, function);
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
index 2e81c25..67432d4 100644 (file)
@@ -249,6 +249,8 @@ public:
 
     ExpressionNode* createAssignResolve(int lineNumber, const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
     {
+        if (rhs->isFuncExprNode())
+            static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident);
         AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, ident, rhs, rhsHasAssignment);
         setExceptionLocation(node, start, divot, end);
         return node;
@@ -271,6 +273,7 @@ public:
     {
         ASSERT(name);
         body->setLoc(bodyStartLine, bodyEndLine);
+        body->setInferredName(*name);
         return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type);
     }
     
@@ -280,7 +283,12 @@ public:
     ArgumentListNode* createArgumentsList(int lineNumber, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, arg); }
     ArgumentListNode* createArgumentsList(int lineNumber, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, args, arg); }
 
-    template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+    template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type)
+    {
+        if (node->isFuncExprNode())
+            static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName);
+        return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type);
+    }
     template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
     PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property) { return new (m_globalData) PropertyListNode(lineNumber, property); }
     PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(lineNumber, property, tail); }
@@ -903,6 +911,8 @@ ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc,
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
         if (op == OpEqual) {
+            if (expr->isFuncExprNode())
+                static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier());
             AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, resolve->identifier(), expr, exprHasAssignments);
             setExceptionLocation(node, start, divot, end);
             return node;
@@ -919,8 +929,11 @@ ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc,
     }
     ASSERT(loc->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
-    if (op == OpEqual)
+    if (op == OpEqual) {
+        if (expr->isFuncExprNode())
+            static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier());
         return new (m_globalData) AssignDotNode(lineNumber, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+    }
 
     ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(lineNumber, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
index 5098dc7..54eccde 100644 (file)
@@ -1494,6 +1494,8 @@ namespace JSC {
         void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
         
         const Identifier& ident() { return m_ident; }
+        void setInferredName(const Identifier& inferredName) { m_inferredName = inferredName; }
+        const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
 
         static const bool scopeIsFunction = true;
 
@@ -1502,6 +1504,7 @@ namespace JSC {
         FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         Identifier m_ident;
+        Identifier m_inferredName;
         RefPtr<FunctionParameters> m_parameters;
     };
 
index 0a4b547..0ecd5b2 100644 (file)
@@ -48,7 +48,7 @@ static const char* GlobalCodeExecution = "(program)";
 static const char* AnonymousFunction = "(anonymous function)";
 static unsigned ProfilesUID = 0;
 
-static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const UString& defaultSourceURL, int defaultLineNumber);
 
 Profiler* Profiler::s_sharedProfiler = 0;
 Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
@@ -163,23 +163,18 @@ CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionV
         return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
     if (!functionValue.isObject())
         return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
-    if (asObject(functionValue)->inherits(&JSFunction::s_info)) {
-        JSFunction* function = asFunction(functionValue);
-        if (!function->executable()->isHostFunction())
-            return createCallIdentifierFromFunctionImp(exec, function);
-    }
-    if (asObject(functionValue)->inherits(&JSFunction::s_info))
-        return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
-    if (asObject(functionValue)->inherits(&InternalFunction::s_info))
-        return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
+    if (asObject(functionValue)->inherits(&JSFunction::s_info) || asObject(functionValue)->inherits(&InternalFunction::s_info))
+        return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber);
     return CallIdentifier(makeUString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber);
 }
 
-CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const UString& defaultSourceURL, int defaultLineNumber)
 {
-    ASSERT(!function->isHostFunction());
-    const UString& name = function->calculatedDisplayName(exec);
-    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo());
+    const UString& name = getCalculatedDisplayName(exec, function);
+    JSFunction* jsFunction = jsDynamicCast<JSFunction*>(function);
+    if (jsFunction && !jsFunction->isHostFunction())
+        return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->lineNo());
+    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, defaultSourceURL, defaultLineNumber);
 }
 
 } // namespace JSC
index d9de2d6..c67c54c 100644 (file)
@@ -131,22 +131,24 @@ void ProgramExecutable::destroy(JSCell* cell)
 
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
     : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
+    , m_inferredName(inferredName)
     , m_symbolTable(0)
 {
 }
 
-FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
     : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
+    , m_inferredName(inferredName)
     , m_symbolTable(0)
 {
 }
@@ -660,7 +662,7 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functio
     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
     ASSERT(body);
 
-    return FunctionExecutable::create(exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+    return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
 }
 
 UString FunctionExecutable::paramString() const
index 86080fe..6800b5a 100644 (file)
@@ -456,17 +456,17 @@ namespace JSC {
     public:
         typedef ScriptExecutable Base;
 
-        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
             executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
             exec->globalData().heap.addFinalizer(executable, &finalize);
             return executable;
         }
 
-        static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
             executable->finishCreation(globalData, name, firstLine, lastLine);
             globalData.heap.addFinalizer(executable, &finalize);
             return executable;
@@ -608,6 +608,7 @@ namespace JSC {
         }
         
         const Identifier& name() { return m_name; }
+        const Identifier& inferredName() { return m_inferredName; }
         JSString* nameValue() const { return m_nameValue.get(); }
         size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'!
         unsigned capturedVariableCount() const { return m_numCapturedVariables; }
@@ -639,8 +640,8 @@ namespace JSC {
         }
 
     private:
-        FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
-        FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+        FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+        FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
 
         JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
         JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
@@ -661,6 +662,7 @@ namespace JSC {
         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
         Identifier m_name;
+        Identifier m_inferredName;
         WriteBarrier<JSString> m_nameValue;
         SharedSymbolTable* m_symbolTable;
     };
index c525e7c..15718a1 100644 (file)
@@ -136,7 +136,11 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
     if (!explicitName.isEmpty())
         return explicitName;
     
-    return name(exec);
+    const UString actualName = name(exec);
+    if (!actualName.isEmpty() || isHostFunction())
+        return actualName;
+    
+    return jsExecutable()->inferredName().ustring();
 }
 
 const SourceCode* JSFunction::sourceCode() const
@@ -357,5 +361,15 @@ ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& construc
     constructData.js.scopeChain = thisObject->scope();
     return ConstructTypeJS;
 }
+    
+
+UString getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
+{
+    if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
+        return function->calculatedDisplayName(callFrame);
+    if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
+        return function->calculatedDisplayName(callFrame);
+    return UString();
+}
 
 } // namespace JSC
index 4792301..a12b079 100644 (file)
@@ -42,6 +42,8 @@ namespace JSC {
 
     JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
 
+    JS_EXPORT_PRIVATE UString getCalculatedDisplayName(CallFrame*, JSObject*);
+    
     class JSFunction : public JSNonFinalObject {
         friend class JIT;
         friend class DFG::SpeculativeJIT;