Title: [197033] trunk
Revision
197033
Author
commit-qu...@webkit.org
Date
2016-02-24 09:36:12 -0800 (Wed, 24 Feb 2016)

Log Message

[ES6] Arrow function syntax. Emit loading&putting this/super only if they are used in arrow function
https://bugs.webkit.org/show_bug.cgi?id=153981

Patch by Skachkov Oleksandr <gskach...@gmail.com> on 2016-02-24
Reviewed by Saam Barati.
Source/_javascript_Core:

In first iteration of implemenation arrow function, we emit load and store variables 'this', 'arguments',
'super', 'new.target' in case if arrow function is exist even variables are not used in arrow function.
Current patch added logic that prevent from emiting those varibles if they are not used in arrow function.
During syntax analyze parser store information about using variables in arrow function inside of
the ordinary function scope and then put to BytecodeGenerator through UnlinkedCodeBlock

* bytecode/ExecutableInfo.h:
(JSC::ExecutableInfo::ExecutableInfo):
(JSC::ExecutableInfo::arrowFunctionCodeFeatures):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::arrowFunctionCodeFeatures):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseArguments):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseSuperCall):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseSuperProperty):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseEval):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseThis):
(JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseNewTarget):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::isThisUsedInInnerArrowFunction):
(JSC::BytecodeGenerator::isArgumentsUsedInInnerArrowFunction):
(JSC::BytecodeGenerator::isNewTargetUsedInInnerArrowFunction):
(JSC::BytecodeGenerator::isSuperUsedInInnerArrowFunction):
(JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
(JSC::BytecodeGenerator::emitPutThisToArrowFunctionContextScope):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ThisNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionMetadata):
* parser/Nodes.cpp:
(JSC::FunctionMetadataNode::FunctionMetadataNode):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseGeneratorFunctionSourceElements):
(JSC::Parser<LexerType>::parseFunctionBody):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseProperty):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression):
* parser/Parser.h:
(JSC::Scope::Scope):
(JSC::Scope::isArrowFunctionBoundary):
(JSC::Scope::innerArrowFunctionFeatures):
(JSC::Scope::setInnerArrowFunctionUseSuperCall):
(JSC::Scope::setInnerArrowFunctionUseSuperProperty):
(JSC::Scope::setInnerArrowFunctionUseEval):
(JSC::Scope::setInnerArrowFunctionUseThis):
(JSC::Scope::setInnerArrowFunctionUseNewTarget):
(JSC::Scope::setInnerArrowFunctionUseArguments):
(JSC::Scope::setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded):
(JSC::Scope::collectFreeVariables):
(JSC::Scope::mergeInnerArrowFunctionFeatures):
(JSC::Scope::fillParametersForSourceProviderCache):
(JSC::Scope::restoreFromSourceProviderCache):
(JSC::Scope::setIsFunction):
(JSC::Scope::setIsArrowFunction):
(JSC::Parser::closestParentNonArrowFunctionNonLexicalScope):
(JSC::Parser::pushScope):
(JSC::Parser::popScopeInternal):
* parser/ParserModes.h:
* parser/SourceProviderCacheItem.h:
(JSC::SourceProviderCacheItem::SourceProviderCacheItem):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createFunctionMetadata):
* tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js:
* tests/stress/arrowfunction-lexical-bind-arguments-strict.js:
* tests/stress/arrowfunction-lexical-bind-newtarget.js:
* tests/stress/arrowfunction-lexical-bind-superproperty.js:
* tests/stress/arrowfunction-lexical-bind-this-8.js: Added.

LayoutTests:

Added new benchmark tests for invoking arrow function within function, class's constructor and method

* js/regress/arrowfunction-call-in-class-constructor-expected.txt: Added.
* js/regress/arrowfunction-call-in-class-constructor.html: Added.
* js/regress/arrowfunction-call-in-class-method-expected.txt: Added.
* js/regress/arrowfunction-call-in-class-method.html: Added.
* js/regress/arrowfunction-call-in-function-expected.txt: Added.
* js/regress/arrowfunction-call-in-function.html: Added.
* js/regress/script-tests/arrowfunction-call-in-class-constructor.js: Added.
* js/regress/script-tests/arrowfunction-call-in-class-method.js: Added.
* js/regress/script-tests/arrowfunction-call-in-function.js: Added.
* js/regress/script-tests/arrowfunction-call.js:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (197032 => 197033)


