Title: [198288] trunk
Revision
198288
Author
[email protected]
Date
2016-03-16 11:16:32 -0700 (Wed, 16 Mar 2016)

Log Message

Add support for setting Function.name from computed properties.
https://bugs.webkit.org/show_bug.cgi?id=155437

Reviewed by Filip Pizlo.

Source/_javascript_Core:

In JS code, we can have initialization of computed properties with function and
class objects e.g.

    var o = {
        [x]: function() {},
        [y]: class {}
    }

The ES6 spec states that the function and class in the example above (being
anonymous) should take on the value of x and y respectively as their names:

    o[x].name; // should be the "stringified" value of x.
    o[y].name; // should be the "stringified" value of y.

To achieve this, we will now inject an op_set_function_name bytecode at property
initialization sites if:

1. the property assigned value is a function or class, and
2. the function and class is anonymous, and
3. if property assigned value is a class, it doesn't have a static method
   that is statically named "name".

The op_set_function_name will result in JSFunction::setFunctionName() being
called on the target function / class before it is assigned to the property.
JSFunction::setFunctionName() will take care of:

1. computing the name to use from the value of the computed property name
   e.g. x and y in the example above.

   If the computed property name is not a symbol, then the function / class name
   should be the toString() value of that computed property name.

   If the computed property name is a symbol, then ...
   a. if the Symbol has a defined description (e.g. Symbol("foo")), then the
      function / class name should be "[<symbol description>]" e.g. "[foo]".
   b. if the Symbol has an undefined description (e.g. Symbol()), then the
      function / class name should be "".

   Note: Symbol("") is not the same as Symbol().  The former has a defined
   descriptor "", and hence, yields a function / class name of "[]".  The latter
   yields a function / class name of "".

2. reifying the lazy name property with this function / class name.

op_set_function_name is named after the SetFunctionName internal function
in the ES6 spec that performs the above operation.

It is behaviorally correct to use op_set_function_name at every property
initialization site with computed property names.  However, we choose to not
emit the op_set_function_name bytecode when we already know that it will do
nothing i.e. when the target function / class is proven to already have a name or
name property.  This is done as an optimization to avoid unnecessary calls to
JSFunction::setFunctionName().

Note: we could further check if the class has a static method with a computed
name that is a constant string "name" and elide op_set_function_name there too.
However, we don't bother because this should be rare.  JSFunction::setFunctionName()
will still do the right thing.

* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitNewFunction):
(JSC::BytecodeGenerator::emitSetFunctionNameIfNeeded):
(JSC::BytecodeGenerator::emitCall):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitBytecode):
(JSC::PropertyListNode::emitPutConstantProperty):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewFunction):
(JSC::DFG::SpeculativeJIT::compileSetFunctionName):
(JSC::DFG::SpeculativeJIT::compileForwardVarargs):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
(JSC::FTL::DFG::LowerDFGToB3::compileSetFunctionName):
(JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_to_primitive):
(JSC::JIT::emit_op_set_function_name):
(JSC::JIT::emit_op_strcat):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emitSlow_op_to_primitive):
(JSC::JIT::emit_op_set_function_name):
(JSC::JIT::emit_op_strcat):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::handleHostCall):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* parser/Nodes.cpp:
(JSC::FunctionNode::finishParsing):
(JSC::PropertyListNode::hasStaticallyNamedProperty):
(JSC::VariableEnvironmentNode::VariableEnvironmentNode):
* parser/Nodes.h:
* runtime/JSFunction.cpp:
(JSC::getCalculatedDisplayName):
(JSC::JSFunction::setFunctionName):
(JSC::JSFunction::reifyLength):
(JSC::JSFunction::reifyName):
* runtime/JSFunction.h:
* tests/es6.yaml:
* tests/stress/computed-function-names.js: Added.
(toKeyString):
(toFuncName):
(shouldBe):
(return.propKey):

LayoutTests:

* js/object-literal-computed-methods-expected.txt:
- Exercise op_set_function_name at all tiers.

* js/script-tests/function-toString-vs-name.js:
- Added tests for computed properties.

* js/script-tests/object-literal-computed-methods.js:
- rebased results.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (198287 => 198288)


--- trunk/LayoutTests/ChangeLog	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/LayoutTests/ChangeLog	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,3 +1,19 @@
+2016-03-16  Mark Lam  <[email protected]>
+
+        Add support for setting Function.name from computed properties.
+        https://bugs.webkit.org/show_bug.cgi?id=155437
+
+        Reviewed by Filip Pizlo.
+
+        * js/object-literal-computed-methods-expected.txt:
+        - Exercise op_set_function_name at all tiers.
+
+        * js/script-tests/function-toString-vs-name.js:
+        - Added tests for computed properties.
+
+        * js/script-tests/object-literal-computed-methods.js:
+        - rebased results.
+
 2016-03-16  Ryan Haddad  <[email protected]>
 
         Marking imported/blink/fast/multicol/dynamic/relayout-abspos-in-relpos-spanner.html as flaky on ios-sim

Modified: trunk/LayoutTests/js/object-literal-computed-methods-expected.txt (198287 => 198288)


