Changeset 198288 in webkit


Ignore:
Timestamp:
Mar 16, 2016 11:16:32 AM (8 years ago)
Author:
mark.lam@apple.com
Message:

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

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

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 ...

  1. if the Symbol has a defined description (e.g. Symbol("foo")), then the function / class name should be "[<symbol description>]" e.g. "[foo]".
  2. 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 "".

  1. 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.
Location:
trunk
Files:
1 added
42 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r198287 r198288  
     12016-03-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add support for setting Function.name from computed properties.
     4        https://bugs.webkit.org/show_bug.cgi?id=155437
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * js/object-literal-computed-methods-expected.txt:
     9        - Exercise op_set_function_name at all tiers.
     10
     11        * js/script-tests/function-toString-vs-name.js:
     12        - Added tests for computed properties.
     13
     14        * js/script-tests/object-literal-computed-methods.js:
     15        - rebased results.
     16
    1172016-03-16  Ryan Haddad  <ryanhaddad@apple.com>
    218
  • trunk/LayoutTests/js/object-literal-computed-methods-expected.txt

    r181901 r198288  
    88PASS typeof o.foo is 'function'
    99PASS o.foo.length is 0
    10 PASS o.foo.name is ''
     10PASS o.foo.name is 'foo'
    1111PASS o.foo.toString() is 'function () { return 10; }'
    1212PASS Object.getOwnPropertyDescriptor(o, 'foo').value is o.foo
     
    1818PASS typeof o.add is 'function'
    1919PASS o.add.length is 2
    20 PASS o.add.name is ''
     20PASS o.add.name is 'add'
    2121PASS o.add.toString() is 'function (x, y) { return x + y; }'
    2222PASS o = { [ (function() { return 'method'; })() ](x, y) { return x + y; } }; did not throw exception.
  • trunk/LayoutTests/js/script-tests/function-toString-vs-name.js

    r198042 r198288  
    55let failures = "";
    66let failureCount = 0;
     7
     8let nonSymbolValues = [ "foo", "", undefined, null, true, false, 0, 10, 1234.567 ];
     9let symbolValues = [
     10    { v: Symbol("foo"), name: "[foo]" },
     11    { v: Symbol(""), name: "[]" },
     12    { v: Symbol(), name: "" },
     13];
    714
    815function isWhiteSpace(string) {
     
    519526})();
    520527
    521 // FIXME: Uncomment these when we've added support for Function.name of computed properties.
    522 // section = "Object computed string property";
    523 // {
    524 //     let str1 = "foo";
    525 //     let str2 = "";
    526 //     let o = {   
    527 //         [str1]: function() {},
    528 //         [str2]: function() {}
    529 //     };
    530 //     test(o[str1], "foo", "function() {}");
    531 //     test(o[str2], "", "function() {}");
    532 // }
    533 //
    534 // let sym1 = Symbol("foo");
    535 // let sym2 = Symbol();
    536 
    537 // section = "Object computed symbol property";
    538 // {
    539 //     let o = {   
    540 //         [sym1]: function() {},
    541 //         [sym2]: function() {}
    542 //     };
    543 //     test(o[sym1], "[foo]", "function() {}");
    544 //     test(o[sym2], "", "function() {}");
    545 // }
    546 
    547 // section = "Object computed symbol property with shorthand function";
    548 // {
    549 //     let o = {
    550 //         [sym1]() {},
    551 //         [sym2]() {}
    552 //     };
    553 //     test(o[sym1], "[foo]", "function() {}");
    554 //     test(o[sym2], "", "function() {}");
    555 // }
    556 
    557 // section = "Object computed symbol property with get/set function";
    558 // {
    559 //     let o = {
    560 //         get [sym1]() {},
    561 //         set [sym1](x) {},
    562 //         get [sym2]() {},
    563 //         set [sym2](x) {}
    564 //     };
    565 //     let desc = Object.getOwnPropertyDescriptor(o, sym1);
    566 //     test(desc.get, "get [foo]", "function() {}");
    567 //     test(desc.set, "set [foo]", "function(x) {}");
    568 //
    569 //     desc = Object.getOwnPropertyDescriptor(o, sym2);
    570 //     test(desc.get, "get ", "function() {}");
    571 //     test(desc.set, "set ", "function(x) {}");
    572 // }
     528section = "Object computed non-symbol anonymous function property";
     529(function() {
     530    let values = nonSymbolValues;
     531    function runTest(value) {
     532        let o = {   
     533            [value]: function() {},
     534        }
     535        test(o[value], toString(value), "function() {}");
     536
     537        let bound = o[value].bind({});
     538        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
     539    }
     540    for (var i = 0; i < values.length; i++)
     541        runTest(values[i]);
     542})();
     543
     544section = "Object computed non-symbol named function property";
     545(function() {
     546    let values = nonSymbolValues;
     547    function runTest(value) {
     548        let o = {   
     549            [value]: function bar() {},
     550        }
     551        test(o[value], "bar", "function bar() {}");
     552
     553        let bound = o[value].bind({});
     554        test(bound, "bound bar", "function bar() { [native code] }");
     555    }
     556    for (var i = 0; i < values.length; i++)
     557        runTest(values[i]);
     558})();
     559
     560section = "Object computed non-symbol property with shorthand function";
     561(function () {
     562    let values = nonSymbolValues;
     563    function runTest(value) {
     564        let o = {   
     565            [value]() {},
     566        }
     567        test(o[value], toString(value), "function() {}");
     568
     569        let bound = o[value].bind({});
     570        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
     571    }
     572    for (var i = 0; i < values.length; i++)
     573        runTest(values[i]);
     574})();
     575
     576section = "Object computed non-symbol property with get/set function";
     577(function () {
     578    let values = nonSymbolValues;
     579    function runTest(value) {
     580        let o = {   
     581            get [value]() {},
     582            set [value](x) {},
     583        }
     584
     585        let desc = Object.getOwnPropertyDescriptor(o, value);
     586        test(desc.get, "get " + value, "function() {}");
     587        test(desc.set, "set " + value, "function(x) {}");
     588
     589        let bound = desc.get.bind({});
     590        test(bound, "bound get " + toString(value), "function get " + toString(value) + "() { [native code] }");
     591        bound = desc.set.bind({});
     592        test(bound, "bound set " + toString(value), "function set " + toString(value) + "() { [native code] }");
     593    }
     594    for (var i = 0; i < values.length; i++)
     595        runTest(values[i]);
     596})();
     597
     598section = "Object computed symbol anonymous function property";
     599(function() {
     600    let values = symbolValues;
     601    function runTest(value, expectedName) {
     602        let o = {   
     603            [value]: function() {},
     604        }
     605        test(o[value], expectedName, "function() {}");
     606
     607        let bound = o[value].bind({});
     608        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
     609    }
     610    for (var i = 0; i < values.length; i++)
     611        runTest(values[i].v, values[i].name);
     612})();
     613
     614section = "Object computed symbol named function property";
     615(function() {
     616    let values = symbolValues;
     617    function runTest(value) {
     618        let o = {   
     619            [value]: function bar() {},
     620        }
     621        test(o[value], "bar", "function bar() {}");
     622
     623        let bound = o[value].bind({});
     624        test(bound, "bound bar", "function bar() { [native code] }");
     625    }
     626    for (var i = 0; i < values.length; i++)
     627        runTest(values[i].v);
     628})();
     629
     630section = "Object computed symbol property with shorthand function";
     631(function() {
     632    let values = symbolValues;
     633    function runTest(value, expectedName) {
     634        let o = {   
     635            [value]() {},
     636        }
     637        test(o[value], expectedName, "function() {}");
     638
     639        let bound = o[value].bind({});
     640        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
     641    }
     642    for (var i = 0; i < values.length; i++)
     643        runTest(values[i].v, values[i].name);
     644})();
     645
     646section = "Object computed symbol property with get/set function";
     647(function () {
     648    let values = symbolValues;
     649    function runTest(value, expectedName) {
     650        let o = {   
     651            get [value]() {},
     652            set [value](x) {},
     653        }
     654
     655        let desc = Object.getOwnPropertyDescriptor(o, value);
     656        test(desc.get, "get " + expectedName, "function() {}");
     657        test(desc.set, "set " + expectedName, "function(x) {}");
     658
     659        let bound = desc.get.bind({});
     660        test(bound, "bound get " + expectedName, "function get " + expectedName + "() { [native code] }");
     661        bound = desc.set.bind({});
     662        test(bound, "bound set " + expectedName, "function set " + expectedName + "() { [native code] }");
     663    }
     664    for (var i = 0; i < values.length; i++)
     665        runTest(values[i].v, values[i].name);
     666})();
    573667
    574668// Test functions in destructuring assignments.
     
    650744    let o3 = { get [100]() {}, set [100](x){} };
    651745    let desc3 = Object.getOwnPropertyDescriptor(o3, 100);
    652     test(desc3.get, "get ", "function() {}");
    653     test(desc3.set, "set ", "function(x) {}");
     746    test(desc3.get, "get 100", "function() {}");
     747    test(desc3.set, "set 100", "function(x) {}");
    654748
    655749    section = "bound get/set function";
     
    674768
    675769        bound1 = desc3.get.bind(o);
    676         test(bound1, "bound get ", "function get () { [native code] }");
     770        test(bound1, "bound get 100", "function get 100() { [native code] }");
    677771        bound2 = desc3.set.bind(o);
    678         test(bound2, "bound set ", "function set () { [native code] }");
     772        test(bound2, "bound set 100", "function set 100() { [native code] }");
    679773    }
    680774}
     
    733827}
    734828
     829section = "Object computed non-symbol anonymous class property";
     830(function() {
     831    let values = nonSymbolValues;
     832    function runTest(value) {
     833        let o = {   
     834            [value]: class {},
     835        }
     836        test(o[value], toString(value), "class {}");
     837
     838        let bound = o[value].bind({});
     839        test(bound, "bound " + toString(value), "function " + toString(value) + "() { [native code] }");
     840    }
     841    for (var i = 0; i < values.length; i++)
     842        runTest(values[i]);
     843})();
     844
     845section = "Object computed non-symbol named class property";
     846(function() {
     847    let values = nonSymbolValues;
     848    function runTest(value) {
     849        let o = {   
     850            [value]: class bar {},
     851        }
     852        test(o[value], "bar", "class bar {}");
     853
     854        let bound = o[value].bind({});
     855        test(bound, "bound bar", "function bar() { [native code] }");
     856    }
     857    for (var i = 0; i < values.length; i++)
     858        runTest(values[i]);
     859})();
     860
     861section = "Object computed symbol anonymous class property";
     862(function() {
     863    let values = symbolValues;
     864    function runTest(value, expectedName) {
     865        let o = {   
     866            [value]: class {},
     867        }
     868        test(o[value], expectedName, "class {}");
     869
     870        let bound = o[value].bind({});
     871        test(bound, "bound " + expectedName, "function " + expectedName + "() { [native code] }");
     872    }
     873    for (var i = 0; i < values.length; i++)
     874        runTest(values[i].v, values[i].name);
     875})();
     876
     877section = "Object computed symbol named class property";
     878(function() {
     879    let values = symbolValues;
     880    function runTest(value) {
     881        let o = {   
     882            [value]: class bar {},
     883        }
     884        test(o[value], "bar", "class bar {}");
     885
     886        let bound = o[value].bind({});
     887        test(bound, "bound bar", "function bar() { [native code] }");
     888    }
     889    for (var i = 0; i < values.length; i++)
     890        runTest(values[i].v);
     891})();
     892
     893section = "Object computed non-symbol anonymous class (with name method) property";
     894(function() {
     895    let values = nonSymbolValues;
     896    function runTest(value) {
     897        let o = {   
     898            [value]: class { static name(){} },
     899        }
     900        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     901        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
     902
     903        let bound = o[value].bind({});
     904        test(bound, "bound ", "function () { [native code] }");
     905    }
     906    for (var i = 0; i < values.length; i++)
     907        runTest(values[i]);
     908})();
     909
     910section = "Object computed non-symbol named class (with name method) property";
     911(function() {
     912    let values = nonSymbolValues;
     913    function runTest(value) {
     914        let o = {   
     915            [value]: class bar { static name(){} },
     916        }
     917        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     918        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
     919
     920        let bound = o[value].bind({});
     921        test(bound, "bound ", "function () { [native code] }");
     922    }
     923    for (var i = 0; i < values.length; i++)
     924        runTest(values[i]);
     925})();
     926
     927section = "Object computed symbol anonymous class (with name method) property";
     928(function() {
     929    let values = symbolValues;
     930    function runTest(value, expectedName) {
     931        let o = {   
     932            [value]: class { static name(){} },
     933        }
     934        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     935        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static name(){} }");
     936
     937        let bound = o[value].bind({});
     938        test(bound, "bound ", "function () { [native code] }");
     939    }
     940    for (var i = 0; i < values.length; i++)
     941        runTest(values[i].v, values[i].name);
     942})();
     943
     944section = "Object computed symbol named class (with name method) property";
     945(function() {
     946    let values = symbolValues;
     947    function runTest(value) {
     948        let o = {   
     949            [value]: class bar { static name(){} },
     950        }
     951        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     952        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static name(){} }");
     953
     954        let bound = o[value].bind({});
     955        test(bound, "bound ", "function () { [native code] }");
     956    }
     957    for (var i = 0; i < values.length; i++)
     958        runTest(values[i].v);
     959})();
     960
     961section = "Object computed non-symbol anonymous class (with computed name method) property";
     962(function() {
     963    let values = nonSymbolValues;
     964    let nameStr = "name";
     965    function runTest(value) {
     966        let o = {   
     967            [value]: class { static [nameStr](){} },
     968        }
     969        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     970        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
     971
     972        let bound = o[value].bind({});
     973        test(bound, "bound ", "function () { [native code] }");
     974    }
     975    for (var i = 0; i < values.length; i++)
     976        runTest(values[i]);
     977})();
     978
     979section = "Object computed non-symbol named class (with computed name method) property";
     980(function() {
     981    let values = nonSymbolValues;
     982    let nameStr = "name";
     983    function runTest(value) {
     984        let o = {   
     985            [value]: class bar { static [nameStr](){} },
     986        }
     987        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     988        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
     989
     990        let bound = o[value].bind({});
     991        test(bound, "bound ", "function () { [native code] }");
     992    }
     993    for (var i = 0; i < values.length; i++)
     994        runTest(values[i]);
     995})();
     996
     997section = "Object computed symbol anonymous class (with computed name method) property";
     998(function() {
     999    let values = symbolValues;
     1000    let nameStr = "name";
     1001    function runTest(value, expectedName) {
     1002        let o = {   
     1003            [value]: class { static [nameStr](){} },
     1004        }
     1005        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     1006        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class { static [nameStr](){} }");
     1007
     1008        let bound = o[value].bind({});
     1009        test(bound, "bound ", "function () { [native code] }");
     1010    }
     1011    for (var i = 0; i < values.length; i++)
     1012        runTest(values[i].v, values[i].name);
     1013})();
     1014
     1015section = "Object computed symbol named class (with computed name method) property";
     1016(function() {
     1017    let values = symbolValues;
     1018    let nameStr = "name";
     1019    function runTest(value) {
     1020        let o = {   
     1021            [value]: class bar { static [nameStr](){} },
     1022        }
     1023        shouldBe("typeof ", "o[" + toString(value) + "].name", typeof o[value].name, "function");
     1024        shouldBe("toString of ", "o[" + toString(value) + "].name", o[value].toString(), "class bar { static [nameStr](){} }");
     1025
     1026        let bound = o[value].bind({});
     1027        test(bound, "bound ", "function () { [native code] }");
     1028    }
     1029    for (var i = 0; i < values.length; i++)
     1030        runTest(values[i].v);
     1031})();
     1032
    7351033if (failureCount)
    7361034    throw Error("Found " + failureCount + " failures:\n" + failures);
  • trunk/LayoutTests/js/script-tests/object-literal-computed-methods.js

    r181829 r198288  
    55shouldBe("typeof o.foo", "'function'");
    66shouldBe("o.foo.length", "0");
    7 shouldBe("o.foo.name", "''");
     7shouldBe("o.foo.name", "'foo'");
    88shouldBe("o.foo.toString()", "'function () { return 10; }'");
    99shouldBe("Object.getOwnPropertyDescriptor(o, 'foo').value", "o.foo");
     
    1616shouldBe("typeof o.add", "'function'");
    1717shouldBe("o.add.length", "2");
    18 shouldBe("o.add.name", "''");
     18shouldBe("o.add.name", "'add'");
    1919shouldBe("o.add.toString()", "'function (x, y) { return x + y; }'");
    2020
  • trunk/Source/JavaScriptCore/ChangeLog

    r198270 r198288  
     12016-03-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add support for setting Function.name from computed properties.
     4        https://bugs.webkit.org/show_bug.cgi?id=155437
     5
     6        Reviewed by Filip Pizlo.
     7
     8        In JS code, we can have initialization of computed properties with function and
     9        class objects e.g.
     10
     11            var o = {
     12                [x]: function() {},
     13                [y]: class {}
     14            }
     15
     16        The ES6 spec states that the function and class in the example above (being
     17        anonymous) should take on the value of x and y respectively as their names:
     18
     19            o[x].name; // should be the "stringified" value of x.
     20            o[y].name; // should be the "stringified" value of y.
     21
     22        To achieve this, we will now inject an op_set_function_name bytecode at property
     23        initialization sites if:
     24
     25        1. the property assigned value is a function or class, and
     26        2. the function and class is anonymous, and
     27        3. if property assigned value is a class, it doesn't have a static method
     28           that is statically named "name".
     29
     30        The op_set_function_name will result in JSFunction::setFunctionName() being
     31        called on the target function / class before it is assigned to the property.
     32        JSFunction::setFunctionName() will take care of:
     33
     34        1. computing the name to use from the value of the computed property name
     35           e.g. x and y in the example above.
     36
     37           If the computed property name is not a symbol, then the function / class name
     38           should be the toString() value of that computed property name.
     39
     40           If the computed property name is a symbol, then ...
     41           a. if the Symbol has a defined description (e.g. Symbol("foo")), then the
     42              function / class name should be "[<symbol description>]" e.g. "[foo]".
     43           b. if the Symbol has an undefined description (e.g. Symbol()), then the
     44              function / class name should be "".
     45
     46           Note: Symbol("") is not the same as Symbol().  The former has a defined
     47           descriptor "", and hence, yields a function / class name of "[]".  The latter
     48           yields a function / class name of "".
     49
     50        2. reifying the lazy name property with this function / class name.
     51
     52        op_set_function_name is named after the SetFunctionName internal function
     53        in the ES6 spec that performs the above operation.
     54
     55        It is behaviorally correct to use op_set_function_name at every property
     56        initialization site with computed property names.  However, we choose to not
     57        emit the op_set_function_name bytecode when we already know that it will do
     58        nothing i.e. when the target function / class is proven to already have a name or
     59        name property.  This is done as an optimization to avoid unnecessary calls to
     60        JSFunction::setFunctionName().
     61
     62        Note: we could further check if the class has a static method with a computed
     63        name that is a constant string "name" and elide op_set_function_name there too.
     64        However, we don't bother because this should be rare.  JSFunction::setFunctionName()
     65        will still do the right thing.
     66
     67        * bytecode/BytecodeList.json:
     68        * bytecode/BytecodeUseDef.h:
     69        (JSC::computeUsesForBytecodeOffset):
     70        (JSC::computeDefsForBytecodeOffset):
     71        * bytecode/CodeBlock.cpp:
     72        (JSC::CodeBlock::dumpBytecode):
     73        * bytecompiler/BytecodeGenerator.cpp:
     74        (JSC::BytecodeGenerator::emitNewFunction):
     75        (JSC::BytecodeGenerator::emitSetFunctionNameIfNeeded):
     76        (JSC::BytecodeGenerator::emitCall):
     77        * bytecompiler/BytecodeGenerator.h:
     78        * bytecompiler/NodesCodegen.cpp:
     79        (JSC::PropertyListNode::emitBytecode):
     80        (JSC::PropertyListNode::emitPutConstantProperty):
     81        * dfg/DFGAbstractInterpreterInlines.h:
     82        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     83        * dfg/DFGByteCodeParser.cpp:
     84        (JSC::DFG::ByteCodeParser::parseBlock):
     85        * dfg/DFGCapabilities.cpp:
     86        (JSC::DFG::capabilityLevel):
     87        * dfg/DFGClobberize.h:
     88        (JSC::DFG::clobberize):
     89        * dfg/DFGDoesGC.cpp:
     90        (JSC::DFG::doesGC):
     91        * dfg/DFGFixupPhase.cpp:
     92        (JSC::DFG::FixupPhase::fixupNode):
     93        * dfg/DFGNodeType.h:
     94        * dfg/DFGPredictionPropagationPhase.cpp:
     95        (JSC::DFG::PredictionPropagationPhase::propagate):
     96        * dfg/DFGSafeToExecute.h:
     97        (JSC::DFG::safeToExecute):
     98        * dfg/DFGSpeculativeJIT.cpp:
     99        (JSC::DFG::SpeculativeJIT::compileNewFunction):
     100        (JSC::DFG::SpeculativeJIT::compileSetFunctionName):
     101        (JSC::DFG::SpeculativeJIT::compileForwardVarargs):
     102        * dfg/DFGSpeculativeJIT.h:
     103        (JSC::DFG::SpeculativeJIT::callOperation):
     104        * dfg/DFGSpeculativeJIT32_64.cpp:
     105        (JSC::DFG::SpeculativeJIT::compile):
     106        * dfg/DFGSpeculativeJIT64.cpp:
     107        (JSC::DFG::SpeculativeJIT::compile):
     108        * dfg/DFGStoreBarrierInsertionPhase.cpp:
     109        * ftl/FTLCapabilities.cpp:
     110        (JSC::FTL::canCompile):
     111        * ftl/FTLLowerDFGToB3.cpp:
     112        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     113        (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
     114        (JSC::FTL::DFG::LowerDFGToB3::compileSetFunctionName):
     115        (JSC::FTL::DFG::LowerDFGToB3::compileStringReplace):
     116        * jit/JIT.cpp:
     117        (JSC::JIT::privateCompileMainPass):
     118        * jit/JIT.h:
     119        * jit/JITInlines.h:
     120        (JSC::JIT::callOperation):
     121        * jit/JITOpcodes.cpp:
     122        (JSC::JIT::emit_op_to_primitive):
     123        (JSC::JIT::emit_op_set_function_name):
     124        (JSC::JIT::emit_op_strcat):
     125        * jit/JITOpcodes32_64.cpp:
     126        (JSC::JIT::emitSlow_op_to_primitive):
     127        (JSC::JIT::emit_op_set_function_name):
     128        (JSC::JIT::emit_op_strcat):
     129        * jit/JITOperations.cpp:
     130        * jit/JITOperations.h:
     131        * llint/LLIntSlowPaths.cpp:
     132        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     133        (JSC::LLInt::handleHostCall):
     134        * llint/LLIntSlowPaths.h:
     135        * llint/LowLevelInterpreter.asm:
     136        * parser/Nodes.cpp:
     137        (JSC::FunctionNode::finishParsing):
     138        (JSC::PropertyListNode::hasStaticallyNamedProperty):
     139        (JSC::VariableEnvironmentNode::VariableEnvironmentNode):
     140        * parser/Nodes.h:
     141        * runtime/JSFunction.cpp:
     142        (JSC::getCalculatedDisplayName):
     143        (JSC::JSFunction::setFunctionName):
     144        (JSC::JSFunction::reifyLength):
     145        (JSC::JSFunction::reifyName):
     146        * runtime/JSFunction.h:
     147        * tests/es6.yaml:
     148        * tests/stress/computed-function-names.js: Added.
     149        (toKeyString):
     150        (toFuncName):
     151        (shouldBe):
     152        (return.propKey):
     153
    11542016-03-16  Yusuke Suzuki  <utatane.tea@gmail.com>
    2155
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r198154 r198288  
    9595            { "name" : "op_new_generator_func_exp", "length" : 4 },
    9696            { "name" : "op_new_arrow_func_exp", "length" : 4 },
     97            { "name" : "op_set_function_name", "length" : 3 },
    9798            { "name" : "op_call", "length" : 9 },
    9899            { "name" : "op_tail_call", "length" : 9 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r198154 r198288  
    8686    case op_jngreatereq:
    8787    case op_jless:
     88    case op_set_function_name:
    8889    case op_copy_rest: {
    8990        ASSERT(opcodeLengths[opcodeID] > 2);
     
    323324    case op_profile_control_flow:
    324325    case op_put_to_arguments:
     326    case op_set_function_name:
    325327    case op_watchdog:
    326328#define LLINT_HELPER_OPCODES(opcode, length) case opcode:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r198154 r198288  
    13701370            printLocationAndOp(out, exec, location, it, "new_generator_func_exp");
    13711371            out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
     1372            break;
     1373        }
     1374        case op_set_function_name: {
     1375            int funcReg = (++it)->u.operand;
     1376            int nameReg = (++it)->u.operand;
     1377            printLocationAndOp(out, exec, location, it, "set_function_name");
     1378            out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data());
    13721379            break;
    13731380        }
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r198206 r198288  
    28192819    instructions().append(index);
    28202820    return dst;
     2821}
     2822
     2823void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name)
     2824{
     2825    if (valueNode->isFuncExprNode()) {
     2826        FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(valueNode)->metadata();
     2827        if (!metadata->ecmaName().isNull())
     2828            return;
     2829    } else if (valueNode->isClassExprNode()) {
     2830        ClassExprNode* classExprNode = static_cast<ClassExprNode*>(valueNode);
     2831        if (!classExprNode->ecmaName().isNull())
     2832            return;
     2833        if (classExprNode->hasStaticProperty(m_vm->propertyNames->name))
     2834            return;
     2835    } else
     2836        return;
     2837
     2838    // FIXME: We should use an op_call to an internal function here instead.
     2839    // https://bugs.webkit.org/show_bug.cgi?id=155547
     2840    emitOpcode(op_set_function_name);
     2841    instructions().append(value->index());
     2842    instructions().append(name->index());
    28212843}
    28222844
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r198206 r198288  
    523523        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
    524524
     525        void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name);
     526
    525527        RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
    526528        RegisterID* emitMoveEmptyValue(RegisterID* dst);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r198042 r198288  
    512512                if (node->m_type & PropertyNode::Computed) {
    513513                    RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
     514                    generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
    514515                    if (node->m_type & PropertyNode::Getter)
    515516                        generator.emitPutGetterByVal(dst, propertyName.get(), attribute, value.get());
     
    602603    }
    603604    RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
     605    generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
    604606    generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
    605607}
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r198212 r198288  
    26542654    }
    26552655
     2656    case SetFunctionName: {
     2657        clobberWorld(node->origin.semantic, clobberLimit);
     2658        break;
     2659    }
     2660
    26562661    case StoreBarrier: {
    26572662        filter(node->child1(), SpecCell);
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r198154 r198288  
    46374637        }
    46384638
     4639        case op_set_function_name: {
     4640            Node* func = get(VirtualRegister(currentInstruction[1].u.operand));
     4641            Node* name = get(VirtualRegister(currentInstruction[2].u.operand));
     4642            addToGraph(SetFunctionName, func, name);
     4643            NEXT_OPCODE(op_set_function_name);
     4644        }
     4645
    46394646        case op_typeof: {
    46404647            set(VirtualRegister(currentInstruction[1].u.operand),
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r198154 r198288  
    11/*
    2  * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    220220    case op_new_generator_func_exp:
    221221    case op_new_arrow_func_exp:
     222    case op_set_function_name:
    222223    case op_create_lexical_environment:
    223224    case op_get_parent_scope:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r198212 r198288  
    445445    case In:
    446446    case ValueAdd:
     447    case SetFunctionName:
    447448        read(World);
    448449        write(Heap);
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r198212 r198288  
    264264    case MaterializeNewObject:
    265265    case MaterializeCreateActivation:
     266    case SetFunctionName:
    266267    case StrCat:
    267268    case StringReplace:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r198212 r198288  
    14371437            fixEdge<CellUse>(node->child1());
    14381438            fixEdge<CellUse>(node->child2());
     1439            break;
     1440        }
     1441
     1442        case SetFunctionName: {
     1443            // The first child is guaranteed to be a cell because op_set_function_name is only used
     1444            // on a newly instantiated function object (the first child).
     1445            fixEdge<KnownCellUse>(node->child1());
     1446            fixEdge<UntypedUse>(node->child2());
    14391447            break;
    14401448        }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r198212 r198288  
    309309    macro(ProfileType, NodeMustGenerate) \
    310310    macro(ProfileControlFlow, NodeMustGenerate) \
     311    macro(SetFunctionName, NodeMustGenerate) \
    311312    \
    312313    macro(CreateActivation, NodeResultJS) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r198212 r198288  
    753753        case ForceOSRExit:
    754754        case SetArgument:
     755        case SetFunctionName:
    755756        case CheckStructure:
    756757        case CheckCell:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r198212 r198288  
    263263    case ToPrimitive:
    264264    case ToString:
     265    case SetFunctionName:
    265266    case StrCat:
    266267    case CallStringConstructor:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r198212 r198288  
    55985598}
    55995599
     5600void SpeculativeJIT::compileSetFunctionName(Node* node)
     5601{
     5602    SpeculateCellOperand func(this, node->child1());
     5603    GPRReg funcGPR = func.gpr();
     5604    JSValueOperand nameValue(this, node->child2());
     5605    JSValueRegs nameValueRegs = nameValue.jsValueRegs();
     5606
     5607    flushRegisters();
     5608    callOperation(operationSetFunctionName, funcGPR, nameValueRegs);
     5609    m_jit.exceptionCheck();
     5610
     5611    noResult(node);
     5612}
     5613
    56005614void SpeculativeJIT::compileForwardVarargs(Node* node)
    56015615{
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r197833 r198288  
    15491549        return appendCall(operation);
    15501550    }
     1551    JITCompiler::Call callOperation(V_JITOperation_ECJ operation, GPRReg arg1, JSValueRegs arg2)
     1552    {
     1553        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR());
     1554        return appendCall(operation);
     1555    }
    15511556    JITCompiler::Call callOperation(V_JITOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
    15521557    {
     
    19261931    {
    19271932        m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, arg2Payload, TrustedImm32(JSValue::CellTag), TrustedImmPtr(uid));
     1933        return appendCall(operation);
     1934    }
     1935    JITCompiler::Call callOperation(V_JITOperation_ECJ operation, GPRReg arg1, JSValueRegs arg2)
     1936    {
     1937        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR());
    19281938        return appendCall(operation);
    19291939    }
     
    23802390    template <typename ClassType> void compileNewFunctionCommon(GPRReg, Structure*, GPRReg, GPRReg, GPRReg, MacroAssembler::JumpList&, size_t, FunctionExecutable*, ptrdiff_t, ptrdiff_t, ptrdiff_t);
    23812391    void compileNewFunction(Node*);
     2392    void compileSetFunctionName(Node*);
    23822393    void compileForwardVarargs(Node*);
    23832394    void compileCreateActivation(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r198212 r198288  
    46114611        break;
    46124612
     4613    case SetFunctionName:
     4614        compileSetFunctionName(node);
     4615        break;
     4616
    46134617    case In:
    46144618        compileIn(node);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r198212 r198288  
    45954595        break;
    45964596
     4597    case SetFunctionName:
     4598        compileSetFunctionName(node);
     4599        break;
     4600
    45974601    case In:
    45984602        compileIn(node);
  • trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp

    r197549 r198288  
    284284            }
    285285               
     286            case SetFunctionName: {
     287                considerBarrier(m_node->child1(), m_node->child2());
     288                break;
     289            }
     290
    286291            default:
    287292                break;
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r198212 r198288  
    228228    case GetRegExpObjectLastIndex:
    229229    case SetRegExpObjectLastIndex:
     230    case SetFunctionName:
    230231        // These are OK.
    231232        break;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r198212 r198288  
    926926        case NewRegexp:
    927927            compileNewRegexp();
     928            break;
     929        case SetFunctionName:
     930            compileSetFunctionName();
    928931            break;
    929932        case StringReplace:
     
    65496552    }
    65506553
     6554    void compileSetFunctionName()
     6555    {
     6556        vmCall(m_out.voidType, m_out.operation(operationSetFunctionName), m_callFrame,
     6557            lowCell(m_node->child1()), lowJSValue(m_node->child2()));
     6558    }
     6559   
    65516560    void compileStringReplace()
    65526561    {
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r198212 r198288  
    11/*
    2  * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    299299        DEFINE_OP(op_unsigned)
    300300        DEFINE_OP(op_urshift)
     301        DEFINE_OP(op_set_function_name)
    301302        DEFINE_OP(op_strcat)
    302303        DEFINE_OP(op_stricteq)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r198264 r198288  
    11/*
    2  * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2012-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    571571        void emit_op_ret(Instruction*);
    572572        void emit_op_rshift(Instruction*);
     573        void emit_op_set_function_name(Instruction*);
    573574        void emit_op_strcat(Instruction*);
    574575        void emit_op_stricteq(Instruction*);
     
    792793        MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, UniquedStringImpl*);
    793794        MacroAssembler::Call callOperation(V_JITOperation_ECIZJJ, RegisterID, UniquedStringImpl*, int32_t, RegisterID, RegisterID);
     795        MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID);
    794796#else
    795797        MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, UniquedStringImpl*);
     798        MacroAssembler::Call callOperation(V_JITOperation_ECJ, RegisterID, RegisterID, RegisterID);
    796799#endif
    797800        MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID);
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r196419 r198288  
    11/*
    2  * Copyright (C) 2008, 2012, 2013, 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    559559}
    560560
     561ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJ operation, RegisterID arg1, RegisterID arg2)
     562{
     563    setupArgumentsWithExecState(arg1, arg2);
     564    return appendCallWithExceptionCheck(operation);
     565}
     566
    561567ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJZC operation, RegisterID regOp1, RegisterID regOp2, int32_t op3, RegisterID regOp4)
    562568{
     
    690696{
    691697    setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), TrustedImm32(op3), regOp4, regOp5);
     698    return appendCallWithExceptionCheck(operation);
     699}
     700
     701ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECJ operation, RegisterID arg1, RegisterID arg2Tag, RegisterID arg2Payload)
     702{
     703    setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
    692704    return appendCallWithExceptionCheck(operation);
    693705}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r198212 r198288  
    297297}
    298298
     299void JIT::emit_op_set_function_name(Instruction* currentInstruction)
     300{
     301    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
     302    emitGetVirtualRegister(currentInstruction[2].u.operand, regT1);
     303    callOperation(operationSetFunctionName, regT0, regT1);
     304}
     305
    299306void JIT::emit_op_strcat(Instruction* currentInstruction)
    300307{
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r198212 r198288  
    396396}
    397397
     398void JIT::emit_op_set_function_name(Instruction* currentInstruction)
     399{
     400    int func = currentInstruction[1].u.operand;
     401    int name = currentInstruction[2].u.operand;
     402    emitLoadPayload(func, regT1);
     403    emitLoad(name, regT3, regT2);
     404    callOperation(operationSetFunctionName, regT1, regT3, regT2);
     405}
     406
    398407void JIT::emit_op_strcat(Instruction* currentInstruction)
    399408{
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r198228 r198288  
    11/*
    2  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    10181018}
    10191019
     1020void JIT_OPERATION operationSetFunctionName(ExecState* exec, JSCell* funcCell, EncodedJSValue encodedName)
     1021{
     1022    JSFunction* func = jsCast<JSFunction*>(funcCell);
     1023    JSValue name = JSValue::decode(encodedName);
     1024    func->setFunctionName(exec, name);
     1025}
     1026
    10201027JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
    10211028{
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r197646 r198288  
    226226typedef void JIT_OPERATION (*V_JITOperation_ECJZC)(ExecState*, JSCell*, EncodedJSValue, int32_t, JSCell*);
    227227typedef void JIT_OPERATION (*V_JITOperation_ECCIcf)(ExecState*, JSCell*, JSCell*, InlineCallFrame*);
     228typedef void JIT_OPERATION (*V_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
    228229typedef void JIT_OPERATION (*V_JITOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
    229230typedef void JIT_OPERATION (*V_JITOperation_ECPSPS)(ExecState*, JSCell*, void*, size_t, void*, size_t);
     
    334335EncodedJSValue JIT_OPERATION operationNewGeneratorFunction(ExecState*, JSScope*, JSCell*) WTF_INTERNAL;
    335336EncodedJSValue JIT_OPERATION operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint(ExecState*, JSScope*, JSCell*) WTF_INTERNAL;
     337void JIT_OPERATION operationSetFunctionName(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
    336338JSCell* JIT_OPERATION operationNewObject(ExecState*, Structure*) WTF_INTERNAL;
    337339EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r198228 r198288  
    11/*
    2  * Copyright (C) 2011-2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    10841084}
    10851085
     1086LLINT_SLOW_PATH_DECL(slow_path_set_function_name)
     1087{
     1088    LLINT_BEGIN();
     1089    JSFunction* func = jsCast<JSFunction*>(LLINT_OP(1).Register::unboxedCell());
     1090    JSValue name = LLINT_OP_C(2).Register::jsValue();
     1091    func->setFunctionName(exec, name);
     1092    LLINT_END();
     1093}
     1094
    10861095static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
    10871096{
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r194248 r198288  
    11/*
    2  * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2014, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    103103LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_generator_func_exp);
    104104LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_new_arrow_func_exp);
     105LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_set_function_name);
    105106LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call);
    106107LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r198212 r198288  
    1 # Copyright (C) 2011-2015 Apple Inc. All rights reserved.
     1# Copyright (C) 2011-2016 Apple Inc. All rights reserved.
    22#
    33# Redistribution and use in source and binary forms, with or without
     
    14721472    dispatch(4)
    14731473
     1474_llint_op_set_function_name:
     1475    traceExecution()
     1476    callSlowPath(_llint_slow_path_set_function_name)
     1477    dispatch(3)
     1478
    14741479_llint_op_call:
    14751480    traceExecution()
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r197915 r198288  
    22*  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
    33*  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
     4*  Copyright (C) 2003-2009, 2013, 2016 Apple Inc. All rights reserved.
    55*  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
    66*  Copyright (C) 2007 Maks Orlovich
     
    197197}
    198198
     199bool PropertyListNode::hasStaticallyNamedProperty(const Identifier& propName)
     200{
     201    PropertyListNode* list = this;
     202    while (list) {
     203        const Identifier* currentNodeName = list->m_node->name();
     204        if (currentNodeName && *currentNodeName == propName)
     205            return true;
     206        list = list->m_next;
     207    }
     208    return false;
     209}
     210
    199211VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment& lexicalVariables)
    200212{
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r198206 r198288  
    649649        PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*);
    650650
     651        bool hasStaticallyNamedProperty(const Identifier& propName);
     652
    651653    private:
    652654        RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     
    19851987        void setEcmaName(const Identifier& name) { m_ecmaName = m_name.isNull() ? &name : &m_name; }
    19861988
     1989        bool hasStaticProperty(const Identifier& propName) { return m_staticMethods ? m_staticMethods->hasStaticallyNamedProperty(propName) : false; }
     1990
    19871991    private:
    19881992        RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r198270 r198288  
    572572}
    573573
     574void JSFunction::setFunctionName(ExecState* exec, JSValue value)
     575{
     576    // The "name" property may have been already been defined as part of a property list in an
     577    // object literal (and therefore reified).
     578    if (hasReifiedName())
     579        return;
     580
     581    ASSERT(!isHostFunction());
     582    ASSERT(jsExecutable()->ecmaName().isNull());
     583    String name;
     584    if (value.isSymbol()) {
     585        SymbolImpl* uid = asSymbol(value)->privateName().uid();
     586        if (uid->isNullSymbol())
     587            name = emptyString();
     588        else
     589            name = makeString("[", String(asSymbol(value)->privateName().uid()), ']');
     590    } else {
     591        VM& vm = exec->vm();
     592        JSString* jsStr = value.toString(exec);
     593        if (vm.exception())
     594            return;
     595        name = jsStr->value(exec);
     596        if (vm.exception())
     597            return;
     598    }
     599    reifyName(exec, name);
     600}
     601
    574602void JSFunction::reifyLength(ExecState* exec)
    575603{
     
    589617void JSFunction::reifyName(ExecState* exec)
    590618{
     619    String name = jsExecutable()->ecmaName().string();
     620    reifyName(exec, name);
     621}
     622
     623void JSFunction::reifyName(ExecState* exec, String name)
     624{
    591625    VM& vm = exec->vm();
    592626    FunctionRareData* rareData = this->rareData(vm);
     
    596630    unsigned initialAttributes = DontEnum | ReadOnly;
    597631    const Identifier& propID = exec->propertyNames().name;
    598 
    599     String name = jsExecutable()->ecmaName().string();
    600632
    601633    if (jsExecutable()->isGetter())
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r198023 r198288  
    151151    bool isClassConstructorFunction() const;
    152152
     153    void setFunctionName(ExecState*, JSValue name);
     154
    153155protected:
    154156    JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
     
    192194    void reifyLength(ExecState*);
    193195    void reifyName(ExecState*);
     196    void reifyName(ExecState*, String name);
    194197    void reifyLazyPropertyIfNeeded(ExecState*, PropertyName propertyName);
    195198
  • trunk/Source/JavaScriptCore/tests/es6.yaml

    r198270 r198288  
    808808  cmd: runES6 :fail
    809809- path: es6/function_name_property_symbol-keyed_methods.js
    810   cmd: runES6 :fail
     810  cmd: runES6 :normal
    811811- path: es6/function_name_property_variables_class.js
    812812  cmd: runES6 :normal
Note: See TracChangeset for help on using the changeset viewer.