--- trunk/LayoutTests/ChangeLog	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/LayoutTests/ChangeLog	2016-02-24 17:36:12 UTC (rev 197033)
@@ -1,3 +1,23 @@
+2016-02-24  Skachkov Oleksandr  <gskach...@gmail.com>
+
+        [ES6] Arrow function syntax. Emit loading&putting this/super only if they are used in arrow function
+        https://bugs.webkit.org/show_bug.cgi?id=153981
+
+        Reviewed by Saam Barati.
+
+        Added new benchmark tests for invoking arrow function within function, class's constructor and method
+
+        * js/regress/arrowfunction-call-in-class-constructor-expected.txt: Added.
+        * js/regress/arrowfunction-call-in-class-constructor.html: Added.
+        * js/regress/arrowfunction-call-in-class-method-expected.txt: Added.
+        * js/regress/arrowfunction-call-in-class-method.html: Added.
+        * js/regress/arrowfunction-call-in-function-expected.txt: Added.
+        * js/regress/arrowfunction-call-in-function.html: Added.
+        * js/regress/script-tests/arrowfunction-call-in-class-constructor.js: Added.
+        * js/regress/script-tests/arrowfunction-call-in-class-method.js: Added.
+        * js/regress/script-tests/arrowfunction-call-in-function.js: Added.
+        * js/regress/script-tests/arrowfunction-call.js:
+
 2016-02-24  Zalan Bujtas  <za...@apple.com>
 
         Background of an absolutely positioned inline element inside text-indented parent is positioned statically.

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor-expected.txt	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,10 @@
+JSRegress/arrowfunction-call-in-class-constructor
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-class-constructor.html	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method-expected.txt	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,10 @@
+JSRegress/arrowfunction-call-in-class-method
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method.html (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-class-method.html	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-function-expected.txt	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,10 @@
+JSRegress/arrowfunction-call-in-function
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/arrowfunction-call-in-function.html (0 => 197033)


--- trunk/LayoutTests/js/regress/arrowfunction-call-in-function.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/arrowfunction-call-in-function.html	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js (0 => 197033)


--- trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-constructor.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,23 @@
+var testValue  = 'test-value';
+
+class A {
+    constructor() {
+        this.value = testValue;
+    }
+}
+
+class B extends A {
+    constructor() {
+        super();
+        var arrow  = () => testValue;
+        arrow();
+    }
+}
+
+noInline(B);
+
+for (let i = 0; i < 1000000; ++i) {
+    let b = new B();
+    if (b.value != testValue)
+        throw "Error: bad result: " + result;
+}

Added: trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js (0 => 197033)


--- trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-class-method.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,24 @@
+var testValue  = 'test-value';
+
+class A {
+    constructor() {
+        this.value = testValue;
+    }
+
+    getValue () {
+        return this.value;
+    }
+}
+
+class B extends A {
+    getParentValue() {
+        var arrow  = () => testValue;
+        return arrow();
+    }
+}
+
+for (let i = 0; i < 100000; ++i) {
+    let b = new B();
+    if (b.getParentValue() != testValue)
+        throw "Error: bad result: " + result;
+}

Added: trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js (0 => 197033)


--- trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/arrowfunction-call-in-function.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,11 @@
+function bar(a, b) {
+    return ((_a, _b) => _a + _b)(a, b);
+}
+
+noInline(bar);
+
+for (let i = 0; i < 1000000; ++i) {
+    let result = bar(1, 2);
+    if (result != 3)
+        throw "Error: bad result: " + result;
+}

Modified: trunk/LayoutTests/js/regress/script-tests/arrowfunction-call.js (197032 => 197033)


--- trunk/LayoutTests/js/regress/script-tests/arrowfunction-call.js	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/LayoutTests/js/regress/script-tests/arrowfunction-call.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -8,8 +8,8 @@
 
 noInline(bar);
 
-for (var i = 0; i < 1000000; ++i) {
-    var result = bar(1, 2);
+for (let i = 0; i < 1000000; ++i) {
+    let result = bar(1, 2);
     if (result != 3)
         throw "Error: bad result: " + result;
 }

Modified: trunk/Source/_javascript_Core/ChangeLog (197032 => 197033)


--- trunk/Source/_javascript_Core/ChangeLog	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-02-24 17:36:12 UTC (rev 197033)
@@ -1,3 +1,96 @@
+2016-02-24  Skachkov Oleksandr  <gskach...@gmail.com>
+
+        [ES6] Arrow function syntax. Emit loading&putting this/super only if they are used in arrow function
+        https://bugs.webkit.org/show_bug.cgi?id=153981
+
+        Reviewed by Saam Barati.
+       
+        In first iteration of implemenation arrow function, we emit load and store variables 'this', 'arguments',
+        'super', 'new.target' in case if arrow function is exist even variables are not used in arrow function. 
+        Current patch added logic that prevent from emiting those varibles if they are not used in arrow function.
+        During syntax analyze parser store information about using variables in arrow function inside of 
+        the ordinary function scope and then put to BytecodeGenerator through UnlinkedCodeBlock
+
+        * bytecode/ExecutableInfo.h:
+        (JSC::ExecutableInfo::ExecutableInfo):
+        (JSC::ExecutableInfo::arrowFunctionCodeFeatures):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::arrowFunctionCodeFeatures):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseArguments):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseSuperCall):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseSuperProperty):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseEval):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseThis):
+        (JSC::UnlinkedCodeBlock::doAnyInnerArrowFunctionsUseNewTarget):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
+        (JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment):
+        (JSC::BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment):
+        (JSC::BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment):
+        (JSC::BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment):
+        (JSC::BytecodeGenerator::isThisUsedInInnerArrowFunction):
+        (JSC::BytecodeGenerator::isArgumentsUsedInInnerArrowFunction):
+        (JSC::BytecodeGenerator::isNewTargetUsedInInnerArrowFunction):
+        (JSC::BytecodeGenerator::isSuperUsedInInnerArrowFunction):
+        (JSC::BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope):
+        (JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
+        (JSC::BytecodeGenerator::emitPutThisToArrowFunctionContextScope):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ThisNode::emitBytecode):
+        (JSC::EvalFunctionCallNode::emitBytecode):
+        (JSC::FunctionCallValueNode::emitBytecode):
+        (JSC::FunctionNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionMetadata):
+        * parser/Nodes.cpp:
+        (JSC::FunctionMetadataNode::FunctionMetadataNode):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseGeneratorFunctionSourceElements):
+        (JSC::Parser<LexerType>::parseFunctionBody):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseProperty):
+        (JSC::Parser<LexerType>::parsePrimaryExpression):
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        * parser/Parser.h:
+        (JSC::Scope::Scope):
+        (JSC::Scope::isArrowFunctionBoundary):
+        (JSC::Scope::innerArrowFunctionFeatures):
+        (JSC::Scope::setInnerArrowFunctionUseSuperCall):
+        (JSC::Scope::setInnerArrowFunctionUseSuperProperty):
+        (JSC::Scope::setInnerArrowFunctionUseEval):
+        (JSC::Scope::setInnerArrowFunctionUseThis):
+        (JSC::Scope::setInnerArrowFunctionUseNewTarget):
+        (JSC::Scope::setInnerArrowFunctionUseArguments):
+        (JSC::Scope::setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded):
+        (JSC::Scope::collectFreeVariables):
+        (JSC::Scope::mergeInnerArrowFunctionFeatures):
+        (JSC::Scope::fillParametersForSourceProviderCache):
+        (JSC::Scope::restoreFromSourceProviderCache):
+        (JSC::Scope::setIsFunction):
+        (JSC::Scope::setIsArrowFunction):
+        (JSC::Parser::closestParentNonArrowFunctionNonLexicalScope):
+        (JSC::Parser::pushScope):
+        (JSC::Parser::popScopeInternal):
+        * parser/ParserModes.h:
+        * parser/SourceProviderCacheItem.h:
+        (JSC::SourceProviderCacheItem::SourceProviderCacheItem):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createFunctionMetadata):
+        * tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js:
+        * tests/stress/arrowfunction-lexical-bind-arguments-strict.js:
+        * tests/stress/arrowfunction-lexical-bind-newtarget.js:
+        * tests/stress/arrowfunction-lexical-bind-superproperty.js:
+        * tests/stress/arrowfunction-lexical-bind-this-8.js: Added.
+
 2016-02-23  Brian Burg  <bb...@apple.com>
 
         Web Inspector: teach the Objective-C protocol generators about --frontend and --backend directives