--- trunk/LayoutTests/js/object-literal-computed-methods-expected.txt	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/LayoutTests/js/object-literal-computed-methods-expected.txt	2016-03-16 18:16:32 UTC (rev 198288)
@@ -7,7 +7,7 @@
 PASS o.foo() is 10
 PASS typeof o.foo is 'function'
 PASS o.foo.length is 0
-PASS o.foo.name is ''
+PASS o.foo.name is 'foo'
 PASS o.foo.toString() is 'function () { return 10; }'
 PASS Object.getOwnPropertyDescriptor(o, 'foo').value is o.foo
 PASS Object.getOwnPropertyDescriptor(o, 'foo').enumerable is true
@@ -17,7 +17,7 @@
 PASS o.add(42, -10) is 32
 PASS typeof o.add is 'function'
 PASS o.add.length is 2
-PASS o.add.name is ''
+PASS o.add.name is 'add'
 PASS o.add.toString() is 'function (x, y) { return x + y; }'
 PASS o = { [ (function() { return 'method'; })() ](x, y) { return x + y; } }; did not throw exception.
 PASS o.method(142, -10) is 132

Modified: trunk/LayoutTests/js/script-tests/function-toString-vs-name.js (198287 => 198288)


--- trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	2016-03-16 18:16:32 UTC (rev 198288)
@@ -5,6 +5,13 @@
 let failures = "";
 let failureCount = 0;
 
+let nonSymbolValues = [ "foo", "", undefined, null, true, false, 0, 10, 1234.567 ];
+let symbolValues = [
+    { v: Symbol("foo"), name: "[foo]" },
+    { v: Symbol(""), name: "[]" },
+    { v: Symbol(), name: "" },
+];
+
 function isWhiteSpace(string) {
     let cc = string.charCodeAt(0);
     switch (cc) {
@@ -518,59 +525,146 @@
     test(bar3(), "foo3", "class { constructor(x) { return x; } stuff3() { return 15; } }");
 })();
 
-// FIXME: Uncomment these when we've added support for Function.name of computed properties.
-// section = "Object computed string property";
-// {
-//     let str1 = "foo";
-//     let str2 = "";
-//     let o = {    
-//         [str1]: function() {},
-//         [str2]: function() {}
-//     };
-//     test(o[str1], "foo", "function() {}");
-//     test(o[str2], "", "function() {}");
-// }
-// 
-// let sym1 = Symbol("foo");
-// let sym2 = Symbol();
+section = "Object computed non-symbol anonymous function property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: function() {},
+        }
+        test(o[value], toString(value), "function() {}");
 
-// section = "Object computed symbol property";
-// {
-//     let o = {    
-//         [sym1]: function() {},
-//         [sym2]: function() {}
-//     };
-//     test(o[sym1], "[foo]", "function() {}");
-//     test(o[sym2], "", "function() {}");
-// }
+        let bound = o[value].bind({});
+        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
 
-// section = "Object computed symbol property with shorthand function";
-// {
-//     let o = {
-//         [sym1]() {},
-//         [sym2]() {}
-//     };
-//     test(o[sym1], "[foo]", "function() {}");
-//     test(o[sym2], "", "function() {}");
-// }
+section = "Object computed non-symbol named function property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: function bar() {},
+        }
+        test(o[value], "bar", "function bar() {}");
 
