[JSC] JSC should have "parseFunction" to optimize Function constructor
https://bugs.webkit.org/show_bug.cgi?id=190340

Reviewed by Mark Lam.

JSTests:

This patch fixes the line number of syntax errors raised by the Function constructor,
since we now parse the final code only once. And we no longer use block statement
for Function constructor's parsing.

* ChakraCore/test/Function/FuncBodyES5.baseline-jsc:
* stress/function-cache-with-parameters-end-position.js: Added.
(shouldBe):
(shouldThrow):
(i.anonymous):
* stress/function-constructor-name.js: Added.
(shouldBe):
(GeneratorFunction):
(AsyncFunction.async):
(AsyncGeneratorFunction.async):
(anonymous):
(async.anonymous):
* test262/expectations.yaml:

LayoutTests/imported/w3c:

* web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt:
* web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt:
* web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt:
* web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt:

Source/JavaScriptCore:

The current Function constructor is suboptimal. We parse the piece of the same code three times to meet
the spec requirement. (1) check parameters syntax, (2) check body syntax, and (3) parse the entire function.
And to parse 1-3 correctly, we create two strings, the parameters and the entire function. This operation
is really costly and ideally we should meet the above requirement by the one time parsing.

To meet the above requirement, we add a special function for Parser, parseSingleFunction. This function
takes `std::optional<int> functionConstructorParametersEndPosition` and check this end position is correct in the parser.
For example, if we run the code,

    Function('/*', '*/){')

According to the spec, this should produce '/*' parameter string and '*/){' body string. And parameter
string should be syntax-checked by the parser, and raise the error since it is incorrect. Instead of doing
that, in our implementation, we first create the entire string.

    function anonymous(/*) {
        */){
    }