Modified: trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -35,7 +35,7 @@
 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
 // https://bugs.webkit.org/show_bug.cgi?id=151547
 struct ExecutableInfo {
-    ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext)
+    ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures = NoArrowFunctionFeatures)
         : m_usesEval(usesEval)
         , m_isStrictMode(isStrictMode)
         , m_isConstructor(isConstructor)
@@ -46,6 +46,7 @@
         , m_derivedContextType(static_cast<unsigned>(derivedContextType))
         , m_isArrowFunctionContext(isArrowFunctionContext)
         , m_isClassContext(isClassContext)
+        , m_arrowFunctionCodeFeatures(arrowFunctionCodeFeatures)
     {
         ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
         ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
@@ -61,6 +62,7 @@
     DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
     bool isClassContext() const { return m_isClassContext; }
+    ArrowFunctionCodeFeatures arrowFunctionCodeFeatures() const { return m_arrowFunctionCodeFeatures; }
 
 private:
     unsigned m_usesEval : 1;
@@ -73,6 +75,7 @@
     unsigned m_derivedContextType : 2;
     unsigned m_isArrowFunctionContext : 1;
     unsigned m_isClassContext : 1;
+    ArrowFunctionCodeFeatures m_arrowFunctionCodeFeatures;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -71,6 +71,7 @@
     , m_firstLine(0)
     , m_lineCount(0)
     , m_endColumn(UINT_MAX)
+    , m_arrowFunctionCodeFeatures(info.arrowFunctionCodeFeatures())
     , m_parseMode(info.parseMode())
     , m_features(0)
     , m_codeType(codeType)

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -122,6 +122,14 @@
     DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
     bool isClassContext() const { return m_isClassContext; }
+    ArrowFunctionCodeFeatures arrowFunctionCodeFeatures() const { return m_arrowFunctionCodeFeatures; }
+    
+    bool doAnyInnerArrowFunctionsUseArguments() { return m_arrowFunctionCodeFeatures & ArgumentsArrowFunctionFeature; }
+    bool doAnyInnerArrowFunctionsUseSuperCall() { return m_arrowFunctionCodeFeatures & SuperCallArrowFunctionFeature; }
+    bool doAnyInnerArrowFunctionsUseSuperProperty() { return m_arrowFunctionCodeFeatures & SuperPropertyArrowFunctionFeature; }
+    bool doAnyInnerArrowFunctionsUseEval() { return m_arrowFunctionCodeFeatures & EvalArrowFunctionFeature; }
+    bool doAnyInnerArrowFunctionsUseThis() { return m_arrowFunctionCodeFeatures & ThisArrowFunctionFeature; }
+    bool doAnyInnerArrowFunctionsUseNewTarget() { return m_arrowFunctionCodeFeatures & NewTargetArrowFunctionFeature; }
 
     void addExpressionInfo(unsigned instructionOffset, int divot,
         int startOffset, int endOffset, unsigned line, unsigned column);
@@ -391,7 +399,8 @@
     unsigned m_firstLine;
     unsigned m_lineCount;
     unsigned m_endColumn;
-
+    
+    ArrowFunctionCodeFeatures m_arrowFunctionCodeFeatures;
     SourceParseMode m_parseMode;
     CodeFeatures m_features;
     CodeType m_codeType;

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -69,7 +69,7 @@
     bool isClassContext = executable->superBinding() == SuperBinding::Needed;
 
     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
-        ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext));
+        ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, executable->arrowFunctionCodeFeatures()));
 
     auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables()));
     error = generator->generate();
@@ -101,6 +101,7 @@
     , m_superBinding(static_cast<unsigned>(node->superBinding()))
     , m_derivedContextType(static_cast<unsigned>(derivedContextType))
     , m_sourceParseMode(static_cast<unsigned>(node->parseMode()))
+    , m_arrowFunctionCodeFeatures(node->arrowFunctionCodeFeatures())
     , m_name(node->ident())
     , m_inferredName(node->inferredName())
     , m_sourceOverride(WTFMove(sourceOverride))

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -84,6 +84,7 @@
     FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
+    ArrowFunctionCodeFeatures arrowFunctionCodeFeatures() const { return m_arrowFunctionCodeFeatures; }
 
     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
     unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
@@ -156,6 +157,7 @@
     unsigned m_superBinding : 1;
     unsigned m_derivedContextType: 2;
     unsigned m_sourceParseMode : 4; // SourceParseMode
+    ArrowFunctionCodeFeatures m_arrowFunctionCodeFeatures;
 
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -243,7 +243,7 @@
     bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || functionNode->needsActivation() || containsArrowOrEvalButNotInArrowBlock;
 
     bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval();
-    bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction()));
+    bool needsArguments = (functionNode->usesArguments() || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction()));
 
     // Generator never provides "arguments". "arguments" reference will be resolved in an upper generator function scope.
     if (parseMode == SourceParseMode::GeneratorBodyMode)
@@ -572,7 +572,7 @@
     // Loading |this| inside an arrow function must be done after initializeDefaultParameterValuesAndSetupFunctionScopeStack()
     // because that function sets up the SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment()
     // consults the SymbolTable stack
-    if (SourceParseMode::ArrowFunctionMode == parseMode && (functionNode->usesThis() || isDerivedClassContext() || isDerivedConstructorContext()))
+    if (SourceParseMode::ArrowFunctionMode == parseMode && (functionNode->usesThis() || isThisUsedInInnerArrowFunction()))
         emitLoadThisFromArrowFunctionLexicalEnvironment();
     
     if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunction()) {
@@ -888,16 +888,18 @@
         
         if (!m_codeBlock->isArrowFunction()) {
             ScopeOffset offset;
+            
+            if (isThisUsedInInnerArrowFunction()) {
+                offset = symbolTable->takeNextScopeOffset();
+                symbolTable->set(propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));
+            }
 
-            offset = symbolTable->takeNextScopeOffset();
-            symbolTable->set(propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));
-
-            if (m_codeType == FunctionCode) {
+            if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
                 offset = symbolTable->takeNextScopeOffset();
                 symbolTable->set(propertyNames().newTargetLocalPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));
             }
             