-// section = "Object computed symbol property with get/set function";
-// {
-//     let o = {
-//         get [sym1]() {},
-//         set [sym1](x) {},
-//         get [sym2]() {},
-//         set [sym2](x) {}
-//     };
-//     let desc = Object.getOwnPropertyDescriptor(o, sym1);
-//     test(desc.get, "get [foo]", "function() {}");
-//     test(desc.set, "set [foo]", "function(x) {}");
-// 
-//     desc = Object.getOwnPropertyDescriptor(o, sym2);
-//     test(desc.get, "get ", "function() {}");
-//     test(desc.set, "set ", "function(x) {}");
-// }
+        let bound = o[value].bind({});
+        test(bound, "bound bar", "function bar() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
 
+section = "Object computed non-symbol property with shorthand function";
+(function () {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]() {},
+        }
+        test(o[value], toString(value), "function() {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed non-symbol property with get/set function";
+(function () {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            get [value]() {},
+            set [value](x) {},
+        }
+
+        let desc = Object.getOwnPropertyDescriptor(o, value);
+        test(desc.get, "get " + value, "function() {}");
+        test(desc.set, "set " + value, "function(x) {}");
+
+        let bound = desc.get.bind({});
+        test(bound, "bound get " + toString(value), "function get " + toString(value) + "() { [native code] }");
+        bound = desc.set.bind({});
+        test(bound, "bound set " + toString(value), "function set " + toString(value) + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed symbol anonymous function property";
+(function() {
+    let values = symbolValues;
+    function runTest(value, expectedName) {
+        let o = {    
+            [value]: function() {},
+        }
+        test(o[value], expectedName, "function() {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
+section = "Object computed symbol named function property";
+(function() {
+    let values = symbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: function bar() {},
+        }
+        test(o[value], "bar", "function bar() {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound bar", "function bar() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v);
+})();
+
+section = "Object computed symbol property with shorthand function";
+(function() {
+    let values = symbolValues;
+    function runTest(value, expectedName) {
+        let o = {    
+            [value]() {},
+        }
+        test(o[value], expectedName, "function() {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
+section = "Object computed symbol property with get/set function";
+(function () {
+    let values = symbolValues;
+    function runTest(value, expectedName) {
+        let o = {    
+            get [value]() {},
+            set [value](x) {},
+        }
+
+        let desc = Object.getOwnPropertyDescriptor(o, value);
+        test(desc.get, "get " + expectedName, "function() {}");
+        test(desc.set, "set " + expectedName, "function(x) {}");
+
+        let bound = desc.get.bind({});
+        test(bound, "bound get " + expectedName, "function get " + expectedName + "() { [native code] }");
+        bound = desc.set.bind({});
+        test(bound, "bound set " + expectedName, "function set " + expectedName + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
 // Test functions in destructuring assignments.
 section = "destructuring assignment";
 {
@@ -649,8 +743,8 @@
 
     let o3 = { get [100]() {}, set [100](x){} };
     let desc3 = Object.getOwnPropertyDescriptor(o3, 100);
-    test(desc3.get, "get ", "function() {}");
-    test(desc3.set, "set ", "function(x) {}");
+    test(desc3.get, "get 100", "function() {}");
+    test(desc3.set, "set 100", "function(x) {}");
 
     section = "bound get/set function";
     {
@@ -673,9 +767,9 @@
         test(bound2, "bound set ", "function set () { [native code] }");
 
         bound1 = desc3.get.bind(o);
-        test(bound1, "bound get ", "function get () { [native code] }");
+        test(bound1, "bound get 100", "function get 100() { [native code] }");
         bound2 = desc3.set.bind(o);
-        test(bound2, "bound set ", "function set () { [native code] }");
+        test(bound2, "bound set 100", "function set 100() { [native code] }");
     }
 }
 
@@ -732,5 +826,209 @@
     test(bound, "bound ", "function () { [native code] }");    
 }
 
+section = "Object computed non-symbol anonymous class property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class {},
+        }
+        test(o[value], toString(value), "class {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed non-symbol named class property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class bar {},
+        }
+        test(o[value], "bar", "class bar {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound bar", "function bar() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed symbol anonymous class property";
+(function() {
+    let values = symbolValues;
+    function runTest(value, expectedName) {
+        let o = {    
+            [value]: class {},
+        }
+        test(o[value], expectedName, "class {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
+section = "Object computed symbol named class property";
+(function() {
+    let values = symbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class bar {},
+        }
+        test(o[value], "bar", "class bar {}");
+
+        let bound = o[value].bind({});
+        test(bound, "bound bar", "function bar() { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v);
+})();
+
+section = "Object computed non-symbol anonymous class (with name method) property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class { static name(){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed non-symbol named class (with name method) property";
+(function() {
+    let values = nonSymbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class bar { static name(){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed symbol anonymous class (with name method) property";
+(function() {
+    let values = symbolValues;
+    function runTest(value, expectedName) {
+        let o = {    
+            [value]: class { static name(){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
+section = "Object computed symbol named class (with name method) property";
+(function() {
+    let values = symbolValues;
+    function runTest(value) {
+        let o = {    
+            [value]: class bar { static name(){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v);
+})();
+
+section = "Object computed non-symbol anonymous class (with computed name method) property";
+(function() {
+    let values = nonSymbolValues;
+    let nameStr = "name";
+    function runTest(value) {
+        let o = {    
+            [value]: class { static [nameStr](){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed non-symbol named class (with computed name method) property";
+(function() {
+    let values = nonSymbolValues;
+    let nameStr = "name";
+    function runTest(value) {
+        let o = {    
+            [value]: class bar { static [nameStr](){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i]);
+})();
+
+section = "Object computed symbol anonymous class (with computed name method) property";
+(function() {
+    let values = symbolValues;
+    let nameStr = "name";
+    function runTest(value, expectedName) {
+        let o = {    
+            [value]: class { static [nameStr](){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v, values[i].name);
+})();
+
+section = "Object computed symbol named class (with computed name method) property";
+(function() {
+    let values = symbolValues;
+    let nameStr = "name";
+    function runTest(value) {
+        let o = {    
+            [value]: class bar { static [nameStr](){} },
+        }
+        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
+        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
+
+        let bound = o[value].bind({});
+        test(bound, "bound ", "function () { [native code] }");
+    }
+    for (var i = 0; i < values.length; i++)
+        runTest(values[i].v);
+})();
+
 if (failureCount)
     throw Error("Found " + failureCount + " failures:\n" + failures);

Modified: trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js (198287 => 198288)


--- trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js	2016-03-16 18:16:32 UTC (rev 198288)
@@ -4,7 +4,7 @@
 shouldBe("o.foo()", "10");
 shouldBe("typeof o.foo", "'function'");
 shouldBe("o.foo.length", "0");
-shouldBe("o.foo.name", "''");
+shouldBe("o.foo.name", "'foo'");
 shouldBe("o.foo.toString()", "'function () { return 10; }'");
 shouldBe("Object.getOwnPropertyDescriptor(o, 'foo').value", "o.foo");
 shouldBeTrue("Object.getOwnPropertyDescriptor(o, 'foo').enumerable");
@@ -15,7 +15,7 @@
 shouldBe("o.add(42, -10)", "32");
 shouldBe("typeof o.add", "'function'");
 shouldBe("o.add.length", "2");
-shouldBe("o.add.name", "''");
+shouldBe("o.add.name", "'add'");
 shouldBe("o.add.toString()", "'function (x, y) { return x + y; }'");
 
 shouldNotThrow("o = { [ (function() { return 'method'; })() ](x, y) { return x + y; } };");

Modified: trunk/Source/_javascript_Core/ChangeLog (198287 => 198288)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,3 +1,156 @@
+2016-03-16  Mark Lam  <[email protected]>
+
+        Add support for setting Function.name from computed properties.
+        https://bugs.webkit.org/show_bug.cgi?id=155437
+
+        Reviewed by Filip Pizlo.
+
+        In JS code, we can have initialization of computed properties with function and
+        class objects e.g.
+
+            var o = {
+                [x]: function() {},
+                [y]: class {}
+            }
+
+        The ES6 spec states that the function and class in the example above (being
+        anonymous) should take on the value of x and y respectively as their names:
+
+            o[x].name; // should be the "stringified" value of x.
+            o[y].name; // should be the "stringified" value of y.
+
+        To achieve this, we will now inject an op_set_function_name bytecode at property
+        initialization sites if:
+
+        1. the property assigned value is a function or class, and
+        2. the function and class is anonymous, and
+        3. if property assigned value is a class, it doesn't have a static method
+           that is statically named "name".
+
+        The op_set_function_name will result in JSFunction::setFunctionName() being
+        called on the target function / class before it is assigned to the property.
+        JSFunction::setFunctionName() will take care of:
+
+        1. computing the name to use from the value of the computed property name
+           e.g. x and y in the example above.
+
+           If the computed property name is not a symbol, then the function / class name
+           should be the toString() value of that computed property name.
+
+           If the computed property name is a symbol, then ...
+           a. if the Symbol has a defined description (e.g. Symbol("foo")), then the
+              function / class name should be "[<symbol description>]" e.g. "[foo]".
+           b. if the Symbol has an undefined description (e.g. Symbol()), then the
+              function / class name should be "".
+
+           Note: Symbol("") is not the same as Symbol().  The former has a defined
+           descriptor "", and hence, yields a function / class name of "[]".  The latter
+           yields a function / class name of "".
+
+        2. reifying the lazy name property with this function / class name.
+
+        op_set_function_name is named after the SetFunctionName internal function
+        in the ES6 spec that performs the above operation.
+
+        It is behaviorally correct to use op_set_function_name at every property
+        initialization site with computed property names.  However, we choose to not
+        emit the op_set_function_name bytecode when we already know that it will do
+        nothing i.e. when the target function / class is proven to already have a name or
+        name property.  This is done as an optimization to avoid unnecessary calls to
+        JSFunction::setFunctionName().
+
+        Note: we could further check if the class has a static method with a computed
+        name that is a constant string "name" and elide op_set_function_name there too.
+        However, we don't bother because this should be rare.  JSFunction::setFunctionName()
+        will still do the right thing.
+
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitNewFunction):
+        (JSC::BytecodeGenerator::emitSetFunctionNameIfNeeded):
+        (JSC::BytecodeGenerator::emitCall):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitBytecode):
+        (JSC::PropertyListNode::emitPutConstantProperty):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewFunction):
+        (JSC::DFG::SpeculativeJIT::compileSetFunctionName):
+        (JSC::DFG::SpeculativeJIT::compileForwardVarargs):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+        (JSC::FTL::DFG::LowerDFGToB3::compileSetFunctionName):
+        (JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_to_primitive):
+        (JSC::JIT::emit_op_set_function_name):
+        (JSC::JIT::emit_op_strcat):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emitSlow_op_to_primitive):
+        (JSC::JIT::emit_op_set_function_name):
+        (JSC::JIT::emit_op_strcat):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::handleHostCall):
+        * llint/LLIntSlowPaths.h:
+        * llint/LowLevelInterpreter.asm:
+        * parser/Nodes.cpp:
+        (JSC::FunctionNode::finishParsing):
+        (JSC::PropertyListNode::hasStaticallyNamedProperty):
+        (JSC::VariableEnvironmentNode::VariableEnvironmentNode):
+        * parser/Nodes.h:
+        * runtime/JSFunction.cpp:
+        (JSC::getCalculatedDisplayName):
+        (JSC::JSFunction::setFunctionName):
+        (JSC::JSFunction::reifyLength):
+        (JSC::JSFunction::reifyName):
+        * runtime/JSFunction.h:
+        * tests/es6.yaml:
+        * tests/stress/computed-function-names.js: Added.
+        (toKeyString):
+        (toFuncName):
+        (shouldBe):
+        (return.propKey):
+
 2016-03-16  Yusuke Suzuki  <[email protected]>
 
         [ES6] Reflect.set with receiver

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-03-16 18:16:32 UTC (rev 198288)
@@ -94,6 +94,7 @@
             { "name" : "op_new_generator_func", "length" : 4 },
             { "name" : "op_new_generator_func_exp", "length" : 4 },
             { "name" : "op_new_arrow_func_exp", "length" : 4 },
+            { "name" : "op_set_function_name", "length" : 3 },
             { "name" : "op_call", "length" : 9 },
             { "name" : "op_tail_call", "length" : 9 },
             { "name" : "op_call_eval", "length" : 9 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -85,6 +85,7 @@
     case op_jngreater:
     case op_jngreatereq:
     case op_jless:
+    case op_set_function_name:
     case op_copy_rest: {
         ASSERT(opcodeLengths[opcodeID] > 2);
         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
@@ -322,6 +323,7 @@
     case op_profile_type:
     case op_profile_control_flow:
     case op_put_to_arguments:
+    case op_set_function_name:
     case op_watchdog:
 #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
         FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1371,6 +1371,13 @@
             out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
             break;
         }
+        case op_set_function_name: {
+            int funcReg = (++it)->u.operand;
+            int nameReg = (++it)->u.operand;
+            printLocationAndOp(out, exec, location, it, "set_function_name");
+            out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data());
+            break;
+        }
         case op_call: {
             printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
             break;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -2820,6 +2820,28 @@
     return dst;
 }
 
+void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name)
+{
+    if (valueNode->isFuncExprNode()) {
+        FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(valueNode)->metadata();
+        if (!metadata->ecmaName().isNull())
+            return;
+    } else if (valueNode->isClassExprNode()) {
+        ClassExprNode* classExprNode = static_cast<ClassExprNode*>(valueNode);
+        if (!classExprNode->ecmaName().isNull())
+            return;
+        if (classExprNode->hasStaticProperty(m_vm->propertyNames->name))
+            return;
+    } else
+        return;
+
+    // FIXME: We should use an op_call to an internal function here instead.
+    // https://bugs.webkit.org/show_bug.cgi?id=155547
+    emitOpcode(op_set_function_name);
+    instructions().append(value->index());
+    instructions().append(name->index());
+}
+
 RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
     return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -522,6 +522,8 @@
         RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
 
+        void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name);
+
         RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
         RegisterID* emitMoveEmptyValue(RegisterID* dst);
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -511,6 +511,7 @@
                 // Computed accessors.
                 if (node->m_type & PropertyNode::Computed) {
                     RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
+                    generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
                     if (node->m_type & PropertyNode::Getter)
                         generator.emitPutGetterByVal(dst, propertyName.get(), attribute, value.get());
                     else
@@ -601,6 +602,7 @@
         return;
     }
     RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
+    generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
     generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -2653,6 +2653,11 @@
         break;
     }
 
+    case SetFunctionName: {
+        clobberWorld(node->origin.semantic, clobberLimit);
+        break;
+    }
+
     case StoreBarrier: {
         filter(node->child1(), SpecCell);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -4636,6 +4636,13 @@
             }
         }
 
+        case op_set_function_name: {
+            Node* func = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* name = get(VirtualRegister(currentInstruction[2].u.operand));
+            addToGraph(SetFunctionName, func, name);
+            NEXT_OPCODE(op_set_function_name);
+        }
+
         case op_typeof: {
             set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(TypeOf, get(VirtualRegister(currentInstruction[2].u.operand))));

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -219,6 +219,7 @@
     case op_new_generator_func:
     case op_new_generator_func_exp:
     case op_new_arrow_func_exp:
+    case op_set_function_name:
     case op_create_lexical_environment:
     case op_get_parent_scope:
     case op_catch:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -444,6 +444,7 @@
     case ToPrimitive:
     case In:
     case ValueAdd:
+    case SetFunctionName:
         read(World);
         write(Heap);
         return;

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -263,6 +263,7 @@
     case ToIndexString:
     case MaterializeNewObject:
     case MaterializeCreateActivation:
+    case SetFunctionName:
     case StrCat:
     case StringReplace:
         return true;

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1439,6 +1439,14 @@
             break;
         }
 
+        case SetFunctionName: {
+            // The first child is guaranteed to be a cell because op_set_function_name is only used
+            // on a newly instantiated function object (the first child).
+            fixEdge<KnownCellUse>(node->child1());
+            fixEdge<UntypedUse>(node->child2());
+            break;
+        }
+
         case CopyRest: {
             fixEdge<KnownCellUse>(node->child1());
             fixEdge<KnownInt32Use>(node->child2());

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -308,6 +308,7 @@
     macro(In, NodeResultBoolean | NodeMustGenerate) \
     macro(ProfileType, NodeMustGenerate) \
     macro(ProfileControlFlow, NodeMustGenerate) \
+    macro(SetFunctionName, NodeMustGenerate) \
     \
     macro(CreateActivation, NodeResultJS) \
     \

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -752,6 +752,7 @@
         case ThrowReferenceError:
         case ForceOSRExit:
         case SetArgument:
+        case SetFunctionName:
         case CheckStructure:
         case CheckCell:
         case CheckNotEmpty:

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -262,6 +262,7 @@
     case LogicalNot:
     case ToPrimitive:
     case ToString:
+    case SetFunctionName:
     case StrCat:
     case CallStringConstructor:
     case NewStringObject:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -5597,6 +5597,20 @@
     cellResult(resultGPR, node);
 }
 
+void SpeculativeJIT::compileSetFunctionName(Node* node)
+{
+    SpeculateCellOperand func(this, node->child1());
+    GPRReg funcGPR = func.gpr();
+    JSValueOperand nameValue(this, node->child2());
+    JSValueRegs nameValueRegs = nameValue.jsValueRegs();
+
+    flushRegisters();
+    callOperation(operationSetFunctionName, funcGPR, nameValueRegs);
+    m_jit.exceptionCheck();
+
+    noResult(node);
+}
+
 void SpeculativeJIT::compileForwardVarargs(Node* node)
 {
     LoadVarargsData* data = ""

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1548,6 +1548,11 @@
         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(V_JITOperation_ECJ operation, GPRReg arg1, JSValueRegs arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR());
+        return appendCall(operation);
+    }
     JITCompiler::Call callOperation(V_JITOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
@@ -1927,6 +1932,11 @@
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, arg2Payload, TrustedImm32(JSValue::CellTag), TrustedImmPtr(uid));
         return appendCall(operation);
     }
+    JITCompiler::Call callOperation(V_JITOperation_ECJ operation, GPRReg arg1, JSValueRegs arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR());
+        return appendCall(operation);
+    }
     JITCompiler::Call callOperation(V_JITOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
@@ -2379,6 +2389,7 @@
     void compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
     template <typename ClassType> void compileNewFunctionCommon(GPRReg, Structure*, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*, ptrdiff_t, ptrdiff_t, ptrdiff_t);
     void compileNewFunction(Node*);
+    void compileSetFunctionName(Node*);
     void compileForwardVarargs(Node*);
     void compileCreateActivation(Node*);
     void compileCreateDirectArguments(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -4610,6 +4610,10 @@
         compileNewFunction(node);
         break;
 
+    case SetFunctionName:
+        compileSetFunctionName(node);
+        break;
+
     case In:
         compileIn(node);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -4594,6 +4594,10 @@
         compileNewFunction(node);
         break;
 
+    case SetFunctionName:
+        compileSetFunctionName(node);
+        break;
+
     case In:
         compileIn(node);
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/dfg/DFGStoreBarrierInsertionPhase.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -283,6 +283,11 @@
                 break;
             }
                 
+            case SetFunctionName: {
+                considerBarrier(m_node->child1(), m_node->child2());
+                break;
+            }
+
             default:
                 break;
             }

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -227,6 +227,7 @@
     case StringReplace:
     case GetRegExpObjectLastIndex:
     case SetRegExpObjectLastIndex:
+    case SetFunctionName:
         // These are OK.
         break;
 

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -926,6 +926,9 @@
         case NewRegexp:
             compileNewRegexp();
             break;
+        case SetFunctionName:
+            compileSetFunctionName();
+            break;
         case StringReplace:
             compileStringReplace();
             break;
@@ -6548,6 +6551,12 @@
         setJSValue(result);
     }
 
+    void compileSetFunctionName()
+    {
+        vmCall(m_out.voidType, m_out.operation(operationSetFunctionName), m_callFrame,
+            lowCell(m_node->child1()), lowJSValue(m_node->child2()));
+    }
+    
     void compileStringReplace()
     {
         if (m_node->child1().useKind() == StringUse

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2012-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -298,6 +298,7 @@
         DEFINE_OP(op_rshift)
         DEFINE_OP(op_unsigned)
         DEFINE_OP(op_urshift)
+        DEFINE_OP(op_set_function_name)
         DEFINE_OP(op_strcat)
         DEFINE_OP(op_stricteq)
         DEFINE_OP(op_sub)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -570,6 +570,7 @@
         void emit_op_put_setter_by_val(Instruction*);
         void emit_op_ret(Instruction*);
         void emit_op_rshift(Instruction*);
+        void emit_op_set_function_name(Instruction*);
         void emit_op_strcat(Instruction*);
         void emit_op_stricteq(Instruction*);
         void emit_op_sub(Instruction*);
@@ -791,8 +792,10 @@
         MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, int32_t, RegisterID);
         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, UniquedStringImpl*);
         MacroAssembler::Call callOperation(V_JITOperation_ECIZJJ, RegisterID, UniquedStringImpl*, int32_t, RegisterID, RegisterID);
+        MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID);
 #else
         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, UniquedStringImpl*);
+        MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID, RegisterID);
 #endif
         MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID);
         MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, ArrayProfile*);

Modified: trunk/Source/_javascript_Core/jit/JITInlines.h (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JITInlines.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JITInlines.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012, 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -558,6 +558,12 @@
     return appendCallWithExceptionCheck(operation);
 }
 
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJ operation, RegisterID arg1, RegisterID arg2)
+{
+    setupArgumentsWithExecState(arg1, arg2);
+    return appendCallWithExceptionCheck(operation);
+}
+
 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJZC operation, RegisterID regOp1, RegisterID regOp2, int32_t op3, RegisterID regOp4)
 {
     setupArgumentsWithExecState(regOp1, regOp2, TrustedImm32(op3), regOp4);
@@ -692,6 +698,12 @@
     return appendCallWithExceptionCheck(operation);
 }
 
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJ operation, RegisterID arg1, RegisterID arg2Tag, RegisterID arg2Payload)
+{
+    setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+    return appendCallWithExceptionCheck(operation);
+}
+
 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJZC operation, RegisterID arg1, RegisterID arg2Tag, RegisterID arg2Payload, int32_t arg3, RegisterID arg4)
 {
     setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3), arg4);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -296,6 +296,13 @@
 
 }
 
+void JIT::emit_op_set_function_name(Instruction* currentInstruction)
+{
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+    emitGetVirtualRegister(currentInstruction[2].u.operand, regT1);
+    callOperation(operationSetFunctionName, regT0, regT1);
+}
+
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_strcat);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -395,6 +395,15 @@
     slowPathCall.call();
 }
 
+void JIT::emit_op_set_function_name(Instruction* currentInstruction)
+{
+    int func = currentInstruction[1].u.operand;
+    int name = currentInstruction[2].u.operand;
+    emitLoadPayload(func, regT1);
+    emitLoad(name, regT3, regT2);
+    callOperation(operationSetFunctionName, regT1, regT3, regT2);
+}
+
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_strcat);

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1017,6 +1017,13 @@
     return operationNewFunctionCommon<JSGeneratorFunction>(exec, scope, functionExecutable, true);
 }
 
+void JIT_OPERATION operationSetFunctionName(ExecState* exec, JSCell* funcCell, EncodedJSValue encodedName)
+{
+    JSFunction* func = jsCast<JSFunction*>(funcCell);
+    JSValue name = JSValue::decode(encodedName);
+    func->setFunctionName(exec, name);
+}
+
 JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (198287 => 198288)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -225,6 +225,7 @@
 typedef void JIT_OPERATION (*V_JITOperation_ECIZJJ)(ExecState*, JSCell*, UniquedStringImpl*, int32_t, EncodedJSValue, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_ECJZC)(ExecState*, JSCell*, EncodedJSValue, int32_t, JSCell*);
 typedef void JIT_OPERATION (*V_JITOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*);
+typedef void JIT_OPERATION (*V_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
 typedef void JIT_OPERATION (*V_JITOperation_ECPSPS)(ExecState*, JSCell*, void*, size_t, void*, size_t);
 typedef void JIT_OPERATION (*V_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
@@ -333,6 +334,7 @@
 EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState*, JSScope*, JSCell*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewGeneratorFunction(ExecState*, JSScope*, JSCell*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint(ExecState*, JSScope*, JSCell*) WTF_INTERNAL;
+void JIT_OPERATION operationSetFunctionName(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationNewObject(ExecState*, Structure*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
 UnusedPtr JIT_OPERATION operationHandleWatchdogTimer(ExecState*) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1083,6 +1083,15 @@
     LLINT_RETURN(JSFunction::create(vm, executable, scope));
 }
 
+LLINT_SLOW_PATH_DECL(slow_path_set_function_name)
+{
+    LLINT_BEGIN();
+    JSFunction* func = jsCast<JSFunction*>(LLINT_OP(1).Register::unboxedCell());
+    JSValue name = LLINT_OP_C(2).Register::jsValue();
+    func->setFunctionName(exec, name);
+    LLINT_END();
+}
+
 static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
 {
     UNUSED_PARAM(pc);

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h (198287 => 198288)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2014, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -102,6 +102,7 @@
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_generator_func);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_generator_func_exp);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_arrow_func_exp);
+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_set_function_name);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct);
 LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_size_frame_for_varargs);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (198287 => 198288)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,4 +1,4 @@
-# Copyright (C) 2011-2015 Apple Inc. All rights reserved.
+# Copyright (C) 2011-2016 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -1471,6 +1471,11 @@
     callSlowPath(_llint_slow_path_new_arrow_func_exp)
     dispatch(4)
 
+_llint_op_set_function_name:
+    traceExecution()
+    callSlowPath(_llint_slow_path_set_function_name)
+    dispatch(3)
+
 _llint_op_call:
     traceExecution()
     arrayProfileForCall()

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -1,7 +1,7 @@
 /*
 *  Copyright (C) 1999-2002 Harri Porten ([email protected])
 *  Copyright (C) 2001 Peter Kelly ([email protected])
-*  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+*  Copyright (C) 2003-2009, 2013, 2016 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Cameron Zwarich ([email protected])
 *  Copyright (C) 2007 Maks Orlovich
 *  Copyright (C) 2007 Eric Seidel <[email protected]>
@@ -196,6 +196,18 @@
     m_functionMode = functionMode;
 }
 
+bool PropertyListNode::hasStaticallyNamedProperty(const Identifier& propName)
+{
+    PropertyListNode* list = this;
+    while (list) {
+        const Identifier* currentNodeName = list->m_node->name();
+        if (currentNodeName && *currentNodeName == propName)
+            return true;
+        list = list->m_next;
+    }
+    return false;
+}
+
 VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables)
 {
     m_lexicalVariables.swap(lexicalVariables);

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (198287 => 198288)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -648,6 +648,8 @@
         PropertyListNode(const JSTokenLocation&, PropertyNode*);
         PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*);
 
+        bool hasStaticallyNamedProperty(const Identifier& propName);
+
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
         void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&);
@@ -1984,6 +1986,8 @@
         const Identifier& ecmaName() { return m_ecmaName ? *m_ecmaName : m_name; }
         void setEcmaName(const Identifier& name) { m_ecmaName = m_name.isNull() ? &name : &m_name; }
 
+        bool hasStaticProperty(const Identifier& propName) { return m_staticMethods ? m_staticMethods->hasStaticallyNamedProperty(propName) : false; }
+
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (198287 => 198288)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-03-16 18:16:32 UTC (rev 198288)
@@ -571,6 +571,34 @@
     return emptyString();
 }
 
+void JSFunction::setFunctionName(ExecState* exec, JSValue value)
+{
+    // The "name" property may have been already been defined as part of a property list in an
+    // object literal (and therefore reified).
+    if (hasReifiedName())
+        return;
+
+    ASSERT(!isHostFunction());
+    ASSERT(jsExecutable()->ecmaName().isNull());
+    String name;
+    if (value.isSymbol()) {
+        SymbolImpl* uid = asSymbol(value)->privateName().uid();
+        if (uid->isNullSymbol())
+            name = emptyString();
+        else
+            name = makeString("[", String(asSymbol(value)->privateName().uid()), ']');
+    } else {
+        VM& vm = exec->vm();
+        JSString* jsStr = value.toString(exec);
+        if (vm.exception())
+            return;
+        name = jsStr->value(exec);
+        if (vm.exception())
+            return;
+    }
+    reifyName(exec, name);
+}
+
 void JSFunction::reifyLength(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -588,6 +616,12 @@
 
 void JSFunction::reifyName(ExecState* exec)
 {
+    String name = jsExecutable()->ecmaName().string();
+    reifyName(exec, name);
+}
+
+void JSFunction::reifyName(ExecState* exec, String name)
+{
     VM& vm = exec->vm();
     FunctionRareData* rareData = this->rareData(vm);
 
@@ -596,8 +630,6 @@
     unsigned initialAttributes = DontEnum | ReadOnly;
     const Identifier& propID = exec->propertyNames().name;
 
-    String name = jsExecutable()->ecmaName().string();
-
     if (jsExecutable()->isGetter())
         name = makeString("get ", name);
     else if (jsExecutable()->isSetter())

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (198287 => 198288)


--- trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-03-16 18:16:32 UTC (rev 198288)
@@ -150,6 +150,8 @@
     JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
     bool isClassConstructorFunction() const;
 
+    void setFunctionName(ExecState*, JSValue name);
+
 protected:
     JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
     JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
@@ -191,6 +193,7 @@
     bool hasReifiedName() const;
     void reifyLength(ExecState*);
     void reifyName(ExecState*);
+    void reifyName(ExecState*, String name);
     void reifyLazyPropertyIfNeeded(ExecState*, PropertyName propertyName);
 
     friend class LLIntOffsetsExtractor;

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (198287 => 198288)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-16 17:20:11 UTC (rev 198287)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-16 18:16:32 UTC (rev 198288)
@@ -807,7 +807,7 @@
 - path: es6/function_name_property_shorthand_methods_no_lexical_binding.js
   cmd: runES6 :fail
 - path: es6/function_name_property_symbol-keyed_methods.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/function_name_property_variables_class.js
   cmd: runES6 :normal
 - path: es6/function_name_property_variables_function.js

Added: trunk/Source/_javascript_Core/tests/stress/computed-function-names.js (0 => 198288)


--- trunk/Source/_javascript_Core/tests/stress/computed-function-names.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/computed-function-names.js	2016-03-16 18:16:32 UTC (rev 198288)
@@ -0,0 +1,68 @@
+let nullSymbol = Symbol();
+
+let propKeys = [
+     "foo", "", undefined, null, true, false, 0, 10, 1234.567,
+     Symbol("foo"), Symbol(""), nullSymbol,
+];
+
+function toKeyString(x) {
+    if (typeof x === "string")
+        return '"' + x + '"';
+    if (typeof x === "symbol")
+        return x.toString();
+    return "" + x;
+}
+
+function toFuncName(x) {
+    if (typeof x === "symbol") {
+        if (x !== nullSymbol) {
+            let str = x.toString();
+            let key = str.slice(7, str.length - 1);
+            return "[" + key + "]";
+        }
+        return "";
+    }
+    return "" + x;
+}
+
+function shouldBe(title, actual, expected) {
+    if (actual !== expected)
+        throw Error(title + ": actual:" + actual + " expected:" + expected);
+}
+
+function makeObj(propKey, classMethodName) {
+    return {
+        [propKey]: class { static [classMethodName](){} },
+    };
+}
+noInline(makeObj);
+
+for (var i = 0; i < 1000; i++) {
+    for (var k = 0; k < propKeys.length; k++) {
+        let key = propKeys[k];
+        let o = makeObj(key, "prop");
+        shouldBe("typeof o[" + toKeyString(key) + "].name", typeof o[key].name, "string");
+        shouldBe("o[" + toKeyString(key) + "].name", o[key].name, toFuncName(key));
+    }
+
+    for (var k = 0; k < propKeys.length; k++) {
+        let key = propKeys[k];
+        let o = makeObj(key, "name");
+        shouldBe("typeof o[" + toKeyString(key) + "].name", typeof o[key], "function");
+    }
+
+    for (var k = 0; k < propKeys.length; k++) {
+        let key = propKeys[k];
+        let prop = { toString() { return "prop" } };
+        let o = makeObj(key, prop);
+        shouldBe("typeof o[" + toKeyString(key) + "].name", typeof o[key].name, "string");
+        shouldBe("o[" + toKeyString(key) + "].name", o[key].name, toFuncName(key));
+    }
+
+    for (var k = 0; k < propKeys.length; k++) {
+        let key = propKeys[k];
+        let prop = { toString() { return "name" } };
+        let o = makeObj(key, prop);
+        shouldBe("typeof o[" + toKeyString(key) + "].name", typeof o[key], "function");
+    }
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to