And we parse it. At that time, we also pass the end position of the parameters to the parser. In the above case,
the position of the `function anonymous(/*)' <> is passed. And in the parser, we check that the last token
offset of the parameters is the given end position. This check allows us to raise the error correctly to the
above example while we parse the entire function only once. And we do not need to create two strings too.

This improves the performance of the Function constructor significantly. And web-tooling-benchmark/uglify-js is
significantly sped up (28.2%).

Before:
    uglify-js:  2.94 runs/s
After:
    uglify-js:  3.77 runs/s

* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::fromGlobalCode):
* bytecode/UnlinkedFunctionExecutable.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseSingleFunction):
(JSC::Parser<LexerType>::parseFunctionInfo):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseAsyncFunctionDeclaration):
* parser/Parser.h:
(JSC::Parser<LexerType>::parse):
(JSC::parse):
(JSC::parseFunctionForFunctionConstructor):
* parser/ParserModes.h:
* parser/ParserTokens.h:
(JSC::JSTextPosition::JSTextPosition):
(JSC::JSTokenLocation::JSTokenLocation): Deleted.
* parser/SourceCodeKey.h:
(JSC::SourceCodeKey::SourceCodeKey):
(JSC::SourceCodeKey::operator== const):
* runtime/CodeCache.cpp:
(JSC::CodeCache::getUnlinkedGlobalCodeBlock):
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
* runtime/CodeCache.h:
* runtime/FunctionConstructor.cpp:
(JSC::constructFunctionSkippingEvalEnabledCheck):
* runtime/FunctionExecutable.cpp:
(JSC::FunctionExecutable::fromGlobalCode):
* runtime/FunctionExecutable.h:

LayoutTests:

* fast/dom/attribute-event-listener-errors-expected.txt:
* fast/events/attribute-listener-deletion-crash-expected.txt:
* fast/events/window-onerror-syntax-error-in-attr-expected.txt:
* js/dom/invalid-syntax-for-function-expected.txt:
* js/dom/script-start-end-locations-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@237254 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc b/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc
index 36f2a20..38248d7 100644
--- a/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc
+++ b/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc
@@ -9,13 +9,13 @@
 PASS: 8: new Function succeeded as expected
 PASS: 9: new Function succeeded as expected
 PASS: 10: new Function succeeded as expected
-PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.
-PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.
-PASS: 101: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
-PASS: 102: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
-PASS: 103: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
-PASS: 104: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.
-PASS: 105: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.
+PASS: 100: new Function failed as expected. SyntaxError: Parser error
+PASS: 100: new Function failed as expected. SyntaxError: Parser error
+PASS: 101: new Function failed as expected. SyntaxError: Parser error
+PASS: 102: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor.
+PASS: 103: new Function failed as expected. SyntaxError: Parser error
+PASS: 104: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor.
+PASS: 105: new Function failed as expected. SyntaxError: Parser error
 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
 PASS: 201: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog
index 85e53dc..7386e23 100644
--- a/JSTests/ChangeLog
+++ b/JSTests/ChangeLog
@@ -1,3 +1,28 @@
+2018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] JSC should have "parseFunction" to optimize Function constructor
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+
+        Reviewed by Mark Lam.
+
+        This patch fixes the line number of syntax errors raised by the Function constructor,
+        since we now parse the final code only once. And we no longer use block statement
+        for Function constructor's parsing.
+
+        * ChakraCore/test/Function/FuncBodyES5.baseline-jsc:
+        * stress/function-cache-with-parameters-end-position.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (i.anonymous):
+        * stress/function-constructor-name.js: Added.
+        (shouldBe):
+        (GeneratorFunction):
+        (AsyncFunction.async):
+        (AsyncGeneratorFunction.async):
+        (anonymous):
+        (async.anonymous):
+        * test262/expectations.yaml:
+
 2018-10-18  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r237242.
diff --git a/JSTests/stress/function-cache-with-parameters-end-position.js b/JSTests/stress/function-cache-with-parameters-end-position.js
new file mode 100644
index 0000000..b0ff221
--- /dev/null
+++ b/JSTests/stress/function-cache-with-parameters-end-position.js
@@ -0,0 +1,40 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+for (var i = 0; i < 10; ++i) {
+    var f = Function('/*) {\n*/', 'return 42');
+    shouldBe(f.toString(),
+`function anonymous(/*) {
+*/) {
+return 42
+}`);
+}
+shouldThrow(() => Function('/*', '*/){\nreturn 42'), `SyntaxError: Parameters should match arguments offered as parameters in Function constructor.`);
+
+shouldThrow(() => Function('/*', '*/){\nreturn 43'), `SyntaxError: Parameters should match arguments offered as parameters in Function constructor.`);
+for (var i = 0; i < 10; ++i) {
+    var f = Function('/*) {\n*/', 'return 43');
+    shouldBe(f.toString(),
+`function anonymous(/*) {
+*/) {
+return 43
+}`);
+}
+
diff --git a/JSTests/stress/function-constructor-name.js b/JSTests/stress/function-constructor-name.js
new file mode 100644
index 0000000..bf7e945
--- /dev/null
+++ b/JSTests/stress/function-constructor-name.js
@@ -0,0 +1,36 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var GeneratorFunction = function*(){}.constructor;
+var AsyncFunction = async function(){}.constructor;
+var AsyncGeneratorFunction = async function*(){}.constructor;
+
+var f = Function(`return 42`);
+shouldBe(typeof anonymous, `undefined`);
+shouldBe(f.toString(),
+`function anonymous() {
+return 42
+}`);
+
+var gf = GeneratorFunction(`return 42`);
+shouldBe(typeof anonymous, `undefined`);
+shouldBe(gf.toString(),
+`function* anonymous() {
+return 42
+}`);
+
+var af = AsyncFunction(`return 42`);
+shouldBe(typeof anonymous, `undefined`);
+shouldBe(af.toString(),
+`async function anonymous() {
+return 42
+}`);
+
+var agf = AsyncGeneratorFunction(`return 42`);
+shouldBe(typeof anonymous, `undefined`);
+shouldBe(agf.toString(),
+`async function* anonymous() {
+return 42
+}`);
diff --git a/JSTests/test262/expectations.yaml b/JSTests/test262/expectations.yaml
index 08ca9b1..d399f33 100644
--- a/JSTests/test262/expectations.yaml
+++ b/JSTests/test262/expectations.yaml
@@ -900,14 +900,14 @@
   default: "ReferenceError: Can't find variable: verifyNotEnumerable"
   strict mode: "ReferenceError: Can't find variable: verifyNotEnumerable"
 test/built-ins/Function/prototype/toString/AsyncFunction.js:
-  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/Function.js:
-  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/GeneratorFunction.js:
-  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/async-arrow-function.js:
   default: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
   strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4b12403..5c4d4d5 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] JSC should have "parseFunction" to optimize Function constructor
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+
+        Reviewed by Mark Lam.
+
+        * fast/dom/attribute-event-listener-errors-expected.txt:
+        * fast/events/attribute-listener-deletion-crash-expected.txt:
+        * fast/events/window-onerror-syntax-error-in-attr-expected.txt:
+        * js/dom/invalid-syntax-for-function-expected.txt:
+        * js/dom/script-start-end-locations-expected.txt:
+
 2018-10-17  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Enable the datalist element by default on iOS and macOS
diff --git a/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt b/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt
index 1df9397..4236767 100644
--- a/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt
+++ b/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt
@@ -1,4 +1,4 @@
 CONSOLE MESSAGE: line 4: ReferenceError: Can't find variable: error
-CONSOLE MESSAGE: line 9: SyntaxError: Invalid character: '@'
+CONSOLE MESSAGE: line 5: SyntaxError: Invalid character: '@'
 This test verifies that an attribute event listener error shows the right line number even if the attribute contains newlines.
   
diff --git a/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt b/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt
index 0db7728..5824baa 100644
--- a/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt
+++ b/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt
@@ -1,21 +1,21 @@
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
 PASS
diff --git a/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt b/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt
index 5ac9501..68edd01 100644
--- a/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt
+++ b/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt
@@ -1,6 +1,6 @@
 Test that window.onerror is called on window object when there is a syntax error in attribute handler. Bug 70991.
 
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:11:38 SyntaxError: Unexpected token '%'
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:37:38 SyntaxError: Unexpected token '%'
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:37:14 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:10:38 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:38 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:14 SyntaxError: Unexpected token '%'
 Button 1 Button 2 Button 3
diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog
index 3e37324..06aaba7 100644
--- a/LayoutTests/imported/w3c/ChangeLog
+++ b/LayoutTests/imported/w3c/ChangeLog
@@ -1,3 +1,15 @@
+2018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] JSC should have "parseFunction" to optimize Function constructor
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+
+        Reviewed by Mark Lam.
+
+        * web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt:
+        * web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt:
+        * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt:
+        * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt:
+
 2018-10-17  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Enable the datalist element by default on iOS and macOS
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt
index 6199cde..43095a3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token '}'
-CONSOLE MESSAGE: line 54: SyntaxError: Unexpected token '}'
+CONSOLE MESSAGE: line 52: SyntaxError: Unexpected token '}'
 
 PASS Inline event handlers retain their ordering when invalid and force-compiled 
 PASS Inline event handlers retain their ordering when invalid and force-compiled via dispatch 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt
index a86e064..9ad5ac6 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: line 26: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.
-CONSOLE MESSAGE: line 21: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.
+CONSOLE MESSAGE: line 24: SyntaxError: Parser error
+CONSOLE MESSAGE: line 21: SyntaxError: Parser error
 
 FAIL Invalid uncompiled raw handlers should only be compiled when about to call them. assert_array_equals: lengths differ, expected 3 got 4
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt
index 1f8441d..26f9d9d 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 26: SyntaxError: Unexpected token ')'
+CONSOLE MESSAGE: line 24: SyntaxError: Unexpected end of script
 
 PASS window.onerror - compile error in attribute 
 PASS window.onerror - compile error in attribute (column) 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt
index a1dae89..314ff15 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token ')'
-CONSOLE MESSAGE: line 18: SyntaxError: Unexpected token ')'
+CONSOLE MESSAGE: line 16: SyntaxError: Unexpected end of script
 
 PASS window.onerror - compile error in <body onerror> 
 
diff --git a/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt b/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt
index 329a417..f50fce7 100644
--- a/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt
+++ b/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt
@@ -1,3 +1,3 @@
-CONSOLE MESSAGE: line 2: SyntaxError: Invalid character: '#'
+CONSOLE MESSAGE: line 1: SyntaxError: Invalid character: '#'
 This test ensures we don't crash when we are given garbage for an attribute expecting a function.
 https://bugs.webkit.org/show_bug.cgi?id=19025
diff --git a/LayoutTests/js/dom/script-start-end-locations-expected.txt b/LayoutTests/js/dom/script-start-end-locations-expected.txt
index ca955d3..32ec07f 100644
--- a/LayoutTests/js/dom/script-start-end-locations-expected.txt
+++ b/LayoutTests/js/dom/script-start-end-locations-expected.txt
@@ -243,32 +243,32 @@
 eval { 1:1 - 1:56 }
 
   new Function Object:
-function "anonymous" { 1:20 - 2:228 }
+function "anonymous" { 1:19 - 2:228 }
 function "nf1a" { 2:57 - 2:219 }
 function "nf1b" { 2:87 - 2:209 }
 function "nf1c" { 2:117 - 2:199 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:20 - 18:8 }
+function "anonymous" { 1:19 - 18:8 }
 function "nf2a" { 5:18 - 16:5 }
 function "nf2b" { 7:22 - 14:9 }
 function "nf2c" { 9:26 - 12:13 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:20 - 2:228 }
+function "anonymous" { 1:19 - 2:228 }
 function "nf1a" { 2:57 - 2:219 }
 function "nf1b" { 2:87 - 2:209 }
 function "nf1c" { 2:117 - 2:199 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:20 - 2:237 }
+function "anonymous" { 1:19 - 2:237 }
 function "nfi1a" { 2:58 - 2:227 }
 function "nfi1b" { 2:90 - 2:216 }
 function "nfi1c" { 2:122 - 2:205 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:20 - 18:8 }
+function "anonymous" { 1:19 - 18:8 }
 function "nf2a" { 5:18 - 16:5 }
 function "nf2b" { 7:22 - 14:9 }
 function "nf2c" { 9:26 - 12:13 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:20 - 18:9 }
+function "anonymous" { 1:19 - 18:9 }
 function "nfi2a" { 5:19 - 16:5 }
 function "nfi2b" { 7:23 - 14:9 }
 function "nfi2c" { 9:27 - 12:13 }
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 0217dd9..bf3d041 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,72 @@
+2018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] JSC should have "parseFunction" to optimize Function constructor
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+
+        Reviewed by Mark Lam.
+
+        The current Function constructor is suboptimal. We parse the piece of the same code three times to meet
+        the spec requirement. (1) check parameters syntax, (2) check body syntax, and (3) parse the entire function.
+        And to parse 1-3 correctly, we create two strings, the parameters and the entire function. This operation
+        is really costly and ideally we should meet the above requirement by the one time parsing.
+
+        To meet the above requirement, we add a special function for Parser, parseSingleFunction. This function
+        takes `std::optional<int> functionConstructorParametersEndPosition` and check this end position is correct in the parser.
+        For example, if we run the code,
+
+            Function('/*', '*/){')
+
+        According to the spec, this should produce '/*' parameter string and '*/){' body string. And parameter
+        string should be syntax-checked by the parser, and raise the error since it is incorrect. Instead of doing
+        that, in our implementation, we first create the entire string.
+
+            function anonymous(/*) {
+                */){
+            }
+
+        And we parse it. At that time, we also pass the end position of the parameters to the parser. In the above case,
+        the position of the `function anonymous(/*)' <> is passed. And in the parser, we check that the last token
+        offset of the parameters is the given end position. This check allows us to raise the error correctly to the
+        above example while we parse the entire function only once. And we do not need to create two strings too.
+
+        This improves the performance of the Function constructor significantly. And web-tooling-benchmark/uglify-js is
+        significantly sped up (28.2%).
+
+        Before:
+            uglify-js:  2.94 runs/s
+        After:
+            uglify-js:  3.77 runs/s
+
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::fromGlobalCode):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::parseSingleFunction):
+        (JSC::Parser<LexerType>::parseFunctionInfo):
+        (JSC::Parser<LexerType>::parseFunctionDeclaration):
+        (JSC::Parser<LexerType>::parseAsyncFunctionDeclaration):
+        * parser/Parser.h:
+        (JSC::Parser<LexerType>::parse):
+        (JSC::parse):
+        (JSC::parseFunctionForFunctionConstructor):
+        * parser/ParserModes.h:
+        * parser/ParserTokens.h:
+        (JSC::JSTextPosition::JSTextPosition):
+        (JSC::JSTokenLocation::JSTokenLocation): Deleted.
+        * parser/SourceCodeKey.h:
+        (JSC::SourceCodeKey::SourceCodeKey):
+        (JSC::SourceCodeKey::operator== const):
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
+        (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+        * runtime/CodeCache.h:
+        * runtime/FunctionConstructor.cpp:
+        (JSC::constructFunctionSkippingEvalEnabledCheck):
+        * runtime/FunctionExecutable.cpp:
+        (JSC::FunctionExecutable::fromGlobalCode):
+        * runtime/FunctionExecutable.h:
+
 2018-10-18  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r237242.
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
index e540a24..71b1374 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
@@ -174,14 +174,14 @@
 
 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
     const Identifier& name, ExecState& exec, const SourceCode& source, 
-    JSObject*& exception, int overrideLineNumber)
+    JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
 {
     ParserError error;
     VM& vm = exec.vm();
     auto& globalObject = *exec.lexicalGlobalObject();
     CodeCache* codeCache = vm.codeCache();
     DebuggerMode debuggerMode = globalObject.hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
-    UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, error);
+    UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, functionConstructorParametersEndPosition, error);
 
     if (globalObject.hasDebugger())
         globalObject.debugger()->sourceParsed(&exec, source.provider(), error.line(), error.message());
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
index f9e8939..313d666 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
@@ -107,7 +107,7 @@
 
     static UnlinkedFunctionExecutable* fromGlobalCode(
         const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, 
-        int overrideLineNumber);
+        int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
 
     JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, std::optional<int> overrideLineNumber = std::nullopt, Intrinsic = NoIntrinsic);
 
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index 4395dc2..935ad3f 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -194,7 +194,7 @@
 }
 
 template <typename LexerType>
-String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
+String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
 {
     String parseError = String();
 
@@ -238,6 +238,8 @@
             sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
         else if (isAsyncGeneratorWrapperParseMode(parseMode))
             sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
+        else if (parsingContext == ParsingContext::FunctionConstructor)
+            sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition);
         else
             sourceElements = parseSourceElements(context, CheckForStrictMode);
     }
@@ -610,6 +612,38 @@
         
     return sourceElements;
 }
+
+template <typename LexerType>
+template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSingleFunction(TreeBuilder& context, std::optional<int> functionConstructorParametersEndPosition)
+{
+    TreeSourceElements sourceElements = context.createSourceElements();
+    TreeStatement statement = 0;
+    switch (m_token.m_type) {
+    case FUNCTION:
+        statement = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
+        break;
+    case IDENT:
+        if (*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped) {
+            next();
+            failIfFalse(match(FUNCTION) && !m_lexer->prevTerminator(), "Cannot parse the async function");
+            statement = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
+            break;
+        }
+        FALLTHROUGH;
+    default:
+        failDueToUnexpectedToken();
+        break;
+    }
+
+    if (statement) {
+        context.setEndOffset(statement, m_lastTokenEndPosition.offset);
+        context.appendStatement(sourceElements, statement);
+    }
+
+    propagateError();
+    return sourceElements;
+}
+
     
 template <typename LexerType>
 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
@@ -2263,7 +2297,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
+template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType, std::optional<int> functionConstructorParametersEndPosition)
 {
     RELEASE_ASSERT(isFunctionParseMode(mode));
 
@@ -2459,6 +2493,10 @@
         }
         
         matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
+
+        // If the code is invoked from function constructor, we need to ensure that parameters are only composed by the string offered as parameters.
+        if (functionConstructorParametersEndPosition)
+            semanticFailIfFalse(lastTokenEndPosition().offset == *functionConstructorParametersEndPosition, "Parameters should match arguments offered as parameters in Function constructor");
         
         // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
         // Set ConstructorKind to None for non-constructor methods of classes.
@@ -2593,7 +2631,7 @@
 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
 {
     ASSERT(match(FUNCTION));
     JSTokenLocation location(tokenLocation());
@@ -2630,7 +2668,7 @@
         functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     }
 
-    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
+    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this function");
     ASSERT(functionInfo.name);
 
     std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
@@ -2651,7 +2689,7 @@
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
 {
     ASSERT(match(FUNCTION));
     JSTokenLocation location(tokenLocation());
@@ -2688,7 +2726,7 @@
         functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     }
 
-    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this async function");
+    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this async function");
     failIfFalse(functionInfo.name, "Async function statements must have a name");
 
     std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h
index 4a6ee25..6533ef9 100644
--- a/Source/JavaScriptCore/parser/Parser.h
+++ b/Source/JavaScriptCore/parser/Parser.h
@@ -859,10 +859,8 @@
     unsigned m_index;
 };
 
-enum class ArgumentType {
-    Normal,
-    Spread
-};
+enum class ArgumentType { Normal, Spread };
+enum class ParsingContext { Program, FunctionConstructor, Eval };
 
 template <typename LexerType>
 class Parser {
@@ -874,7 +872,7 @@
     ~Parser();
 
     template <class ParsedNode>
-    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode);
+    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
 
     JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); }
@@ -1312,7 +1310,8 @@
     }
 
     Parser();
-    String parseInner(const Identifier&, SourceParseMode);
+
+    String parseInner(const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
 
     void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int);
 
@@ -1524,13 +1523,14 @@
     template <class TreeBuilder> TreeSourceElements parseGeneratorFunctionSourceElements(TreeBuilder&, const Identifier& name, SourceElementsMode);
     template <class TreeBuilder> TreeSourceElements parseAsyncFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
     template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
+    template <class TreeBuilder> TreeSourceElements parseSingleFunction(TreeBuilder&, std::optional<int> functionConstructorParametersEndPosition);
     template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
     enum class ExportType { Exported, NotExported };
     template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
-    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
+    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
     template <class TreeBuilder> TreeStatement parseFunctionDeclarationStatement(TreeBuilder&, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement);
-    template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
+    template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
     template <class TreeBuilder> NEVER_INLINE bool maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement);
     template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported);
     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
@@ -1599,7 +1599,7 @@
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression createResolveAndUseVariable(TreeBuilder&, const Identifier*, bool isEval, const JSTextPosition&, const JSTokenLocation&);
 
     enum class FunctionDefinitionType { Expression, Declaration, Method };
-    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
+    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
     
     ALWAYS_INLINE bool isArrowFunctionParameters();
     
@@ -1847,7 +1847,7 @@
 
 template <typename LexerType>
 template <class ParsedNode>
-std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode)
+std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
 {
     int errLine;
     String errMsg;
@@ -1864,7 +1864,7 @@
     ASSERT(m_source->startColumn() > OrdinalNumber::beforeFirst());
     unsigned startColumn = m_source->startColumn().zeroBasedInt();
 
-    String parseError = parseInner(calleeName, parseMode);
+    String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition);
 
     int lineNumber = m_lexer->lineNumber();
     bool lexError = m_lexer->sawError();
@@ -1959,7 +1959,7 @@
     std::unique_ptr<ParsedNode> result;
     if (source.provider()->source().is8Bit()) {
         Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData);
-        result = parser.parse<ParsedNode>(error, name, parseMode);
+        result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
         if (builtinMode == JSParserBuiltinMode::Builtin) {
@@ -1972,7 +1972,7 @@
     } else {
         ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string");
         Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData);
-        result = parser.parse<ParsedNode>(error, name, parseMode);
+        result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     }
@@ -1986,4 +1986,37 @@
     return result;
 }
 
+inline std::unique_ptr<ProgramNode> parseFunctionForFunctionConstructor(VM& vm, const SourceCode& source, ParserError& error, JSTextPosition* positionBeforeLastNewline, std::optional<int> functionConstructorParametersEndPosition)
+{
+    ASSERT(!source.provider()->source().isNull());
+
+    MonotonicTime before;
+    if (UNLIKELY(Options::reportParseTimes()))
+        before = MonotonicTime::now();
+
+    Identifier name;
+    bool isEvalNode = false;
+    std::unique_ptr<ProgramNode> result;
+    if (source.provider()->source().is8Bit()) {
+        Parser<Lexer<LChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr);
+        result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition);
+        if (positionBeforeLastNewline)
+            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
+    } else {
+        Parser<Lexer<UChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr);
+        result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition);
+        if (positionBeforeLastNewline)
+            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
+    }
+
+    if (UNLIKELY(Options::reportParseTimes())) {
+        MonotonicTime after = MonotonicTime::now();
+        ParseHash hash(source);
+        dataLogLn(result ? "Parsed #" : "Failed to parse #", hash.hashForCall(), "/#", hash.hashForConstruct(), " in ", (after - before).milliseconds(), " ms.");
+    }
+
+    return result;
+}
+
+
 } // namespace
diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h
index 6960e51..9e637c4 100644
--- a/Source/JavaScriptCore/parser/ParserModes.h
+++ b/Source/JavaScriptCore/parser/ParserModes.h
@@ -33,7 +33,6 @@
 enum class JSParserStrictMode { NotStrict, Strict };
 enum class JSParserBuiltinMode { NotBuiltin, Builtin };
 enum class JSParserScriptMode { Classic, Module };
-enum class JSParserCodeType { Program, Function, Module };
 
 enum class ConstructorKind { None, Base, Extends };
 enum class SuperBinding { Needed, NotNeeded };
diff --git a/Source/JavaScriptCore/parser/ParserTokens.h b/Source/JavaScriptCore/parser/ParserTokens.h
index 8692603..59cb0fb 100644
--- a/Source/JavaScriptCore/parser/ParserTokens.h
+++ b/Source/JavaScriptCore/parser/ParserTokens.h
@@ -193,7 +193,6 @@
 struct JSTextPosition {
     JSTextPosition() = default;
     JSTextPosition(int _line, int _offset, int _lineStartOffset) : line(_line), offset(_offset), lineStartOffset(_lineStartOffset) { }
-    JSTextPosition(const JSTextPosition& other) : line(other.line), offset(other.offset), lineStartOffset(other.lineStartOffset) { }
 
     JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); }
     JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); }
@@ -246,13 +245,6 @@
 
 struct JSTokenLocation {
     JSTokenLocation() = default;
-    JSTokenLocation(const JSTokenLocation& location)
-    {
-        line = location.line;
-        lineStartOffset = location.lineStartOffset;
-        startOffset = location.startOffset;
-        endOffset = location.endOffset;
-    }
 
     int line { 0 };
     unsigned lineStartOffset { 0 };
diff --git a/Source/JavaScriptCore/parser/SourceCodeKey.h b/Source/JavaScriptCore/parser/SourceCodeKey.h
index abe4181..b0f0575 100644
--- a/Source/JavaScriptCore/parser/SourceCodeKey.h
+++ b/Source/JavaScriptCore/parser/SourceCodeKey.h
@@ -29,6 +29,7 @@
 #include "ParserModes.h"
 #include "UnlinkedSourceCode.h"
 #include <wtf/HashTraits.h>
+#include <wtf/Hasher.h>
 
 namespace JSC {
 
@@ -71,18 +72,17 @@
 
 class SourceCodeKey {
 public:
-    SourceCodeKey()
-    {
-    }
+    SourceCodeKey() = default;
 
     SourceCodeKey(
         const UnlinkedSourceCode& sourceCode, const String& name, SourceCodeType codeType, JSParserStrictMode strictMode, 
         JSParserScriptMode scriptMode, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext,
-        DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled)
+        DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled, std::optional<int> functionConstructorParametersEndPosition)
             : m_sourceCode(sourceCode)
             , m_name(name)
             , m_flags(codeType, strictMode, scriptMode, derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, typeProfilerEnabled, controlFlowProfilerEnabled)
-            , m_hash(sourceCode.hash() ^ m_flags.bits())
+            , m_functionConstructorParametersEndPosition(functionConstructorParametersEndPosition.value_or(-1))
+            , m_hash(sourceCode.hash() ^ computeHash(m_flags.bits(), m_functionConstructorParametersEndPosition))
     {
     }
 
@@ -108,6 +108,7 @@
         return m_hash == other.m_hash
             && length() == other.length()
             && m_flags == other.m_flags
+            && m_functionConstructorParametersEndPosition == other.m_functionConstructorParametersEndPosition
             && m_name == other.m_name
             && string() == other.string();
     }
@@ -127,7 +128,8 @@
     UnlinkedSourceCode m_sourceCode;
     String m_name;
     SourceCodeFlags m_flags;
-    unsigned m_hash;
+    int m_functionConstructorParametersEndPosition { -1 };
+    unsigned m_hash { 0 };
 };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp
index 00a827a..faafb72 100644
--- a/Source/JavaScriptCore/runtime/CodeCache.cpp
+++ b/Source/JavaScriptCore/runtime/CodeCache.cpp
@@ -57,7 +57,8 @@
         source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictMode, scriptMode, 
         derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, 
         vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
-        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
+        std::nullopt);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
     if (cache && Options::useCodeCache()) {
         UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
@@ -95,7 +96,7 @@
     return getUnlinkedGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, JSParserStrictMode::Strict, JSParserScriptMode::Module, debuggerMode, error, EvalContextType::None);
 }
 
-UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, ParserError& error)
+UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError& error)
 {
     bool isArrowFunctionContext = false;
     SourceCodeKey key(
@@ -107,7 +108,8 @@
         isArrowFunctionContext,
         debuggerMode, 
         vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
-        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
+        functionConstructorParametersEndPosition);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
     if (cache && Options::useCodeCache()) {
         UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
@@ -117,25 +119,14 @@
     }
 
     JSTextPosition positionBeforeLastNewline;
-    std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
-        &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin,
-        JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded,
-        error, &positionBeforeLastNewline);
+    std::unique_ptr<ProgramNode> program = parseFunctionForFunctionConstructor(vm, source, error, &positionBeforeLastNewline, functionConstructorParametersEndPosition);
     if (!program) {
         RELEASE_ASSERT(error.isValid());
         return nullptr;
     }
 
     // This function assumes an input string that would result in a single function declaration.
-    StatementNode* statement = program->singleStatement();
-    if (UNLIKELY(!statement)) {
-        JSToken token;
-        error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
-        return nullptr;
-    }
-    ASSERT(statement->isBlock());
-
-    StatementNode* funcDecl = static_cast<BlockNode*>(statement)->singleStatement();
+    StatementNode* funcDecl = program->singleStatement();
     if (UNLIKELY(!funcDecl)) {
         JSToken token;
         error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h
index ab70b65..53e3fda 100644
--- a/Source/JavaScriptCore/runtime/CodeCache.h
+++ b/Source/JavaScriptCore/runtime/CodeCache.h
@@ -194,7 +194,7 @@
     UnlinkedProgramCodeBlock* getUnlinkedProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserStrictMode, DebuggerMode, ParserError&);
     UnlinkedEvalCodeBlock* getUnlinkedEvalCodeBlock(VM&, IndirectEvalExecutable*, const SourceCode&, JSParserStrictMode, DebuggerMode, ParserError&, EvalContextType);
     UnlinkedModuleProgramCodeBlock* getUnlinkedModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, DebuggerMode, ParserError&);
-    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, ParserError&);
+    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError&);
 
     void clear() { m_sourceCode.clear(); }
 
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index 265049f..9b3d35d 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -94,82 +94,48 @@
         prefix = "async function ";
         break;
     case FunctionConstructionMode::AsyncGenerator:
-        prefix = "{async function*";
+        prefix = "async function*";
         break;
     }
 
-    auto checkBody = [&] (const String& body) {
-        // The spec mandates that the body parses a valid function body independent
-        // of the parameters.
-        String program = makeString("(", prefix, "(){\n", body, "\n})");
-        SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
-        JSValue exception;
-        checkSyntax(exec, source, &exception);
-        if (exception) {
-            scope.throwException(exec, exception);
-            return;
-        }
-    };
-
     // How we stringify functions is sometimes important for web compatibility.
     // See https://bugs.webkit.org/show_bug.cgi?id=24350.
     String program;
+    std::optional<int> functionConstructorParametersEndPosition = std::nullopt;
     if (args.isEmpty())
-        program = makeString("{", prefix, functionName.string(), "() {\n\n}}");
+        program = makeString(prefix, functionName.string(), "() {\n\n}");
     else if (args.size() == 1) {
         auto body = args.at(0).toWTFString(exec);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        checkBody(body);
-        RETURN_IF_EXCEPTION(scope, nullptr);
-        program = makeString("{", prefix, functionName.string(), "() {\n", body, "\n}}");
+        program = makeString(prefix, functionName.string(), "() {\n", body, "\n}");
     } else {
         StringBuilder builder;
-        builder.append('{');
         builder.append(prefix);
         builder.append(functionName.string());
+
         builder.append('(');
-        StringBuilder parameterBuilder;
         auto viewWithString = args.at(0).toString(exec)->viewWithUnderlyingString(exec);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        parameterBuilder.append(viewWithString.view);
+        builder.append(viewWithString.view);
         for (size_t i = 1; i < args.size() - 1; i++) {
-            parameterBuilder.appendLiteral(", ");
+            builder.appendLiteral(", ");
             auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(exec);
             RETURN_IF_EXCEPTION(scope, nullptr);
-            parameterBuilder.append(viewWithString.view);
+            builder.append(viewWithString.view);
         }
-        auto body = args.at(args.size() - 1).toWTFString(exec);
-        RETURN_IF_EXCEPTION(scope, nullptr);
-
-        {
-            // The spec mandates that the parameters parse as a valid parameter list
-            // independent of the function body.
-            String program = tryMakeString("(", prefix, "(", parameterBuilder.toString(), "){\n\n})");
-            if (UNLIKELY(!program)) {
-                throwOutOfMemoryError(exec, scope);
-                return nullptr;
-            }
-            SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
-            JSValue exception;
-            checkSyntax(exec, source, &exception);
-            if (exception) {
-                scope.throwException(exec, exception);
-                return nullptr;
-            }
-        }
-
-        builder.append(parameterBuilder);
+        functionConstructorParametersEndPosition = builder.length() + 1;
         builder.appendLiteral(") {\n");
-        checkBody(body);
+
+        auto body = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(exec);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        builder.append(body);
-        builder.appendLiteral("\n}}");
+        builder.append(body.view);
+        builder.appendLiteral("\n}");
         program = builder.toString();
     }
 
     SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
     JSObject* exception = nullptr;
-    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber);
+    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
     if (!function) {
         ASSERT(exception);
         return throwException(exec, scope, exception);
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
index d5770d4..eed3c21 100644
--- a/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
@@ -94,11 +94,11 @@
 
 FunctionExecutable* FunctionExecutable::fromGlobalCode(
     const Identifier& name, ExecState& exec, const SourceCode& source, 
-    JSObject*& exception, int overrideLineNumber)
+    JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
 {
     UnlinkedFunctionExecutable* unlinkedExecutable = 
         UnlinkedFunctionExecutable::fromGlobalCode(
-            name, exec, source, exception, overrideLineNumber);
+            name, exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
     if (!unlinkedExecutable)
         return nullptr;
 
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutable.h b/Source/JavaScriptCore/runtime/FunctionExecutable.h
index 3a93b58..6ba85a1 100644
--- a/Source/JavaScriptCore/runtime/FunctionExecutable.h
+++ b/Source/JavaScriptCore/runtime/FunctionExecutable.h
@@ -55,7 +55,7 @@
     }
     static FunctionExecutable* fromGlobalCode(
         const Identifier& name, ExecState&, const SourceCode&, 
-        JSObject*& exception, int overrideLineNumber);
+        JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
 
     static void destroy(JSCell*);