-            if (isConstructor() && constructorKind() == ConstructorKind::Derived) {
+            if (isConstructor() && constructorKind() == ConstructorKind::Derived && isSuperUsedInInnerArrowFunction()) {
                 offset = symbolTable->takeNextScopeOffset();
                 symbolTable->set(propertyNames().derivedConstructorPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));
             }
@@ -907,28 +909,33 @@
     }
 
     VariableEnvironment environment;
-    auto addResult = environment.add(propertyNames().thisIdentifier);
-    addResult.iterator->value.setIsCaptured();
-    addResult.iterator->value.setIsConst();
+
+    if (isThisUsedInInnerArrowFunction()) {
+        auto addResult = environment.add(propertyNames().thisIdentifier);
+        addResult.iterator->value.setIsCaptured();
+        addResult.iterator->value.setIsConst();
+    }
     
-    if (m_codeType == FunctionCode)  {
+    if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
         auto addTarget = environment.add(propertyNames().newTargetLocalPrivateName);
         addTarget.iterator->value.setIsCaptured();
         addTarget.iterator->value.setIsLet();
     }
 
-    if (isConstructor() && constructorKind() == ConstructorKind::Derived) {
+    if (isConstructor() && constructorKind() == ConstructorKind::Derived && isSuperUsedInInnerArrowFunction()) {
         auto derivedConstructor = environment.add(propertyNames().derivedConstructorPrivateName);
         derivedConstructor.iterator->value.setIsCaptured();
         derivedConstructor.iterator->value.setIsLet();
     }
 
-    size_t size = m_symbolTableStack.size();
-    pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+    if (environment.size() > 0) {
+        size_t size = m_symbolTableStack.size();
+        pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
 
-    ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1);
+        ASSERT_UNUSED(size, m_symbolTableStack.size() == size + 1);
 
-    m_arrowFunctionContextLexicalEnvironmentRegister = m_symbolTableStack.last().m_scope;
+        m_arrowFunctionContextLexicalEnvironmentRegister = m_symbolTableStack.last().m_scope;
+    }
 }
 
 RegisterID* BytecodeGenerator::initializeNextParameter()
@@ -4000,16 +4007,16 @@
     m_forInContextStack.removeLast();
 }
 
-RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment()
+RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier)
 {
     ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Derived);
 
-    return emitResolveScope(nullptr, variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped));
+    return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped));
 }
 
 void BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment()
 {
-    emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound);
+    emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound);
 }
     
 RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment()
@@ -4017,7 +4024,7 @@
     m_isNewTargetLoadedInArrowFunction = true;
 
     Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName);
-    emitMove(m_newTargetRegister, emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(), newTargetVar, ThrowIfNotFound));
+    emitMove(m_newTargetRegister, emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().newTargetLocalPrivateName), newTargetVar, ThrowIfNotFound));
     
     return m_newTargetRegister;
 }
@@ -4025,35 +4032,61 @@
 RegisterID* BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment()
 {
     Variable protoScopeVar = variable(propertyNames().derivedConstructorPrivateName);
-    return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(), protoScopeVar, ThrowIfNotFound);
+    return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().derivedConstructorPrivateName), protoScopeVar, ThrowIfNotFound);
 }
     
+bool BytecodeGenerator::isThisUsedInInnerArrowFunction() 
+{
+    return m_codeBlock->doAnyInnerArrowFunctionsUseThis() || m_codeBlock->doAnyInnerArrowFunctionsUseSuperProperty() || m_codeBlock->doAnyInnerArrowFunctionsUseSuperCall() || m_codeBlock->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
+}
+    
+bool BytecodeGenerator::isArgumentsUsedInInnerArrowFunction()
+{
+    return m_codeBlock->doAnyInnerArrowFunctionsUseArguments() || m_codeBlock->doAnyInnerArrowFunctionsUseEval();
+}
+
+bool BytecodeGenerator::isNewTargetUsedInInnerArrowFunction()
+{
+    return m_codeBlock->doAnyInnerArrowFunctionsUseNewTarget() || m_codeBlock->doAnyInnerArrowFunctionsUseSuperCall();
+}
+
+bool BytecodeGenerator::isSuperUsedInInnerArrowFunction()
+{
+    return m_codeBlock->doAnyInnerArrowFunctionsUseSuperCall() || m_codeBlock->doAnyInnerArrowFunctionsUseSuperProperty();
+}
+
 void BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope()
 {
-    ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);
+    if (isNewTargetUsedInInnerArrowFunction()) {
+        ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
         
-    Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName);
-    emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, Initialization);
+        Variable newTargetVar = variable(propertyNames().newTargetLocalPrivateName);
+        emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, Initialization);
+    }
 }
     
 void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope()
 {
     if ((isConstructor() && constructorKind() == ConstructorKind::Derived) || m_codeBlock->isClassContext()) {
-        ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
+        if (isSuperUsedInInnerArrowFunction()) {
+            ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
             
-        Variable protoScope = variable(propertyNames().derivedConstructorPrivateName);
-        emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, Initialization);
+            Variable protoScope = variable(propertyNames().derivedConstructorPrivateName);
+            emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, Initialization);
+        }
     }
 }
-
+    
 void BytecodeGenerator::emitPutThisToArrowFunctionContextScope()
 {
-    ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);
+    if (isThisUsedInInnerArrowFunction()) {
+        ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);
 
-    Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped);
-    RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment() : m_arrowFunctionContextLexicalEnvironmentRegister;
+        Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped);
+        RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier) : m_arrowFunctionContextLexicalEnvironmentRegister;
     
-    emitPutToScope(scope, thisVar, thisRegister(), DoNotThrowIfNotFound, NotInitialization);
+        emitPutToScope(scope, thisVar, thisRegister(), ThrowIfNotFound, NotInitialization);
+    }
 }
 
 void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -494,7 +494,7 @@
 
         void emitProfileControlFlow(int);
         
-        RegisterID* emitLoadArrowFunctionLexicalEnvironment();
+        RegisterID* emitLoadArrowFunctionLexicalEnvironment(const Identifier&);
         void emitLoadThisFromArrowFunctionLexicalEnvironment();
         RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
 
@@ -717,8 +717,13 @@
         RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
         void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, bool isCaptured);
         void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
+        
+        bool isNewTargetUsedInInnerArrowFunction();
+        bool isSuperUsedInInnerArrowFunction();
+        bool isArgumentsUsedInInnerArrowFunction();
 
     public:
+        bool isThisUsedInInnerArrowFunction();
         void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr);
         void popLexicalScope(VariableEnvironmentNode*);
         void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -146,7 +146,7 @@
 
 RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext())
+    if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
         generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
 
     if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived || generator.isDerivedConstructorContext())
@@ -723,7 +723,7 @@
     //       eval("this.id = 'B'");
     //    }
     // }
-    if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext())
+    if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
         generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
 
     Variable var = generator.variable(generator.propertyNames().eval);
@@ -762,7 +762,7 @@
         bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived;
         if (generator.isDerivedConstructorContext() || (isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext()))
             generator.emitPutThisToArrowFunctionContextScope();
-        
+
         return ret;
     }
     generator.emitLoad(callArguments.thisRegister(), jsUndefined());
@@ -3138,7 +3138,7 @@
 
         // If there is no return we must automatically insert one.
         if (!returnNode) {
-            if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext())
+            if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
                 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
             
             RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -372,12 +372,12 @@
         const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, 
         unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
         int functionNameStart, int parametersStart, bool inStrictContext, 
-        ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
+        ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures = NoArrowFunctionFeatures)
     {
         return new (m_parserArena) FunctionMetadataNode(
             m_parserArena, startLocation, endLocation, startColumn, endColumn, 
             functionKeywordStart, functionNameStart, parametersStart, 
-            inStrictContext, constructorKind, superBinding, parameterCount, mode, isArrowFunctionBodyExpression);
+            inStrictContext, constructorKind, superBinding, parameterCount, mode, isArrowFunctionBodyExpression, arrowFunctionCodeFeatures);
     }
 
     ExpressionNode* createArrowFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -146,7 +146,7 @@
     ParserArena&, const JSTokenLocation& startLocation, 
     const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, 
     int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, 
-    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
+    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression, ArrowFunctionCodeFeatures arrowFunctionCodeFeatures)
         : Node(endLocation)
         , m_startColumn(startColumn)
         , m_endColumn(endColumn)
@@ -160,6 +160,7 @@
         , m_superBinding(static_cast<unsigned>(superBinding))
         , m_constructorKind(static_cast<unsigned>(constructorKind))
         , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression)
+        , m_arrowFunctionCodeFeatures(arrowFunctionCodeFeatures)
 {
     ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
     ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -1824,7 +1824,7 @@
             ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, 
             unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
             int functionNameStart, int parametersStart, bool isInStrictContext, 
-            ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool isArrowFunctionBodyExpression);
+            ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool isArrowFunctionBodyExpression, ArrowFunctionCodeFeatures = NoArrowFunctionFeatures);
 
         void finishParsing(const SourceCode&, const Identifier&, FunctionMode);
         
@@ -1852,6 +1852,7 @@
         SuperBinding superBinding() { return static_cast<SuperBinding>(m_superBinding); }
         ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); }
         bool isArrowFunctionBodyExpression() const { return m_isArrowFunctionBodyExpression; }
+        ArrowFunctionCodeFeatures arrowFunctionCodeFeatures() const { return m_arrowFunctionCodeFeatures;}
 
         void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset)
         {
@@ -1879,6 +1880,7 @@
         unsigned m_superBinding : 1;
         unsigned m_constructorKind : 2;
         unsigned m_isArrowFunctionBodyExpression : 1;
+        ArrowFunctionCodeFeatures m_arrowFunctionCodeFeatures;
     };
 
     class FunctionNode final : public ScopeNode {

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-02-24 17:36:12 UTC (rev 197033)
@@ -519,7 +519,7 @@
         failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
         popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
     }
-    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
+    info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false, currentFunctionScope()->innerArrowFunctionFeatures());
 
     info.endLine = tokenLine();
     info.endOffset = m_token.m_data.offset;
@@ -1735,7 +1735,7 @@
         next();
         if (match(CLOSEBRACE)) {
             unsigned endColumn = tokenColumn();
-            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
+            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression, currentFunctionScope()->innerArrowFunctionFeatures());
         }
     }
 
@@ -1747,7 +1747,7 @@
     else
         failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
     unsigned endColumn = tokenColumn();
-    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
+    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression, currentFunctionScope()->innerArrowFunctionFeatures());
 }
 
 static const char* stringForFunctionMode(SourceParseMode mode)
@@ -1988,7 +1988,7 @@
         functionInfo.body = context.createFunctionMetadata(
             startLocation, endLocation, functionInfo.bodyStartColumn, bodyEndColumn, 
             functionKeywordStart, functionNameStart, parametersStart, 
-            cachedInfo->strictMode, constructorKind, expectedSuperBinding, cachedInfo->parameterCount, mode, functionBodyType == ArrowFunctionBodyExpression);
+            cachedInfo->strictMode, constructorKind, expectedSuperBinding, cachedInfo->parameterCount, mode, functionBodyType == ArrowFunctionBodyExpression, cachedInfo->innerArrowFunctionFeatures);
         
         functionScope->restoreFromSourceProviderCache(cachedInfo);
         popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
@@ -2064,12 +2064,18 @@
                 : closestParentNonArrowFunctionNonLexicalScope()->constructorKind();
             semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, "Cannot call super() outside of a class constructor");
             semanticFailIfTrue(functionConstructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
+            
+            if (functionBodyType == ArrowFunctionBodyBlock || functionBodyType == ArrowFunctionBodyExpression)
+                functionScope->setInnerArrowFunctionUseSuperCall();
         }
         if (functionScope->needsSuperBinding()) {
             SuperBinding functionSuperBinding = functionBodyType == StandardFunctionBodyBlock
                 ? expectedSuperBinding
                 : closestParentNonArrowFunctionNonLexicalScope()->expectedSuperBinding();
             semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
+
+            if (functionBodyType == ArrowFunctionBodyBlock || functionBodyType == ArrowFunctionBodyExpression)
+                functionScope->setInnerArrowFunctionUseSuperProperty();
         }
     }
 
@@ -3207,6 +3213,8 @@
             JSTextPosition start = tokenStartPosition();
             JSTokenLocation location(tokenLocation());
             currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
+            if (currentScope()->isArrowFunction())
+                currentScope()->setInnerArrowFunctionUseEval();
             TreeExpression node = context.createResolve(location, *ident, start, lastTokenEndPosition());
             return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
         }
@@ -3620,6 +3628,8 @@
     case THISTOKEN: {
         JSTokenLocation location(tokenLocation());
         next();
+        if (currentScope()->isArrowFunction())
+            currentScope()->setInnerArrowFunctionUseThis();
         return context.createThisExpr(location, m_thisTDZMode);
     }
     case IDENT: {
@@ -3795,6 +3805,8 @@
             if (m_vm->propertyNames->target == *ident) {
                 semanticFailIfFalse(currentScope()->isFunction(), "new.target is only valid inside functions");
                 baseIsNewTarget = true;
+                if (currentScope()->isArrowFunction())
+                    currentScope()->setInnerArrowFunctionUseNewTarget();
                 base = context.createNewTargetExpr(location);
                 newCount--;
                 next();

Modified: trunk/Source/_javascript_Core/parser/Parser.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/Parser.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -158,7 +158,7 @@
 };
 
 struct Scope {
-    Scope(const VM* vm, bool isFunction, bool isGenerator, bool strictMode)
+    Scope(const VM* vm, bool isFunction, bool isGenerator, bool strictMode, bool isArrowFunction)
         : m_vm(vm)
         , m_shadowsArguments(false)
         , m_usesEval(false)
@@ -170,7 +170,8 @@
         , m_strictMode(strictMode)
         , m_isFunction(isFunction)
         , m_isGenerator(isGenerator)
-        , m_isArrowFunction(false)
+        , m_isArrowFunction(isArrowFunction)
+        , m_isArrowFunctionBoundary(false)
         , m_isLexicalScope(false)
         , m_isFunctionBoundary(false)
         , m_isValidStrictMode(true)
@@ -179,6 +180,7 @@
         , m_expectedSuperBinding(static_cast<unsigned>(SuperBinding::NotNeeded))
         , m_loopDepth(0)
         , m_switchDepth(0)
+        , m_innerArrowFunctionFeatures(0)
     {
     }
 
@@ -195,6 +197,7 @@
         , m_isFunction(rhs.m_isFunction)
         , m_isGenerator(rhs.m_isGenerator)
         , m_isArrowFunction(rhs.m_isArrowFunction)
+        , m_isArrowFunctionBoundary(rhs.m_isArrowFunctionBoundary)
         , m_isLexicalScope(rhs.m_isLexicalScope)
         , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
         , m_isValidStrictMode(rhs.m_isValidStrictMode)
@@ -203,6 +206,7 @@
         , m_expectedSuperBinding(rhs.m_expectedSuperBinding)
         , m_loopDepth(rhs.m_loopDepth)
         , m_switchDepth(rhs.m_switchDepth)
+        , m_innerArrowFunctionFeatures(rhs.m_innerArrowFunctionFeatures)
         , m_moduleScopeData(rhs.m_moduleScopeData)
     {
         if (rhs.m_labels) {
@@ -465,6 +469,7 @@
 
     void setNeedsFullActivation() { m_needsFullActivation = true; }
     bool needsFullActivation() const { return m_needsFullActivation; }
+    bool isArrowFunctionBoundary() { return m_isArrowFunctionBoundary; }
     bool isArrowFunction() { return m_isArrowFunction; }
 
     bool hasDirectSuper() { return m_hasDirectSuper; }
@@ -473,11 +478,31 @@
     bool needsSuperBinding() { return m_needsSuperBinding; }
     void setNeedsSuperBinding() { m_needsSuperBinding = true; }
     
+    ArrowFunctionCodeFeatures innerArrowFunctionFeatures() { return m_innerArrowFunctionFeatures; }
+    
     void setExpectedSuperBinding(SuperBinding superBinding) { m_expectedSuperBinding = static_cast<unsigned>(superBinding); }
     SuperBinding expectedSuperBinding() const { return static_cast<SuperBinding>(m_expectedSuperBinding); }
     void setConstructorKind(ConstructorKind constructorKind) { m_constructorKind = static_cast<unsigned>(constructorKind); }
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
 
+    void setInnerArrowFunctionUseSuperCall() { m_innerArrowFunctionFeatures |= SuperCallArrowFunctionFeature; }
+    void setInnerArrowFunctionUseSuperProperty() { m_innerArrowFunctionFeatures |= SuperPropertyArrowFunctionFeature; }
+    void setInnerArrowFunctionUseEval() { m_innerArrowFunctionFeatures |= EvalArrowFunctionFeature; }
+    void setInnerArrowFunctionUseThis() { m_innerArrowFunctionFeatures |= ThisArrowFunctionFeature; }
+    void setInnerArrowFunctionUseNewTarget() { m_innerArrowFunctionFeatures |= NewTargetArrowFunctionFeature; }
+    void setInnerArrowFunctionUseArguments() { m_innerArrowFunctionFeatures |= ArgumentsArrowFunctionFeature; }
+
+    void setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded()
+    {
+        ASSERT(m_isArrowFunction);
+
+        if (m_usesEval)
+            setInnerArrowFunctionUseEval();
+        
+        if (m_usedVariables.contains(m_vm->propertyNames->arguments.impl()))
+            setInnerArrowFunctionUseArguments();
+    }
+    
     void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
     {
         if (nestedScope->m_usesEval)
@@ -489,7 +514,7 @@
                     continue;
 
                 // "arguments" reference should be resolved at function boudary.
-                if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunction())
+                if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunctionBoundary())
                     continue;
 
                 m_usedVariables.add(impl);
@@ -518,6 +543,11 @@
         }
     }
     
+    void mergeInnerArrowFunctionFeatures(ArrowFunctionCodeFeatures arrowFunctionCodeFeatures)
+    {
+        m_innerArrowFunctionFeatures = m_innerArrowFunctionFeatures | arrowFunctionCodeFeatures;
+    }
+    
     void getCapturedVars(IdentifierSet& capturedVariables, bool& modifiedParameter, bool& modifiedArguments)
     {
         if (m_needsFullActivation || m_usesEval) {
@@ -568,6 +598,7 @@
         parameters.usesEval = m_usesEval;
         parameters.strictMode = m_strictMode;
         parameters.needsFullActivation = m_needsFullActivation;
+        parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures;
         copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables);
         copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables);
     }
@@ -577,6 +608,7 @@
         ASSERT(m_isFunction);
         m_usesEval = info->usesEval;
         m_strictMode = info->strictMode;
+        m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures;
         m_needsFullActivation = info->needsFullActivation;
         for (unsigned i = 0; i < info->usedVariablesCount; ++i)
             m_usedVariables.add(info->usedVariables()[i]);
@@ -592,6 +624,8 @@
         m_hasArguments = true;
         setIsLexicalScope();
         m_isGenerator = false;
+        m_isArrowFunctionBoundary = false;
+        m_isArrowFunction = false;
     }
 
     void setIsGeneratorFunction()
@@ -610,6 +644,7 @@
     void setIsArrowFunction()
     {
         setIsFunction();
+        m_isArrowFunctionBoundary = true;
         m_isArrowFunction = true;
     }
 
@@ -630,6 +665,7 @@
     bool m_isFunction : 1;
     bool m_isGenerator : 1;
     bool m_isArrowFunction : 1;
+    bool m_isArrowFunctionBoundary : 1;
     bool m_isLexicalScope : 1;
     bool m_isFunctionBoundary : 1;
     bool m_isValidStrictMode : 1;
@@ -638,6 +674,7 @@
     unsigned m_expectedSuperBinding : 2;
     int m_loopDepth;
     int m_switchDepth;
+    ArrowFunctionCodeFeatures m_innerArrowFunctionFeatures;
 
     typedef Vector<ScopeLabelInfo, 2> LabelStack;
     std::unique_ptr<LabelStack> m_labels;
@@ -896,9 +933,8 @@
     {
         unsigned i = m_scopeStack.size() - 1;
         ASSERT(i < m_scopeStack.size() && m_scopeStack.size());
-        while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunction()))
+        while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunctionBoundary()))
             i--;
-        // When reaching the top level scope (it can be non function scope), we return it.
         return ScopeRef(&m_scopeStack, i);
     }
     
@@ -907,12 +943,14 @@
         bool isFunction = false;
         bool isStrict = false;
         bool isGenerator = false;
+        bool isArrowFunction = false;
         if (!m_scopeStack.isEmpty()) {
             isStrict = m_scopeStack.last().strictMode();
             isFunction = m_scopeStack.last().isFunction();
             isGenerator = m_scopeStack.last().isGenerator();
+            isArrowFunction = m_scopeStack.last().isArrowFunction();
         }
-        m_scopeStack.append(Scope(m_vm, isFunction, isGenerator, isStrict));
+        m_scopeStack.append(Scope(m_vm, isFunction, isGenerator, isStrict, isArrowFunction));
         return currentScope();
     }
     
@@ -921,6 +959,13 @@
         ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
         ASSERT(m_scopeStack.size() > 1);
         m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
+        
+        if (m_scopeStack.last().isArrowFunction())
+            m_scopeStack.last().setInnerArrowFunctionUseEvalAndUseArgumentsIfNeeded();
+        
+        if (!(m_scopeStack.last().isFunctionBoundary() && !m_scopeStack.last().isArrowFunctionBoundary()))
+            m_scopeStack[m_scopeStack.size() - 2].mergeInnerArrowFunctionFeatures(m_scopeStack.last().innerArrowFunctionFeatures());
+
         if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation())
             m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation();
         m_scopeStack.removeLast();

Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/ParserModes.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -161,6 +161,17 @@
 
 const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature | ModifiedParameterFeature | ArrowFunctionFeature | ArrowFunctionContextFeature;
 
+typedef uint8_t ArrowFunctionCodeFeatures;
+    
+const ArrowFunctionCodeFeatures NoArrowFunctionFeatures =                0;
+const ArrowFunctionCodeFeatures EvalArrowFunctionFeature =          1 << 0;
+const ArrowFunctionCodeFeatures ArgumentsArrowFunctionFeature =     1 << 1;
+const ArrowFunctionCodeFeatures ThisArrowFunctionFeature =          1 << 2;
+const ArrowFunctionCodeFeatures SuperCallArrowFunctionFeature =     1 << 3;
+const ArrowFunctionCodeFeatures SuperPropertyArrowFunctionFeature = 1 << 4;
+const ArrowFunctionCodeFeatures NewTargetArrowFunctionFeature =     1 << 5;
+    
+const ArrowFunctionCodeFeatures AllArrowFunctionCodeFeatures = EvalArrowFunctionFeature | ArgumentsArrowFunctionFeature | ThisArrowFunctionFeature | SuperCallArrowFunctionFeature | SuperPropertyArrowFunctionFeature | NewTargetArrowFunctionFeature;
 } // namespace JSC
 
 #endif // ParserModes_h

Modified: trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/SourceProviderCacheItem.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -44,6 +44,7 @@
     bool needsFullActivation;
     bool usesEval;
     bool strictMode;
+    ArrowFunctionCodeFeatures innerArrowFunctionFeatures;
     Vector<RefPtr<UniquedStringImpl>> usedVariables;
     Vector<RefPtr<UniquedStringImpl>> writtenVariables;
     bool isBodyArrowExpression { false };
@@ -87,6 +88,8 @@
     bool usesEval : 1;
 
     bool strictMode : 1;
+    
+    ArrowFunctionCodeFeatures innerArrowFunctionFeatures;
 
     unsigned lastTockenLineStartOffset;
     unsigned usedVariablesCount;
@@ -127,6 +130,7 @@
     , parameterCount(parameters.parameterCount)
     , usesEval(parameters.usesEval)
     , strictMode(parameters.strictMode)
+    , innerArrowFunctionFeatures(parameters.innerArrowFunctionFeatures)
     , lastTockenLineStartOffset(parameters.lastTockenLineStartOffset)
     , usedVariablesCount(parameters.usedVariables.size())
     , writtenVariablesCount(parameters.writtenVariables.size())

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (197032 => 197033)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-02-24 17:36:12 UTC (rev 197033)
@@ -183,7 +183,7 @@
     ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; }
     ClassExpression createClassExpr(const JSTokenLocation&, const Identifier&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
-    int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool) { return FunctionBodyResult; }
+    int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, ArrowFunctionCodeFeatures = NoArrowFunctionFeatures) { return FunctionBodyResult; }
     ExpressionType createArrowFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     void setFunctionNameStart(int, int) { }
     int createArguments() { return ArgumentsResult; }

Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js (197032 => 197033)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-non-strict-1.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -214,3 +214,39 @@
 for (var i = 0; i < 10000; i++) {
     testCase(boo('A' + i)('B' + i)('D' + i)('E' + i)('G' + i)[0], 'E' + i, txtMsg + "#17");
 }
+
+var testValue = 'test-value';
+
+function f_args () {
+    if (true) {
+        let someValue = '';
+        if (true) {
+            let anotherValue = 'value';
+            return () => () => () => arguments[0];
+        }
+    }
+
+    return () => 'no-value';
+}
+
+for (var i = 0; i < 10000; i++) {
+    let v = f_args(testValue, 'anotherValue')()()();
+    testCase(v, testValue);
+}
+
+function f_args_eval () {
+    if (true) {
+        let someValue = '';
+        if (true) {
+            let anotherValue = 'value';
+            return () => () => () => eval('arguments[0]');
+        }
+    }
+
+    return () => 'no-value';
+}
+
+for (var i = 0; i < 10000; i++) {
+    let v = f_args_eval(testValue, 'anotherValue')()()();
+    testCase(v, testValue);
+}

Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-strict.js (197032 => 197033)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-strict.js	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-arguments-strict.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -131,3 +131,39 @@
 }
 
 test();
+
+var testValue = 'test-value';
+
+function f_args () {
+    if (true) {
+        let someValue = '';
+        if (true) {
+            let anotherValue = 'value';
+            return () => () => () => arguments[0];
+        }
+    }
+
+    return () => 'no-value';
+}
+
+for (var i = 0; i < 10000; i++) {
+    let v = f_args(testValue, 'anotherValue')()()();
+    testCase(v, testValue);
+}
+
+function f_args_eval () {
+    if (true) {
+        let someValue = '';
+        if (true) {
+            let anotherValue = 'value';
+            return () => () => () => eval('arguments[0]');
+        }
+    }
+
+    return () => 'no-value';
+}
+
+for (var i = 0; i < 10000; i++) {
+    let v = f_args_eval(testValue, 'anotherValue')()()();
+    testCase(v, testValue);
+}

Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-newtarget.js (197032 => 197033)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-newtarget.js	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-newtarget.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -66,7 +66,7 @@
         new C(val);
     }
     catch (e) {
-        result = e instanceof ReferenceError; 
+        result = e instanceof ReferenceError;
     }
 
     return result;
@@ -76,3 +76,17 @@
     testCase(tryToCreateClass(true), true, "Error: newTargetLocal should be hided variable");
     testCase(tryToCreateClass(false), true, "Error: newTargetLocal should be hided variable");
 }
+
+function getTargetBlockScope() {
+    if (true) {
+        let someValue = '';
+        if (true)
+            return x => new.target;
+    }
+    return ()=>value;
+}
+
+for (var i = 0; i < 1000; i++) {
+    var undefinedTarget = getTargetBlockScope()()
+    testCase(undefinedTarget, undefined, "Error: new.target is not lexically binded inside of the arrow function #4");
+}

Modified: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js (197032 => 197033)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js	2016-02-24 17:26:52 UTC (rev 197032)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -123,6 +123,20 @@
      getParentValue() {
          return super.getValue();
      }
+
+     getValueBlockScope() {
+         if (true) {
+             var someValue ='';
+             if (true) {
+                 return () => {
+                    if (true) {
+                        let internalValue = '';
+                        return super.getValue();
+                    }
+                 }
+             }
+         }
+     }
  };
 
  var g = new G();
@@ -141,6 +155,8 @@
     let setValue = g1.setValueCB();
     setValue('new-value');
     testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" inside of the method that retun arrow function');
+    getValue = g1.getValueBlockScope();
+    testCase(getValue(), 'new-value',  'Error: Some problem with using arrow and "super" with deep nesting inside of the method that retun arrow function');
 }
 
 var H = class H extends A {

Added: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-this-8.js (0 => 197033)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-this-8.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-this-8.js	2016-02-24 17:36:12 UTC (rev 197033)
@@ -0,0 +1,89 @@
+var testCase = function (actual, expected, message) {
+    if (actual !== expected) {
+        throw message + ". Expected '" + expected + "', but was '" + actual + "'";
+    }
+};
+
+let testValue = 'test-value';
+
+var f_this = function () {
+    let value = 'value';
+    if (true) {
+        let someValue = 'someValue';
+        if (true) {
+            let = anotherValue = 'value';
+            return () => () => () => this.value;
+        }
+    }
+
+    return () => value;
+}
+
+for (let i = 0; i < 10000; i++) {
+    testCase(f_this.call({value : testValue})()()(), testValue);
+}
+
+var f_this_eval = function () {
+    if (true) {
+        let someValue = '';
+        if (true) {
+            let = anotherValue = 'value';
+            return () => () => () => eval('this.value');
+        }
+    }
+
+    return () => 'no-value';
+}
+
+for (let i = 0; i < 10000; i++) {
+    testCase(f_this_eval.call({value : testValue}, false)()()(), testValue);
+}
+
+
+function f_this_branches (branch, returnThis) {
+    let value = 'value';
+    if (branch === 'A') {
+        let someValue = 'someValue';
+        if (true) {
+            let = anotherValue = 'value';
+            return () => () => () => {
+                if (returnThis)
+                    return this.value;
+                  else
+                    return anotherValue;
+            }
+        }
+    }
+
+    return () => value;
+}
+
+for (let i = 0; i < 10000; i++) {
+    testCase(f_this_branches.call({value : testValue}, 'B')() == testValue, false);
+    testCase(f_this_branches.call({value : testValue}, 'A', false)()()() == testValue, false);
+    testCase(f_this_branches.call({value : testValue}, 'A', true)()()(), testValue);
+}
+
+function f_this_eval_branches (branch, returnThis) {
+    let value = 'value';
+    if (branch === 'A') {
+        let someValue = 'someValue';
+        if (true) {
+            let = anotherValue = 'value';
+            return () => () => () => {
+                if (returnThis)
+                    return eval('this.value');
+                  else
+                    return anotherValue;
+            }
+        }
+    }
+
+    return () => value;
+}
+
+for (let i = 0; i < 10000; i++) {
+    testCase(f_this_eval_branches.call({value : testValue}, 'B')() == testValue, false);
+    testCase(f_this_eval_branches.call({value : testValue}, 'A', false)()()() == testValue, false);
+    testCase(f_this_eval_branches.call({value : testValue}, 'A', true)()()(), testValue);
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to