aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2017-08-01 11:36:44 -0500
committerMyles Borins <mylesborins@google.com>2017-08-01 15:23:15 -0500
commit0a66b223e149a841669bfad5598e4254589730cb (patch)
tree5ec050f7f78aafbf5b1e0e50d639fb843141e162 /deps/v8/src/parsing
parent1782b3836ba58ef0da6b687f2bb970c0bd8199ad (diff)
downloadandroid-node-v8-0a66b223e149a841669bfad5598e4254589730cb.tar.gz
android-node-v8-0a66b223e149a841669bfad5598e4254589730cb.tar.bz2
android-node-v8-0a66b223e149a841669bfad5598e4254589730cb.zip
deps: update V8 to 6.0.286.52
PR-URL: https://github.com/nodejs/node/pull/14004 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r--deps/v8/src/parsing/parse-info.cc36
-rw-r--r--deps/v8/src/parsing/parse-info.h27
-rw-r--r--deps/v8/src/parsing/parser-base.h179
-rw-r--r--deps/v8/src/parsing/parser.cc464
-rw-r--r--deps/v8/src/parsing/parser.h41
-rw-r--r--deps/v8/src/parsing/preparse-data-format.h2
-rw-r--r--deps/v8/src/parsing/preparse-data.cc9
-rw-r--r--deps/v8/src/parsing/preparse-data.h31
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.cc119
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.h39
-rw-r--r--deps/v8/src/parsing/preparser.cc54
-rw-r--r--deps/v8/src/parsing/preparser.h91
-rw-r--r--deps/v8/src/parsing/rewriter.cc4
-rw-r--r--deps/v8/src/parsing/scanner-character-streams.cc14
-rw-r--r--deps/v8/src/parsing/scanner.cc45
-rw-r--r--deps/v8/src/parsing/scanner.h8
16 files changed, 680 insertions, 483 deletions
diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc
index 816a854654..12329307ac 100644
--- a/deps/v8/src/parsing/parse-info.cc
+++ b/deps/v8/src/parsing/parse-info.cc
@@ -50,7 +50,6 @@ ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared)
set_toplevel(shared->is_toplevel());
set_allow_lazy_parsing(FLAG_lazy_inner_functions);
set_is_named_expression(shared->is_named_expression());
- set_calls_eval(shared->scope_info()->CallsEval());
set_compiler_hints(shared->compiler_hints());
set_start_position(shared->start_position());
set_end_position(shared->end_position());
@@ -58,7 +57,6 @@ ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared)
set_language_mode(shared->language_mode());
set_shared_info(shared);
set_module(shared->kind() == FunctionKind::kModule);
- set_scope_info_is_empty(shared->scope_info() == ScopeInfo::Empty(isolate));
Handle<Script> script(Script::cast(shared->script()));
set_script(script);
@@ -107,7 +105,6 @@ ParseInfo* ParseInfo::AllocateWithoutScript(Handle<SharedFunctionInfo> shared) {
p->set_toplevel(shared->is_toplevel());
p->set_allow_lazy_parsing(FLAG_lazy_inner_functions);
p->set_is_named_expression(shared->is_named_expression());
- p->set_calls_eval(shared->scope_info()->CallsEval());
p->set_compiler_hints(shared->compiler_hints());
p->set_start_position(shared->start_position());
p->set_end_position(shared->end_position());
@@ -115,7 +112,6 @@ ParseInfo* ParseInfo::AllocateWithoutScript(Handle<SharedFunctionInfo> shared) {
p->set_language_mode(shared->language_mode());
p->set_shared_info(shared);
p->set_module(shared->kind() == FunctionKind::kModule);
- p->set_scope_info_is_empty(shared->scope_info() == ScopeInfo::Empty(isolate));
// BUG(5946): This function exists as a workaround until we can
// get rid of %SetCode in our native functions. The ParseInfo
@@ -168,6 +164,38 @@ void ParseInfo::InitFromIsolate(Isolate* isolate) {
set_ast_string_constants(isolate->ast_string_constants());
}
+void ParseInfo::UpdateStatisticsAfterBackgroundParse(Isolate* isolate) {
+ // Copy over the counters from the background thread to the main counters on
+ // the isolate.
+ RuntimeCallStats* main_call_stats = isolate->counters()->runtime_call_stats();
+ if (FLAG_runtime_stats ==
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) {
+ DCHECK_NE(main_call_stats, runtime_call_stats());
+ DCHECK_NOT_NULL(main_call_stats);
+ DCHECK_NOT_NULL(runtime_call_stats());
+ main_call_stats->Add(runtime_call_stats());
+ }
+ set_runtime_call_stats(main_call_stats);
+}
+
+void ParseInfo::ParseFinished(std::unique_ptr<ParseInfo> info) {
+ if (info->literal()) {
+ base::LockGuard<base::Mutex> access_child_infos(&child_infos_mutex_);
+ child_infos_.emplace_back(std::move(info));
+ }
+}
+
+std::map<int, ParseInfo*> ParseInfo::child_infos() const {
+ base::LockGuard<base::Mutex> access_child_infos(&child_infos_mutex_);
+ std::map<int, ParseInfo*> rv;
+ for (const auto& child_info : child_infos_) {
+ DCHECK_NOT_NULL(child_info->literal());
+ int start_position = child_info->literal()->start_position();
+ rv.insert(std::make_pair(start_position, child_info.get()));
+ }
+ return rv;
+}
+
#ifdef DEBUG
bool ParseInfo::script_is_native() const {
return script_->type() == Script::TYPE_NATIVE;
diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h
index c115126191..5d8bb9c8eb 100644
--- a/deps/v8/src/parsing/parse-info.h
+++ b/deps/v8/src/parsing/parse-info.h
@@ -5,9 +5,12 @@
#ifndef V8_PARSING_PARSE_INFO_H_
#define V8_PARSING_PARSE_INFO_H_
+#include <map>
#include <memory>
+#include <vector>
#include "include/v8.h"
+#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/parsing/preparsed-scope-data.h"
@@ -33,7 +36,7 @@ class Utf16CharacterStream;
class Zone;
// A container for the inputs, configuration options, and outputs of parsing.
-class V8_EXPORT_PRIVATE ParseInfo {
+class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
public:
explicit ParseInfo(AccountingAllocator* zone_allocator);
ParseInfo(Handle<Script> script);
@@ -74,10 +77,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
set_ast_value_factory_owned)
FLAG_ACCESSOR(kIsNamedExpression, is_named_expression,
set_is_named_expression)
- FLAG_ACCESSOR(kCallsEval, calls_eval, set_calls_eval)
FLAG_ACCESSOR(kDebug, is_debug, set_is_debug)
FLAG_ACCESSOR(kSerializing, will_serialize, set_will_serialize)
- FLAG_ACCESSOR(kScopeInfoIsEmpty, scope_info_is_empty, set_scope_info_is_empty)
FLAG_ACCESSOR(kTailCallEliminationEnabled, is_tail_call_elimination_enabled,
set_tail_call_elimination_enabled)
@@ -245,6 +246,13 @@ class V8_EXPORT_PRIVATE ParseInfo {
}
}
+ void UpdateStatisticsAfterBackgroundParse(Isolate* isolate);
+
+ // The key of the map is the FunctionLiteral's start_position
+ std::map<int, ParseInfo*> child_infos() const;
+
+ void ParseFinished(std::unique_ptr<ParseInfo> info) override;
+
#ifdef DEBUG
bool script_is_native() const;
#endif // DEBUG
@@ -262,12 +270,10 @@ class V8_EXPORT_PRIVATE ParseInfo {
kModule = 1 << 6,
kAllowLazyParsing = 1 << 7,
kIsNamedExpression = 1 << 8,
- kCallsEval = 1 << 9,
- kDebug = 1 << 10,
- kSerializing = 1 << 11,
- kScopeInfoIsEmpty = 1 << 12,
- kTailCallEliminationEnabled = 1 << 13,
- kAstValueFactoryOwned = 1 << 14,
+ kDebug = 1 << 9,
+ kSerializing = 1 << 10,
+ kTailCallEliminationEnabled = 1 << 11,
+ kAstValueFactoryOwned = 1 << 12,
};
//------------- Inputs to parsing and scope analysis -----------------------
@@ -307,6 +313,9 @@ class V8_EXPORT_PRIVATE ParseInfo {
FunctionLiteral* literal_;
std::shared_ptr<DeferredHandles> deferred_handles_;
+ std::vector<std::unique_ptr<ParseInfo>> child_infos_;
+ mutable base::Mutex child_infos_mutex_;
+
void SetFlag(Flag f) { flags_ |= f; }
void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
bool GetFlag(Flag f) const { return (flags_ & f) != 0; }
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index 1dbad01dea..2d01398980 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -20,6 +20,7 @@
namespace v8 {
namespace internal {
+class PreParsedScopeData;
enum FunctionNameValidity {
kFunctionNameIsStrictReserved,
@@ -200,6 +201,7 @@ class ParserBase {
ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
v8::Extension* extension, AstValueFactory* ast_value_factory,
RuntimeCallStats* runtime_call_stats,
+ PreParsedScopeData* preparsed_scope_data,
bool parsing_on_main_thread = true)
: scope_(nullptr),
original_scope_(nullptr),
@@ -207,11 +209,12 @@ class ParserBase {
extension_(extension),
fni_(nullptr),
ast_value_factory_(ast_value_factory),
- ast_node_factory_(ast_value_factory),
+ ast_node_factory_(ast_value_factory, zone),
runtime_call_stats_(runtime_call_stats),
parsing_on_main_thread_(parsing_on_main_thread),
parsing_module_(false),
stack_limit_(stack_limit),
+ preparsed_scope_data_(preparsed_scope_data),
zone_(zone),
classifier_(nullptr),
scanner_(scanner),
@@ -448,6 +451,30 @@ class ParserBase {
next_function_is_likely_called_ = true;
}
+ void RecordFunctionOrEvalCall() { contains_function_or_eval_ = true; }
+ bool contains_function_or_eval() const {
+ return contains_function_or_eval_;
+ }
+
+ class FunctionOrEvalRecordingScope {
+ public:
+ explicit FunctionOrEvalRecordingScope(FunctionState* state)
+ : state_(state) {
+ prev_value_ = state->contains_function_or_eval_;
+ state->contains_function_or_eval_ = false;
+ }
+ ~FunctionOrEvalRecordingScope() {
+ bool found = state_->contains_function_or_eval_;
+ if (!found) {
+ state_->contains_function_or_eval_ = prev_value_;
+ }
+ }
+
+ private:
+ FunctionState* state_;
+ bool prev_value_;
+ };
+
private:
void AddDestructuringAssignment(DestructuringAssignment pair) {
destructuring_assignments_to_rewrite_.Add(pair, scope_->zone());
@@ -482,6 +509,9 @@ class ParserBase {
bool next_function_is_likely_called_;
bool previous_function_was_likely_called_;
+ // Track if a function or eval occurs within this FunctionState
+ bool contains_function_or_eval_;
+
friend Impl;
};
@@ -601,7 +631,8 @@ class ParserBase {
constructor(parser->impl()->EmptyFunctionLiteral()),
has_seen_constructor(false),
has_name_static_property(false),
- has_static_computed_names(false) {}
+ has_static_computed_names(false),
+ is_anonymous(false) {}
VariableProxy* proxy;
ExpressionT extends;
typename Types::ClassPropertyList properties;
@@ -609,6 +640,7 @@ class ParserBase {
bool has_seen_constructor;
bool has_name_static_property;
bool has_static_computed_names;
+ bool is_anonymous;
};
DeclarationScope* NewScriptScope() const {
@@ -653,6 +685,10 @@ class ParserBase {
if (target_zone == nullptr) target_zone = zone();
DeclarationScope* result = new (target_zone)
DeclarationScope(zone(), scope(), FUNCTION_SCOPE, kind);
+
+ // Record presence of an inner function scope
+ function_state_->RecordFunctionOrEvalCall();
+
// TODO(verwaest): Move into the DeclarationScope constructor.
if (!IsArrowFunction(kind)) {
result->DeclareDefaultFunctionVariables(ast_value_factory());
@@ -1337,6 +1373,7 @@ class ParserBase {
if (impl()->IsIdentifier(expression) &&
impl()->IsEval(impl()->AsIdentifier(expression))) {
scope->RecordEvalCall();
+ function_state_->RecordFunctionOrEvalCall();
if (is_sloppy(scope->language_mode())) {
// For sloppy scopes we also have to record the call at function level,
// in case it includes declarations that will be hoisted.
@@ -1486,6 +1523,7 @@ class ParserBase {
bool parsing_on_main_thread_;
bool parsing_module_;
uintptr_t stack_limit_;
+ PreParsedScopeData* preparsed_scope_data_;
// Parser base's private field members.
@@ -1530,7 +1568,8 @@ ParserBase<Impl>::FunctionState::FunctionState(
non_patterns_to_rewrite_(0, scope->zone()),
reported_errors_(16, scope->zone()),
next_function_is_likely_called_(false),
- previous_function_was_likely_called_(false) {
+ previous_function_was_likely_called_(false),
+ contains_function_or_eval_(false) {
*function_state_stack = this;
if (outer_function_state_) {
outer_function_state_->previous_function_was_likely_called_ =
@@ -1933,6 +1972,11 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
int ellipsis_pos = position();
int pattern_pos = peek_position();
ExpressionT pattern = ParsePrimaryExpression(CHECK_OK);
+ if (peek() == Token::ASSIGN) {
+ ReportMessage(MessageTemplate::kRestDefaultInitializer);
+ *ok = false;
+ return result;
+ }
ValidateBindingPattern(CHECK_OK);
right = factory()->NewSpread(pattern, ellipsis_pos, pattern_pos);
} else {
@@ -2222,12 +2266,12 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
Token::Value name_token = peek();
- int function_token_position = scanner()->peek_location().beg_pos;
+ int name_token_position = scanner()->peek_location().beg_pos;
IdentifierT name = impl()->EmptyIdentifier();
ExpressionT name_expression;
if (name_token == Token::STATIC) {
Consume(Token::STATIC);
- function_token_position = scanner()->peek_location().beg_pos;
+ name_token_position = scanner()->peek_location().beg_pos;
if (peek() == Token::LPAREN) {
kind = PropertyKind::kMethodProperty;
name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static'
@@ -2305,7 +2349,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
ExpressionT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? function_token_position
+ FLAG_harmony_function_tostring ? name_token_position
: kNoSourcePosition,
FunctionLiteral::kAccessorOrMethod, language_mode(),
CHECK_OK_CUSTOM(EmptyClassLiteralProperty));
@@ -2335,7 +2379,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
FunctionLiteralT value = impl()->ParseFunctionLiteral(
name, scanner()->location(), kSkipFunctionNameCheck, kind,
- FLAG_harmony_function_tostring ? function_token_position
+ FLAG_harmony_function_tostring ? name_token_position
: kNoSourcePosition,
FunctionLiteral::kAccessorOrMethod, language_mode(),
CHECK_OK_CUSTOM(EmptyClassLiteralProperty));
@@ -2351,7 +2395,11 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
*is_computed_name);
}
case PropertyKind::kSpreadProperty:
- UNREACHABLE();
+ ReportUnexpectedTokenAt(
+ Scanner::Location(name_token_position, name_expression->position()),
+ name_token);
+ *ok = false;
+ return impl()->EmptyClassLiteralProperty();
}
UNREACHABLE();
return impl()->EmptyClassLiteralProperty();
@@ -2672,6 +2720,10 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
spread_arg.beg_pos = start_pos;
spread_arg.end_pos = peek_position();
}
+ if (argument->IsAssignment()) {
+ classifier()->RecordAsyncArrowFormalParametersError(
+ scanner()->location(), MessageTemplate::kRestDefaultInitializer);
+ }
argument = factory()->NewSpread(argument, start_pos, expr_pos);
}
result->Add(argument, zone_);
@@ -2684,6 +2736,10 @@ typename ParserBase<Impl>::ExpressionListT ParserBase<Impl>::ParseArguments(
done = (peek() != Token::COMMA);
if (!done) {
Next();
+ if (argument->IsSpread()) {
+ classifier()->RecordAsyncArrowFormalParametersError(
+ scanner()->location(), MessageTemplate::kParamAfterRest);
+ }
if (allow_harmony_trailing_commas() && peek() == Token::RPAREN) {
// allow trailing comma
done = true;
@@ -3265,6 +3321,9 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
// Explicit calls to the super constructor using super() perform an
// implicit binding assignment to the 'this' variable.
if (is_super_call) {
+ classifier()->RecordAssignmentPatternError(
+ Scanner::Location(pos, scanner()->location().end_pos),
+ MessageTemplate::kInvalidDestructuringTarget);
ExpressionT this_expr = impl()->ThisExpression(pos);
result =
factory()->NewAssignment(Token::INIT, this_expr, result, pos);
@@ -3418,6 +3477,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression(
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
// "anonymous". We just want that name in the toString().
+ if (stack_overflow()) {
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
Consume(Token::IDENTIFIER);
DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
} else if (peek_any_identifier()) {
@@ -3506,6 +3569,10 @@ ParserBase<Impl>::ParseNewTargetExpression(bool* ok) {
int pos = position();
ExpectMetaProperty(Token::TARGET, "new.target", pos, CHECK_OK);
+ classifier()->RecordAssignmentPatternError(
+ Scanner::Location(pos, scanner()->location().end_pos),
+ MessageTemplate::kInvalidDestructuringTarget);
+
if (!GetReceiverScope()->is_function_scope()) {
impl()->ReportMessageAt(scanner()->location(),
MessageTemplate::kUnexpectedNewTarget);
@@ -3603,7 +3670,12 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
}
ExpressionT initializer = impl()->EmptyExpression();
- if (!is_rest && Check(Token::ASSIGN)) {
+ if (Check(Token::ASSIGN)) {
+ if (is_rest) {
+ ReportMessage(MessageTemplate::kRestDefaultInitializer);
+ *ok = false;
+ return;
+ }
ExpressionClassifier init_classifier(this);
initializer = ParseAssignmentExpression(true, CHECK_OK_CUSTOM(Void));
impl()->RewriteNonPattern(CHECK_OK_CUSTOM(Void));
@@ -4216,32 +4288,20 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// FIXME(marja): Arrow function parameters will be parsed even if the
// body is preparsed; move relevant parts of parameter handling to
// simulate consistent parameter handling.
- Scanner::BookmarkScope bookmark(scanner());
- bookmark.Set();
+
// For arrow functions, we don't need to retrieve data about function
// parameters.
int dummy_num_parameters = -1;
- int dummy_function_length = -1;
DCHECK((kind & FunctionKind::kArrowFunction) != 0);
- LazyParsingResult result = impl()->SkipFunction(
- kind, formal_parameters.scope, &dummy_num_parameters,
- &dummy_function_length, false, true, CHECK_OK);
- formal_parameters.scope->ResetAfterPreparsing(
- ast_value_factory_, result == kLazyParsingAborted);
-
- if (result == kLazyParsingAborted) {
- bookmark.Apply();
- // Trigger eager (re-)parsing, just below this block.
- is_lazy_top_level_function = false;
-
- // This is probably an initialization function. Inform the compiler it
- // should also eager-compile this function, and that we expect it to
- // be used once.
- eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
- should_be_used_once_hint = true;
- }
- }
- if (!is_lazy_top_level_function) {
+ LazyParsingResult result =
+ impl()->SkipFunction(kind, formal_parameters.scope,
+ &dummy_num_parameters, false, false, CHECK_OK);
+ DCHECK_NE(result, kLazyParsingAborted);
+ USE(result);
+ formal_parameters.scope->ResetAfterPreparsing(ast_value_factory_,
+ false);
+
+ } else {
Consume(Token::LBRACE);
body = impl()->NewStatementList(8);
impl()->ParseFunctionBody(body, impl()->EmptyIdentifier(),
@@ -4339,24 +4399,30 @@ template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
IdentifierT name, Scanner::Location class_name_location,
bool name_is_strict_reserved, int class_token_pos, bool* ok) {
+ bool is_anonymous = impl()->IsEmptyIdentifier(name);
+
// All parts of a ClassDeclaration and ClassExpression are strict code.
- if (name_is_strict_reserved) {
- impl()->ReportMessageAt(class_name_location,
- MessageTemplate::kUnexpectedStrictReserved);
- *ok = false;
- return impl()->EmptyExpression();
- }
- if (impl()->IsEvalOrArguments(name)) {
- impl()->ReportMessageAt(class_name_location,
- MessageTemplate::kStrictEvalArguments);
- *ok = false;
- return impl()->EmptyExpression();
+ if (!is_anonymous) {
+ if (name_is_strict_reserved) {
+ impl()->ReportMessageAt(class_name_location,
+ MessageTemplate::kUnexpectedStrictReserved);
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
+ if (impl()->IsEvalOrArguments(name)) {
+ impl()->ReportMessageAt(class_name_location,
+ MessageTemplate::kStrictEvalArguments);
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
}
- BlockState block_state(zone(), &scope_);
+ Scope* block_scope = NewScope(BLOCK_SCOPE);
+ BlockState block_state(&scope_, block_scope);
RaiseLanguageMode(STRICT);
ClassInfo class_info(this);
+ class_info.is_anonymous = is_anonymous;
impl()->DeclareClassVariable(name, &class_info, class_token_pos, CHECK_OK);
scope()->set_start_position(scanner()->location().end_pos);
@@ -4401,7 +4467,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
}
Expect(Token::RBRACE, CHECK_OK);
- return impl()->RewriteClassLiteral(name, &class_info, class_token_pos, ok);
+ int end_pos = scanner()->location().end_pos;
+ block_scope->set_end_position(end_pos);
+ return impl()->RewriteClassLiteral(block_scope, name, &class_info,
+ class_token_pos, end_pos, ok);
}
template <typename Impl>
@@ -4452,6 +4521,10 @@ ParserBase<Impl>::ParseAsyncFunctionLiteral(bool* ok) {
if (impl()->ParsingDynamicFunctionDeclaration()) {
// We don't want dynamic functions to actually declare their name
// "anonymous". We just want that name in the toString().
+ if (stack_overflow()) {
+ *ok = false;
+ return impl()->EmptyExpression();
+ }
Consume(Token::IDENTIFIER);
DCHECK(scanner()->CurrentMatchesContextual(Token::ANONYMOUS));
} else if (peek_any_identifier()) {
@@ -5460,6 +5533,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
ZoneList<const AstRawString*>* labels, bool* ok) {
+ typename FunctionState::FunctionOrEvalRecordingScope recording_scope(
+ function_state_);
int stmt_pos = peek_position();
ForInfo for_info(this);
bool bound_names_are_lexical = false;
@@ -5469,7 +5544,6 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
Expect(Token::FOR, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
scope()->set_start_position(scanner()->location().beg_pos);
- scope()->set_is_hidden();
StatementT init = impl()->NullStatement();
@@ -5527,6 +5601,7 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithDeclarations(
int stmt_pos, ForInfo* for_info, ZoneList<const AstRawString*>* labels,
bool* ok) {
+ scope()->set_is_hidden();
// Just one declaration followed by in/of.
if (for_info->parsing_result.declarations.length() != 1) {
impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
@@ -5607,6 +5682,7 @@ typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
ForInfo* for_info, ZoneList<const AstRawString*>* labels, bool* ok) {
+ scope()->set_is_hidden();
// Initializer is reference followed by in/of.
if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
expression = impl()->CheckAndRewriteReferenceExpression(
@@ -5690,15 +5766,15 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop(
body = ParseStatement(nullptr, CHECK_OK);
}
- if (bound_names_are_lexical && for_info->bound_names.length() > 0) {
- auto result = impl()->DesugarLexicalBindingsInForStatement(
+ scope()->set_end_position(scanner()->location().end_pos);
+ inner_scope->set_end_position(scanner()->location().end_pos);
+ if (bound_names_are_lexical && for_info->bound_names.length() > 0 &&
+ (is_resumable() || function_state_->contains_function_or_eval())) {
+ scope()->set_is_hidden();
+ return impl()->DesugarLexicalBindingsInForStatement(
loop, init, cond, next, body, inner_scope, *for_info, CHECK_OK);
- scope()->set_end_position(scanner()->location().end_pos);
- inner_scope->set_end_position(scanner()->location().end_pos);
- return result;
}
- scope()->set_end_position(scanner()->location().end_pos);
Scope* for_scope = scope()->FinalizeBlockScope();
if (for_scope != nullptr) {
// Rewrite a for statement of the form
@@ -5722,6 +5798,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop(
BlockT block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition);
if (!impl()->IsNullStatement(init)) {
block->statements()->Add(init, zone());
+ init = impl()->NullStatement();
}
block->statements()->Add(loop, zone());
block->set_scope(for_scope);
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index 6a2c2db0d1..a4f40dda53 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -4,6 +4,7 @@
#include "src/parsing/parser.h"
+#include <algorithm>
#include <memory>
#include "src/api.h"
@@ -14,6 +15,7 @@
#include "src/bailout-reason.h"
#include "src/base/platform/platform.h"
#include "src/char-predicates-inl.h"
+#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/messages.h"
#include "src/objects-inl.h"
#include "src/parsing/duplicate-finder.h"
@@ -109,8 +111,7 @@ int ParseData::FunctionsSize() {
class DiscardableZoneScope {
public:
DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone)
- : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone),
- fni_(parser->ast_value_factory_, temp_zone),
+ : fni_(parser->ast_value_factory_, temp_zone),
parser_(parser),
prev_fni_(parser->fni_),
prev_zone_(parser->zone_),
@@ -122,6 +123,7 @@ class DiscardableZoneScope {
parser_->temp_zoned_ = true;
parser_->fni_ = &fni_;
parser_->zone_ = temp_zone;
+ parser_->factory()->set_zone(temp_zone);
if (parser_->reusable_preparser_ != nullptr) {
parser_->reusable_preparser_->zone_ = temp_zone;
parser_->reusable_preparser_->factory()->set_zone(temp_zone);
@@ -131,18 +133,17 @@ class DiscardableZoneScope {
void Reset() {
parser_->fni_ = prev_fni_;
parser_->zone_ = prev_zone_;
+ parser_->factory()->set_zone(prev_zone_);
parser_->allow_lazy_ = prev_allow_lazy_;
parser_->temp_zoned_ = prev_temp_zoned_;
if (parser_->reusable_preparser_ != nullptr) {
parser_->reusable_preparser_->zone_ = prev_zone_;
parser_->reusable_preparser_->factory()->set_zone(prev_zone_);
}
- ast_node_factory_scope_.Reset();
}
~DiscardableZoneScope() { Reset(); }
private:
- AstNodeFactory::BodyScope ast_node_factory_scope_;
FuncNameInferrer fni_;
Parser* parser_;
FuncNameInferrer* prev_fni_;
@@ -250,60 +251,56 @@ bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
double y_val = y->AsLiteral()->raw_value()->AsNumber();
- bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
- bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
- bool has_dot = x_has_dot || y_has_dot;
switch (op) {
case Token::ADD:
- *x = factory()->NewNumberLiteral(x_val + y_val, pos, has_dot);
+ *x = factory()->NewNumberLiteral(x_val + y_val, pos);
return true;
case Token::SUB:
- *x = factory()->NewNumberLiteral(x_val - y_val, pos, has_dot);
+ *x = factory()->NewNumberLiteral(x_val - y_val, pos);
return true;
case Token::MUL:
- *x = factory()->NewNumberLiteral(x_val * y_val, pos, has_dot);
+ *x = factory()->NewNumberLiteral(x_val * y_val, pos);
return true;
case Token::DIV:
- *x = factory()->NewNumberLiteral(x_val / y_val, pos, has_dot);
+ *x = factory()->NewNumberLiteral(x_val / y_val, pos);
return true;
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
- *x = factory()->NewNumberLiteral(value, pos, has_dot);
+ *x = factory()->NewNumberLiteral(value, pos);
return true;
}
case Token::EXP: {
double value = Pow(x_val, y_val);
int int_value = static_cast<int>(value);
*x = factory()->NewNumberLiteral(
- int_value == value && value != -0.0 ? int_value : value, pos,
- has_dot);
+ int_value == value && value != -0.0 ? int_value : value, pos);
return true;
}
default:
@@ -325,15 +322,13 @@ Expression* Parser::BuildUnaryExpression(Expression* expression,
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->AsNumber();
- bool has_dot = literal->ContainsDot();
switch (op) {
case Token::ADD:
return expression;
case Token::SUB:
- return factory()->NewNumberLiteral(-value, pos, has_dot);
+ return factory()->NewNumberLiteral(-value, pos);
case Token::BIT_NOT:
- return factory()->NewNumberLiteral(~DoubleToInt32(value), pos,
- has_dot);
+ return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
default:
break;
}
@@ -342,7 +337,7 @@ Expression* Parser::BuildUnaryExpression(Expression* expression,
// Desugar '+foo' => 'foo*1'
if (op == Token::ADD) {
return factory()->NewBinaryOperation(
- Token::MUL, expression, factory()->NewNumberLiteral(1, pos, true), pos);
+ Token::MUL, expression, factory()->NewNumberLiteral(1, pos), pos);
}
// The same idea for '-foo' => 'foo*(-1)'.
if (op == Token::SUB) {
@@ -431,9 +426,8 @@ Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
return factory()->NewSmiLiteral(value, pos);
}
case Token::NUMBER: {
- bool has_dot = scanner()->ContainsDot();
double value = scanner()->DoubleValue();
- return factory()->NewNumberLiteral(value, pos, has_dot);
+ return factory()->NewNumberLiteral(value, pos);
}
default:
DCHECK(false);
@@ -503,7 +497,8 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
info->extension(), info->ast_value_factory(),
- info->runtime_call_stats(), true),
+ info->runtime_call_stats(),
+ info->preparsed_scope_data(), true),
scanner_(info->unicode_cache()),
reusable_preparser_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
@@ -513,7 +508,6 @@ Parser::Parser(ParseInfo* info)
total_preparse_skipped_(0),
temp_zoned_(false),
log_(nullptr),
- preparsed_scope_data_(info->preparsed_scope_data()),
parameters_end_pos_(info->parameters_end_pos()) {
// Even though we were passed ParseInfo, we should not store it in
// Parser - this makes sure that Isolate is not accidentally accessed via
@@ -621,25 +615,15 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
source = String::Flatten(source);
FunctionLiteral* result;
+ if (FLAG_use_parse_tasks) {
+ source_ = source;
+ compiler_dispatcher_ = isolate->compiler_dispatcher();
+ main_parse_info_ = info;
+ }
+
{
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source));
- if (FLAG_use_parse_tasks) {
- // FIXME(wiktorg) make it useful for something
- // TODO(wiktorg) make preparser work also with modules
- if (!info->is_module()) {
- scanner_.Initialize(stream.get());
- // NOTE: Some features will be double counted - once here and one more
- // time while being fully parsed by a parse task.
- PreParser::PreParseResult result =
- reusable_preparser()->PreParseProgram(false, use_counts_);
- if (result == PreParser::kPreParseStackOverflow) {
- set_stack_overflow();
- return nullptr;
- }
- stream->Seek(0);
- }
- }
- scanner_.Initialize(stream.get());
+ scanner_.Initialize(stream.get(), info->is_module());
result = DoParseProgram(info);
}
if (result != NULL) {
@@ -647,6 +631,14 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
}
HandleSourceURLComments(isolate, info->script());
+ if (FLAG_use_parse_tasks) {
+ compiler_dispatcher_->FinishAllNow();
+ StitchAst(info, isolate);
+ source_ = Handle<String>();
+ compiler_dispatcher_ = nullptr;
+ main_parse_info_ = nullptr;
+ }
+
if (FLAG_trace_parse && result != nullptr) {
double ms = timer.Elapsed().InMillisecondsF();
if (info->is_eval()) {
@@ -805,8 +797,9 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) {
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
source, shared_info->start_position(), shared_info->end_position()));
Handle<String> name(String::cast(shared_info->name()));
- scanner_.Initialize(stream.get());
- result = DoParseFunction(info, ast_value_factory()->GetString(name));
+ scanner_.Initialize(stream.get(), info->is_module());
+ info->set_function_name(ast_value_factory()->GetString(name));
+ result = DoParseFunction(info);
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
@@ -835,8 +828,25 @@ static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
return FunctionLiteral::kAnonymousExpression;
}
-FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
- const AstRawString* raw_name) {
+FunctionLiteral* Parser::DoParseFunction(ParseInfo* info) {
+ const AstRawString* raw_name = info->function_name();
+ FunctionNameValidity function_name_validity = kSkipFunctionNameCheck;
+ if (!raw_name) {
+ bool ok = true;
+ if (peek() == Token::LPAREN) {
+ const AstRawString* variable_name;
+ impl()->GetDefaultStrings(&raw_name, &variable_name);
+ } else {
+ bool is_strict_reserved = true;
+ raw_name = ParseIdentifierOrStrictReservedWord(info->function_kind(),
+ &is_strict_reserved, &ok);
+ if (!ok) return nullptr;
+ function_name_validity = is_strict_reserved
+ ? kFunctionNameIsStrictReserved
+ : kFunctionNameValidityUnknown;
+ }
+ }
+
DCHECK_NOT_NULL(raw_name);
DCHECK_NULL(scope_);
DCHECK_NULL(target_stack_);
@@ -955,7 +965,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
info->start_position(), info->end_position());
} else {
result = ParseFunctionLiteral(
- raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind,
+ raw_name, Scanner::Location::invalid(), function_name_validity, kind,
kNoSourcePosition, function_type, info->language_mode(), &ok);
}
// Make sure the results agree.
@@ -966,8 +976,6 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
DCHECK_NULL(target_stack_);
DCHECK_IMPLIES(result,
info->function_literal_id() == result->function_literal_id());
- DCHECK_IMPLIES(!info->scope_info_is_empty() && result,
- info->calls_eval() == result->scope()->calls_eval());
return result;
}
@@ -2605,11 +2613,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
DCHECK_IMPLIES(parse_lazily(), allow_lazy_);
DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
- bool can_preparse = parse_lazily() &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
-
- bool is_lazy_top_level_function =
- can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
+ const bool source_is_external =
+ !source_.is_null() && (source_->IsExternalTwoByteString() ||
+ source_->IsExternalOneByteString());
+ const bool is_lazy =
+ eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
+ const bool is_top_level =
+ impl()->AllowsLazyParsingWithoutUnresolvedVariables();
+ const bool is_lazy_top_level_function = is_lazy && is_top_level;
+ const bool is_lazy_inner_function = is_lazy && !is_top_level;
+ const bool is_eager_top_level_function = !is_lazy && is_top_level;
+ const bool is_declaration = function_type == FunctionLiteral::kDeclaration;
RuntimeCallTimerScope runtime_timer(
runtime_call_stats_,
@@ -2633,22 +2647,19 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// Inner functions will be parsed using a temporary Zone. After parsing, we
// will migrate unresolved variable into a Scope in the main Zone.
- // TODO(marja): Refactor parsing modes: simplify this.
- bool use_temp_zone =
- (FLAG_aggressive_lazy_inner_functions
- ? can_preparse
- : (is_lazy_top_level_function ||
- (parse_lazily() &&
- function_type == FunctionLiteral::kDeclaration &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile)));
-
- DCHECK_IMPLIES(
- (is_lazy_top_level_function ||
- (parse_lazily() && function_type == FunctionLiteral::kDeclaration &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile)),
- can_preparse);
- bool is_lazy_inner_function =
- use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function;
+
+ const bool should_preparse_inner =
+ parse_lazily() && FLAG_lazy_inner_functions && is_lazy_inner_function &&
+ (is_declaration || FLAG_aggressive_lazy_inner_functions);
+
+ bool should_use_parse_task =
+ FLAG_use_parse_tasks && parse_lazily() && compiler_dispatcher_ &&
+ is_eager_top_level_function && source_is_external;
+
+ // This may be modified later to reflect preparsing decision taken
+ bool should_preparse = (parse_lazily() && (is_lazy_top_level_function ||
+ should_use_parse_task)) ||
+ should_preparse_inner;
ZoneList<Statement*>* body = nullptr;
int expected_property_count = -1;
@@ -2658,14 +2669,40 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
bool has_duplicate_parameters = false;
int function_literal_id = GetNextFunctionLiteralId();
+ Expect(Token::LPAREN, CHECK_OK);
+
+ if (should_use_parse_task) {
+ int start_pos = scanner()->location().beg_pos;
+ if (function_name_location.IsValid()) {
+ start_pos = function_name_location.beg_pos;
+ }
+ // Warning!
+ // Only sets fields in compiler_hints that are currently used.
+ int compiler_hints = SharedFunctionInfo::FunctionKindBits::encode(kind);
+ if (function_type == FunctionLiteral::kDeclaration) {
+ compiler_hints |= 1 << SharedFunctionInfo::kIsDeclaration;
+ }
+ should_use_parse_task = compiler_dispatcher_->Enqueue(
+ source_, start_pos, source_->length(), language_mode,
+ function_literal_id, allow_natives(), parsing_module_,
+ function_type == FunctionLiteral::kNamedExpression, compiler_hints,
+ main_parse_info_, nullptr);
+ if (V8_UNLIKELY(FLAG_trace_parse_tasks)) {
+ PrintF("Spining off task for function at %d: %s\n", start_pos,
+ should_use_parse_task ? "SUCCESS" : "FAILED");
+ }
+ if (!should_use_parse_task) {
+ should_preparse = false;
+ }
+ }
+
Zone* outer_zone = zone();
DeclarationScope* scope;
{
// Temporary zones can nest. When we migrate free variables (see below), we
// need to recreate them in the previous Zone.
- AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
- previous_zone_ast_node_factory.set_zone(zone());
+ AstNodeFactory previous_zone_ast_node_factory(ast_value_factory(), zone());
// Open a new zone scope, which sets our AstNodeFactory to allocate in the
// new temporary zone if the preconditions are satisfied, and ensures that
@@ -2673,7 +2710,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// to do scope analysis correctly after full parsing, we migrate needed
// information when the function is parsed.
Zone temp_zone(zone()->allocator(), ZONE_NAME);
- DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
+ DiscardableZoneScope zone_scope(this, &temp_zone, should_preparse);
// This Scope lives in the main zone. We'll migrate data into that zone
// later.
@@ -2681,10 +2718,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
SetLanguageMode(scope, language_mode);
#ifdef DEBUG
scope->SetScopeName(function_name);
- if (use_temp_zone) scope->set_needs_migration();
+ if (should_preparse) scope->set_needs_migration();
#endif
-
- Expect(Token::LPAREN, CHECK_OK);
scope->set_start_position(scanner()->location().beg_pos);
// Eager or lazy parse? If is_lazy_top_level_function, we'll parse
@@ -2692,19 +2727,19 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// abort lazy parsing if it suspects that wasn't a good idea. If so (in
// which case the parser is expected to have backtracked), or if we didn't
// try to lazy parse in the first place, we'll have to parse eagerly.
- if (is_lazy_top_level_function || is_lazy_inner_function) {
+ if (should_preparse) {
+ DCHECK(parse_lazily());
+ DCHECK(is_lazy_top_level_function || is_lazy_inner_function ||
+ should_use_parse_task);
Scanner::BookmarkScope bookmark(scanner());
bookmark.Set();
- LazyParsingResult result = SkipFunction(
- kind, scope, &num_parameters, &function_length,
- is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK);
+ LazyParsingResult result =
+ SkipFunction(kind, scope, &num_parameters, is_lazy_inner_function,
+ is_lazy_top_level_function, CHECK_OK);
if (result == kLazyParsingAborted) {
DCHECK(is_lazy_top_level_function);
bookmark.Apply();
- // Trigger eager (re-)parsing, just below this block.
- is_lazy_top_level_function = false;
-
// This is probably an initialization function. Inform the compiler it
// should also eager-compile this function, and that we expect it to be
// used once.
@@ -2712,48 +2747,45 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
should_be_used_once_hint = true;
scope->ResetAfterPreparsing(ast_value_factory(), true);
zone_scope.Reset();
- use_temp_zone = false;
+ // Trigger eager (re-)parsing, just below this block.
+ should_preparse = false;
+ should_use_parse_task = false;
}
}
- if (!is_lazy_top_level_function && !is_lazy_inner_function) {
+ if (should_preparse) {
+ scope->AnalyzePartially(&previous_zone_ast_node_factory,
+ preparsed_scope_data_);
+ } else {
body = ParseFunction(function_name, pos, kind, function_type, scope,
&num_parameters, &function_length,
&has_duplicate_parameters, &expected_property_count,
CHECK_OK);
}
- DCHECK(use_temp_zone || !is_lazy_top_level_function);
- if (use_temp_zone) {
- // If the preconditions are correct the function body should never be
- // accessed, but do this anyway for better behaviour if they're wrong.
- body = nullptr;
- scope->AnalyzePartially(&previous_zone_ast_node_factory,
- preparsed_scope_data_);
- }
-
- DCHECK_IMPLIES(use_temp_zone, temp_zoned_);
- if (FLAG_trace_preparse) {
+ DCHECK_EQ(should_preparse, temp_zoned_);
+ if (V8_UNLIKELY(FLAG_trace_preparse)) {
PrintF(" [%s]: %i-%i %.*s\n",
- is_lazy_top_level_function
- ? "Preparse no-resolution"
- : (temp_zoned_ ? "Preparse resolution" : "Full parse"),
+ should_preparse ? (is_top_level ? "Preparse no-resolution"
+ : "Preparse resolution")
+ : "Full parse",
scope->start_position(), scope->end_position(),
function_name->byte_length(), function_name->raw_data());
}
if (V8_UNLIKELY(FLAG_runtime_stats)) {
- if (is_lazy_top_level_function) {
- RuntimeCallStats::CorrectCurrentCounterId(
- runtime_call_stats_,
- parsing_on_main_thread_
- ? &RuntimeCallStats::PreParseNoVariableResolution
- : &RuntimeCallStats::PreParseBackgroundNoVariableResolution);
- } else if (temp_zoned_) {
- RuntimeCallStats::CorrectCurrentCounterId(
- runtime_call_stats_,
+ if (should_preparse) {
+ RuntimeCallStats::CounterId counter_id =
parsing_on_main_thread_
? &RuntimeCallStats::PreParseWithVariableResolution
- : &RuntimeCallStats::PreParseBackgroundWithVariableResolution);
+ : &RuntimeCallStats::PreParseBackgroundWithVariableResolution;
+ if (is_top_level) {
+ counter_id =
+ parsing_on_main_thread_
+ ? &RuntimeCallStats::PreParseNoVariableResolution
+ : &RuntimeCallStats::PreParseBackgroundNoVariableResolution;
+ }
+ RuntimeCallStats::CorrectCurrentCounterId(runtime_call_stats_,
+ counter_id);
}
}
@@ -2779,6 +2811,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
function_name, scope, body, expected_property_count, num_parameters,
function_length, duplicate_parameters, function_type, eager_compile_hint,
pos, true, function_literal_id);
+ if (should_use_parse_task) {
+ literals_to_stitch_.emplace_back(function_literal);
+ }
function_literal->set_function_token_position(function_token_pos);
if (should_be_used_once_hint)
function_literal->set_should_be_used_once_hint();
@@ -2790,9 +2825,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
return function_literal;
}
-Parser::LazyParsingResult Parser::SkipFunction(
- FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
- int* function_length, bool is_inner_function, bool may_abort, bool* ok) {
+Parser::LazyParsingResult Parser::SkipFunction(FunctionKind kind,
+ DeclarationScope* function_scope,
+ int* num_parameters,
+ bool is_inner_function,
+ bool may_abort, bool* ok) {
+ FunctionState function_state(&function_state_, &scope_, function_scope);
+
DCHECK_NE(kNoSourcePosition, function_scope->start_position());
DCHECK_EQ(kNoSourcePosition, parameters_end_pos_);
if (produce_cached_parse_data()) CHECK(log_);
@@ -2817,52 +2856,21 @@ Parser::LazyParsingResult Parser::SkipFunction(
scanner()->SeekForward(entry.end_pos() - 1);
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
*num_parameters = entry.num_parameters();
- *function_length = entry.function_length();
SetLanguageMode(function_scope, entry.language_mode());
if (entry.uses_super_property())
function_scope->RecordSuperPropertyUsage();
- if (entry.calls_eval()) function_scope->RecordEvalCall();
SkipFunctionLiterals(entry.num_inner_functions());
return kLazyParsingComplete;
}
cached_parse_data_->Reject();
}
- if (FLAG_use_parse_tasks && !is_inner_function &&
- reusable_preparser()->preparse_data()) {
- // All top-level functions are already preparsed and parser tasks for eager
- // functions are already created. Use data gathered during the preparse step
- // to skip the function.
- PreParseData::FunctionData data =
- reusable_preparser()->preparse_data()->GetFunctionData(
- function_scope->start_position());
- if (data.is_valid()) {
- if (FLAG_trace_parse_tasks) {
- PrintF("Skipping top level func @ %d : %d using preparse data\n",
- function_scope->start_position(), data.end);
- }
- function_scope->set_end_position(data.end);
- scanner()->SeekForward(data.end - 1);
- Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
- *num_parameters = data.num_parameters;
- *function_length = data.function_length;
- SetLanguageMode(function_scope, data.language_mode);
- if (data.uses_super_property) {
- function_scope->RecordSuperPropertyUsage();
- }
- if (data.calls_eval) {
- function_scope->RecordEvalCall();
- }
- SkipFunctionLiterals(data.num_inner_functions);
- return kLazyParsingComplete;
- }
- }
-
// FIXME(marja): There are 3 ways to skip functions now. Unify them.
if (preparsed_scope_data_->Consuming()) {
- DCHECK(FLAG_preparser_scope_analysis);
+ DCHECK(FLAG_experimental_preparser_scope_analysis);
const PreParseData::FunctionData& data =
- preparsed_scope_data_->FindFunction(function_scope->start_position());
+ preparsed_scope_data_->FindSkippableFunction(
+ function_scope->start_position());
if (data.is_valid()) {
function_scope->set_is_skipped_function(true);
function_scope->outer_scope()->SetMustUsePreParsedScopeData();
@@ -2871,14 +2879,10 @@ Parser::LazyParsingResult Parser::SkipFunction(
scanner()->SeekForward(data.end - 1);
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
*num_parameters = data.num_parameters;
- *function_length = data.function_length;
SetLanguageMode(function_scope, data.language_mode);
if (data.uses_super_property) {
function_scope->RecordSuperPropertyUsage();
}
- if (data.calls_eval) {
- function_scope->RecordEvalCall();
- }
SkipFunctionLiterals(data.num_inner_functions);
return kLazyParsingComplete;
}
@@ -2914,15 +2918,13 @@ Parser::LazyParsingResult Parser::SkipFunction(
total_preparse_skipped_ +=
function_scope->end_position() - function_scope->start_position();
*num_parameters = logger->num_parameters();
- *function_length = logger->function_length();
SkipFunctionLiterals(logger->num_inner_functions());
if (!is_inner_function && produce_cached_parse_data()) {
DCHECK(log_);
- log_->LogFunction(
- function_scope->start_position(), function_scope->end_position(),
- *num_parameters, *function_length, language_mode(),
- function_scope->uses_super_property(), function_scope->calls_eval(),
- logger->num_inner_functions());
+ log_->LogFunction(function_scope->start_position(),
+ function_scope->end_position(), *num_parameters,
+ language_mode(), function_scope->uses_super_property(),
+ logger->num_inner_functions());
}
return kLazyParsingComplete;
}
@@ -3128,22 +3130,6 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
return result;
}
-Assignment* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
- // .generator = %CreateJSGeneratorObject(...);
- DCHECK_NOT_NULL(function_state_->generator_object_variable());
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(factory()->NewThisFunction(pos), zone());
- args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
- : ThisExpression(kNoSourcePosition),
- zone());
- Expression* allocation =
- factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args, pos);
- VariableProxy* proxy =
- factory()->NewVariableProxy(function_state_->generator_object_variable());
- return factory()->NewAssignment(Token::INIT, proxy, allocation,
- kNoSourcePosition);
-}
-
Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
// %ResolvePromise(.promise, value), .promise
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
@@ -3193,13 +3179,17 @@ Variable* Parser::AsyncGeneratorAwaitVariable() {
}
Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
- Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
- VariableProxy* generator =
+ // We access the generator object twice: once for the {generator}
+ // member of the Suspend AST node, and once for the result of
+ // the initial yield.
+ Expression* yield_result =
+ factory()->NewVariableProxy(function_state_->generator_object_variable());
+ Expression* generator_object =
factory()->NewVariableProxy(function_state_->generator_object_variable());
// The position of the yield is important for reporting the exception
// caused by calling the .throw method on a generator suspended at the
// initial yield (i.e. right after generator instantiation).
- return BuildSuspend(generator, assignment, scope()->start_position(),
+ return BuildSuspend(generator_object, yield_result, scope()->start_position(),
Suspend::kOnExceptionThrow, SuspendFlags::kYield);
}
@@ -3317,7 +3307,7 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
class_info->properties->Add(property, zone());
}
-// This method rewrites a class literal into a do-expression.
+// This method generates a ClassLiteral AST node.
// It uses the following fields of class_info:
// - constructor (if missing, it updates it with a default constructor)
// - proxy
@@ -3325,13 +3315,13 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
// - properties
// - has_name_static_property
// - has_static_computed_names
-Expression* Parser::RewriteClassLiteral(const AstRawString* name,
+Expression* Parser::RewriteClassLiteral(Scope* block_scope,
+ const AstRawString* name,
ClassInfo* class_info, int pos,
- bool* ok) {
- int end_pos = scanner()->location().end_pos;
- Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
- Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
- DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
+ int end_pos, bool* ok) {
+ DCHECK_NOT_NULL(block_scope);
+ DCHECK_EQ(block_scope->scope_type(), BLOCK_SCOPE);
+ DCHECK_EQ(block_scope->language_mode(), STRICT);
bool has_extends = class_info->extends != nullptr;
bool has_default_constructor = class_info->constructor == nullptr;
@@ -3340,31 +3330,20 @@ Expression* Parser::RewriteClassLiteral(const AstRawString* name,
DefaultConstructor(name, has_extends, pos, end_pos);
}
- scope()->set_end_position(end_pos);
-
if (name != nullptr) {
DCHECK_NOT_NULL(class_info->proxy);
class_info->proxy->var()->set_initializer_position(end_pos);
}
ClassLiteral* class_literal = factory()->NewClassLiteral(
- class_info->proxy, class_info->extends, class_info->constructor,
- class_info->properties, pos, end_pos,
+ block_scope, class_info->proxy, class_info->extends,
+ class_info->constructor, class_info->properties, pos, end_pos,
class_info->has_name_static_property,
- class_info->has_static_computed_names);
+ class_info->has_static_computed_names, class_info->is_anonymous);
- do_block->statements()->Add(
- factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::ASSIGN,
- factory()->NewVariableProxy(result_var),
- class_literal, kNoSourcePosition),
- pos),
- zone());
- do_block->set_scope(scope()->FinalizeBlockScope());
- do_expr->set_represented_function(class_info->constructor);
AddFunctionForNameInference(class_info->constructor);
- return do_expr;
+ return class_literal;
}
Literal* Parser::GetLiteralUndefined(int position) {
@@ -3503,13 +3482,6 @@ void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {
}
isolate->counters()->total_preparse_skipped()->Increment(
total_preparse_skipped_);
- if (!parsing_on_main_thread_ &&
- FLAG_runtime_stats ==
- v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) {
- // Copy over the counters from the background thread to the main counters on
- // the isolate.
- isolate->counters()->runtime_call_stats()->Add(runtime_call_stats_);
- }
}
void Parser::ParseOnBackground(ParseInfo* info) {
@@ -3526,10 +3498,6 @@ void Parser::ParseOnBackground(ParseInfo* info) {
compile_options_ = ScriptCompiler::kNoCompileOptions;
}
}
- if (FLAG_runtime_stats) {
- // Create separate runtime stats for background parsing.
- runtime_call_stats_ = new (zone()) RuntimeCallStats();
- }
std::unique_ptr<Utf16CharacterStream> stream;
Utf16CharacterStream* stream_ptr;
@@ -3543,7 +3511,7 @@ void Parser::ParseOnBackground(ParseInfo* info) {
runtime_call_stats_));
stream_ptr = stream.get();
}
- scanner_.Initialize(stream_ptr);
+ scanner_.Initialize(stream_ptr, info->is_module());
DCHECK(info->maybe_outer_scope_info().is_null());
DCHECK(original_scope_);
@@ -3558,12 +3526,7 @@ void Parser::ParseOnBackground(ParseInfo* info) {
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
result = DoParseProgram(info);
} else {
- const AstRawString* function_name = info->function_name();
- if (!function_name) {
- // FIXME(wiktorg) solve fni in parse tasks
- function_name = ast_value_factory()->empty_string();
- }
- result = DoParseFunction(info, function_name);
+ result = DoParseFunction(info);
}
info->set_literal(result);
@@ -3887,9 +3850,6 @@ void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
if (function_state_->generator_object_variable() == nullptr) {
PrepareGeneratorVariables();
}
- body->Add(factory()->NewExpressionStatement(
- BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition),
- zone());
}
// This method completes the desugaring of the body of async_function.
@@ -4251,7 +4211,7 @@ void Parser::SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
// Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
// of an object literal.
- if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
+ if (property->IsPrototype()) return;
Expression* value = property->value();
@@ -4270,12 +4230,11 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
DCHECK_NOT_NULL(name);
if (!value->IsAnonymousFunctionDefinition()) return;
auto function = value->AsFunctionLiteral();
+ if (value->IsClassLiteral()) {
+ function = value->AsClassLiteral()->constructor();
+ }
if (function != nullptr) {
function->set_raw_name(ast_value_factory()->NewConsString(name));
- } else {
- DCHECK(value->IsDoExpression());
- value->AsDoExpression()->represented_function()->set_raw_name(
- ast_value_factory()->NewConsString(name));
}
}
@@ -4704,10 +4663,26 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
// while (true) { ... }
// Already defined earlier: WhileStatement* loop = ...
{
- Block* loop_body = factory()->NewBlock(nullptr, 4, false, nopos);
+ Block* loop_body = factory()->NewBlock(nullptr, 5, false, nopos);
loop_body->statements()->Add(switch_mode, zone());
loop_body->statements()->Add(if_done, zone());
loop_body->statements()->Add(set_mode_return, zone());
+
+ if (is_async_generator()) {
+ // AsyncGeneratorYield does not yield the original iterator result,
+ // unlike sync generators. Do `output = output.value`
+ VariableProxy* output_proxy = factory()->NewVariableProxy(var_output);
+ Expression* literal = factory()->NewStringLiteral(
+ ast_value_factory()->value_string(), nopos);
+ Assignment* assign = factory()->NewAssignment(
+ Token::ASSIGN, output_proxy,
+ factory()->NewProperty(factory()->NewVariableProxy(var_output),
+ literal, nopos),
+ nopos);
+ loop_body->statements()->Add(
+ factory()->NewExpressionStatement(assign, nopos), zone());
+ }
+
loop_body->statements()->Add(try_finally, zone());
loop->Initialize(factory()->NewBooleanLiteral(true, nopos), loop_body);
@@ -5191,6 +5166,41 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
return final_loop;
}
+void Parser::StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate) {
+ if (literals_to_stitch_.empty()) return;
+ std::map<int, ParseInfo*> child_infos = top_level_parse_info->child_infos();
+ DCHECK(std::is_sorted(literals_to_stitch_.begin(), literals_to_stitch_.end(),
+ [](FunctionLiteral* a, FunctionLiteral* b) {
+ return a->start_position() < b->start_position();
+ }));
+ auto it = literals_to_stitch_.begin();
+ for (auto& child_info : child_infos) {
+ ParseInfo* result = child_info.second;
+ // If the parse task failed the function will be treated as lazy function
+ // and reparsed before it gets called
+ if (!result) continue;
+ result->UpdateStatisticsAfterBackgroundParse(isolate);
+ if (!result->literal()) continue;
+ while ((*it)->start_position() != child_info.first) {
+ if (++it == literals_to_stitch_.end()) {
+ return;
+ }
+ }
+ FunctionLiteral* literal = *it;
+ // FIXME(wiktorg) better handling of default params for arrow functions
+ Scope* outer_scope = literal->scope()->outer_scope();
+ if (outer_scope->is_declaration_scope() &&
+ outer_scope->AsDeclarationScope()->was_lazily_parsed()) {
+ continue;
+ }
+ // TODO(wiktorg) in the future internalize somewhere else (stitching may be
+ // done on streamer thread)
+ result->ast_value_factory()->Internalize(isolate);
+ literal->ReplaceBodyAndScope(result->literal());
+ literal->SetShouldEagerCompile();
+ }
+}
+
#undef CHECK_OK
#undef CHECK_OK_VOID
#undef CHECK_FAILED
diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h
index 8a970608e7..c51c0eff01 100644
--- a/deps/v8/src/parsing/parser.h
+++ b/deps/v8/src/parsing/parser.h
@@ -35,7 +35,6 @@ class FunctionEntry BASE_EMBEDDED {
kStartPositionIndex,
kEndPositionIndex,
kNumParametersIndex,
- kFunctionLengthIndex,
kFlagsIndex,
kNumInnerFunctionsIndex,
kSize
@@ -49,29 +48,22 @@ class FunctionEntry BASE_EMBEDDED {
class LanguageModeField : public BitField<LanguageMode, 0, 1> {};
class UsesSuperPropertyField
: public BitField<bool, LanguageModeField::kNext, 1> {};
- class CallsEvalField
- : public BitField<bool, UsesSuperPropertyField::kNext, 1> {};
static uint32_t EncodeFlags(LanguageMode language_mode,
- bool uses_super_property, bool calls_eval) {
+ bool uses_super_property) {
return LanguageModeField::encode(language_mode) |
- UsesSuperPropertyField::encode(uses_super_property) |
- CallsEvalField::encode(calls_eval);
+ UsesSuperPropertyField::encode(uses_super_property);
}
int start_pos() const { return backing_[kStartPositionIndex]; }
int end_pos() const { return backing_[kEndPositionIndex]; }
int num_parameters() const { return backing_[kNumParametersIndex]; }
- int function_length() const { return backing_[kFunctionLengthIndex]; }
LanguageMode language_mode() const {
return LanguageModeField::decode(backing_[kFlagsIndex]);
}
bool uses_super_property() const {
return UsesSuperPropertyField::decode(backing_[kFlagsIndex]);
}
- bool calls_eval() const {
- return CallsEvalField::decode(backing_[kFlagsIndex]);
- }
int num_inner_functions() const { return backing_[kNumInnerFunctionsIndex]; }
bool is_valid() const { return !backing_.is_empty(); }
@@ -274,14 +266,15 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
FunctionLiteral* ParseProgram(Isolate* isolate, ParseInfo* info);
FunctionLiteral* ParseFunction(Isolate* isolate, ParseInfo* info);
- FunctionLiteral* DoParseFunction(ParseInfo* info,
- const AstRawString* raw_name);
+ FunctionLiteral* DoParseFunction(ParseInfo* info);
// Called by ParseProgram after setting up the scanner.
FunctionLiteral* DoParseProgram(ParseInfo* info);
void SetCachedData(ParseInfo* info);
+ void StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate);
+
ScriptCompiler::CompileOptions compile_options() const {
return compile_options_;
}
@@ -297,7 +290,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
reusable_preparser_ =
new PreParser(zone(), &scanner_, stack_limit_, ast_value_factory(),
&pending_error_handler_, runtime_call_stats_,
- parsing_on_main_thread_);
+ preparsed_scope_data_, parsing_on_main_thread_);
#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
SET_ALLOW(natives);
SET_ALLOW(tailcalls);
@@ -380,9 +373,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
ClassInfo* class_info, bool* ok);
- V8_INLINE Expression* RewriteClassLiteral(const AstRawString* name,
+ V8_INLINE Expression* RewriteClassLiteral(Scope* block_scope,
+ const AstRawString* name,
ClassInfo* class_info, int pos,
- bool* ok);
+ int end_pos, bool* ok);
V8_INLINE Statement* DeclareNative(const AstRawString* name, int pos,
bool* ok);
@@ -561,9 +555,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// in order to force the function to be eagerly parsed, after all.
LazyParsingResult SkipFunction(FunctionKind kind,
DeclarationScope* function_scope,
- int* num_parameters, int* function_length,
- bool is_inner_function, bool may_abort,
- bool* ok);
+ int* num_parameters, bool is_inner_function,
+ bool may_abort, bool* ok);
Block* BuildParameterInitializationBlock(
const ParserFormalParameters& parameters, bool* ok);
@@ -733,7 +726,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
V8_INLINE static bool IsIdentifier(Expression* expression) {
DCHECK_NOT_NULL(expression);
VariableProxy* operand = expression->AsVariableProxy();
- return operand != nullptr && !operand->is_this();
+ return operand != nullptr && !operand->is_this() &&
+ !operand->is_new_target();
}
V8_INLINE static const AstRawString* AsIdentifier(Expression* expression) {
@@ -759,7 +753,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
V8_INLINE static bool IsBoilerplateProperty(
ObjectLiteral::Property* property) {
- return ObjectLiteral::IsBoilerplateProperty(property);
+ return !property->IsPrototype();
}
V8_INLINE bool IsNative(Expression* expr) const {
@@ -1161,6 +1155,11 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
PreParser* reusable_preparser_;
Mode mode_;
+ std::vector<FunctionLiteral*> literals_to_stitch_;
+ Handle<String> source_;
+ CompilerDispatcher* compiler_dispatcher_ = nullptr;
+ ParseInfo* main_parse_info_ = nullptr;
+
friend class ParserTarget;
friend class ParserTargetScope;
ParserTarget* target_stack_; // for break, continue statements
@@ -1178,8 +1177,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
bool temp_zoned_;
ParserLogger* log_;
- PreParsedScopeData* preparsed_scope_data_;
-
// If not kNoSourcePosition, indicates that the first function literal
// encountered is a dynamic function, see CreateDynamicFunction(). This field
// indicates the correct position of the ')' that closes the parameter list.
diff --git a/deps/v8/src/parsing/preparse-data-format.h b/deps/v8/src/parsing/preparse-data-format.h
index e579c66af9..2f317ce75f 100644
--- a/deps/v8/src/parsing/preparse-data-format.h
+++ b/deps/v8/src/parsing/preparse-data-format.h
@@ -14,7 +14,7 @@ struct PreparseDataConstants {
public:
// Layout and constants of the preparse data exchange format.
static const unsigned kMagicNumber = 0xBadDead;
- static const unsigned kCurrentVersion = 16;
+ static const unsigned kCurrentVersion = 17;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
diff --git a/deps/v8/src/parsing/preparse-data.cc b/deps/v8/src/parsing/preparse-data.cc
index e9f98b7356..f11eb7b21e 100644
--- a/deps/v8/src/parsing/preparse-data.cc
+++ b/deps/v8/src/parsing/preparse-data.cc
@@ -14,15 +14,14 @@ namespace v8 {
namespace internal {
void ParserLogger::LogFunction(int start, int end, int num_parameters,
- int function_length, LanguageMode language_mode,
- bool uses_super_property, bool calls_eval,
+ LanguageMode language_mode,
+ bool uses_super_property,
int num_inner_functions) {
function_store_.Add(start);
function_store_.Add(end);
function_store_.Add(num_parameters);
- function_store_.Add(function_length);
- function_store_.Add(FunctionEntry::EncodeFlags(
- language_mode, uses_super_property, calls_eval));
+ function_store_.Add(
+ FunctionEntry::EncodeFlags(language_mode, uses_super_property));
function_store_.Add(num_inner_functions);
}
diff --git a/deps/v8/src/parsing/preparse-data.h b/deps/v8/src/parsing/preparse-data.h
index 954d89ef7e..b5db652c9c 100644
--- a/deps/v8/src/parsing/preparse-data.h
+++ b/deps/v8/src/parsing/preparse-data.h
@@ -53,14 +53,11 @@ class PreParserLogger final {
PreParserLogger()
: end_(-1),
num_parameters_(-1),
- function_length_(-1),
num_inner_functions_(-1) {}
- void LogFunction(int end, int num_parameters, int function_length,
- int num_inner_functions) {
+ void LogFunction(int end, int num_parameters, int num_inner_functions) {
end_ = end;
num_parameters_ = num_parameters;
- function_length_ = function_length;
num_inner_functions_ = num_inner_functions;
}
@@ -68,16 +65,12 @@ class PreParserLogger final {
int num_parameters() const {
return num_parameters_;
}
- int function_length() const {
- return function_length_;
- }
int num_inner_functions() const { return num_inner_functions_; }
private:
int end_;
// For function entries.
int num_parameters_;
- int function_length_;
int num_inner_functions_;
};
@@ -85,9 +78,9 @@ class ParserLogger final {
public:
ParserLogger();
- void LogFunction(int start, int end, int num_parameters, int function_length,
+ void LogFunction(int start, int end, int num_parameters,
LanguageMode language_mode, bool uses_super_property,
- bool calls_eval, int num_inner_functions);
+ int num_inner_functions);
ScriptData* GetScriptData();
@@ -105,26 +98,24 @@ class PreParseData final {
struct FunctionData {
int end;
int num_parameters;
- int function_length;
int num_inner_functions;
LanguageMode language_mode;
bool uses_super_property : 1;
- bool calls_eval : 1;
- FunctionData() : end(-1) {}
+ FunctionData() : end(kNoSourcePosition) {}
- FunctionData(int end, int num_parameters, int function_length,
- int num_inner_functions, LanguageMode language_mode,
- bool uses_super_property, bool calls_eval)
+ FunctionData(int end, int num_parameters, int num_inner_functions,
+ LanguageMode language_mode, bool uses_super_property)
: end(end),
num_parameters(num_parameters),
- function_length(function_length),
num_inner_functions(num_inner_functions),
language_mode(language_mode),
- uses_super_property(uses_super_property),
- calls_eval(calls_eval) {}
+ uses_super_property(uses_super_property) {}
- bool is_valid() const { return end > 0; }
+ bool is_valid() const {
+ DCHECK_IMPLIES(end < 0, end == kNoSourcePosition);
+ return end != kNoSourcePosition;
+ }
};
FunctionData GetFunctionData(int start) const;
diff --git a/deps/v8/src/parsing/preparsed-scope-data.cc b/deps/v8/src/parsing/preparsed-scope-data.cc
index c8deb06bc7..c8ea3de22a 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.cc
+++ b/deps/v8/src/parsing/preparsed-scope-data.cc
@@ -20,7 +20,7 @@ class VariableMaybeAssignedField
class VariableContextAllocatedField
: public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {};
-const int kFunctionDataSize = 9;
+const int kFunctionDataSize = 8;
} // namespace
@@ -51,21 +51,20 @@ const int kFunctionDataSize = 9;
void PreParsedScopeData::SaveData(Scope* scope) {
DCHECK(!has_data_);
+ DCHECK_NE(scope->end_position(), kNoSourcePosition);
- if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
+ // We're not trying to save data for default constructors because the
+ // PreParser doesn't construct them.
+ DCHECK_IMPLIES(scope->scope_type() == ScopeType::FUNCTION_SCOPE,
+ (scope->AsDeclarationScope()->function_kind() &
+ kDefaultConstructor) == 0);
+
+ if (scope->scope_type() == ScopeType::FUNCTION_SCOPE &&
+ !scope->AsDeclarationScope()->is_arrow_scope()) {
// This cast is OK since we're not going to have more than 2^32 elements in
// the data. FIXME(marja): Implement limits for the data size.
function_data_positions_[scope->start_position()] =
static_cast<uint32_t>(backing_store_.size());
- // FIXME(marja): Fill in the missing fields: function_length +
- // num_inner_functions.
- function_index_.AddFunctionData(
- scope->start_position(),
- PreParseData::FunctionData(
- scope->end_position(), scope->num_parameters(), -1, -1,
- scope->language_mode(),
- scope->AsDeclarationScope()->uses_super_property(),
- scope->calls_eval()));
}
if (!ScopeNeedsData(scope)) {
@@ -80,7 +79,7 @@ void PreParsedScopeData::SaveData(Scope* scope) {
// index is needed for skipping over data for a function scope when we skip
// parsing of the corresponding function.
size_t data_end_index = backing_store_.size();
- backing_store_.push_back(-1);
+ backing_store_.push_back(0);
if (!scope->is_hidden()) {
for (Variable* var : *scope->locals()) {
@@ -92,11 +91,24 @@ void PreParsedScopeData::SaveData(Scope* scope) {
SaveDataForInnerScopes(scope);
- backing_store_[data_end_index] = backing_store_.size();
+ // FIXME(marja): see above.
+ backing_store_[data_end_index] = static_cast<uint32_t>(backing_store_.size());
+}
+
+void PreParsedScopeData::AddSkippableFunction(
+ int start_position, const PreParseData::FunctionData& function_data) {
+ AddFunction(start_position, function_data);
+ skippable_functions_.insert(start_position);
+}
+
+void PreParsedScopeData::AddFunction(
+ int start_position, const PreParseData::FunctionData& function_data) {
+ DCHECK(function_data.is_valid());
+ function_index_.AddFunctionData(start_position, function_data);
}
void PreParsedScopeData::RestoreData(DeclarationScope* scope) const {
- int index = -1;
+ uint32_t index = 0;
DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
@@ -107,7 +119,7 @@ void PreParsedScopeData::RestoreData(DeclarationScope* scope) const {
RestoreData(scope, &index);
}
-void PreParsedScopeData::RestoreData(Scope* scope, int* index_ptr) const {
+void PreParsedScopeData::RestoreData(Scope* scope, uint32_t* index_ptr) const {
// It's possible that scope is not present in the data at all (since PreParser
// doesn't create the corresponding scope). In this case, the Scope won't
// contain any variables for which we need the data.
@@ -115,22 +127,21 @@ void PreParsedScopeData::RestoreData(Scope* scope, int* index_ptr) const {
return;
}
- int& index = *index_ptr;
+ uint32_t& index = *index_ptr;
#ifdef DEBUG
// Data integrity check.
- if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
- // FIXME(marja): Compare the missing fields too (function length,
- // num_inner_functions).
+ if (scope->scope_type() == ScopeType::FUNCTION_SCOPE &&
+ !scope->AsDeclarationScope()->is_arrow_scope()) {
const PreParseData::FunctionData& data =
- FindFunction(scope->start_position());
+ function_index_.GetFunctionData(scope->start_position());
+ DCHECK(data.is_valid());
DCHECK_EQ(data.end, scope->end_position());
// FIXME(marja): unify num_parameters too and DCHECK here.
DCHECK_EQ(data.language_mode, scope->language_mode());
DCHECK_EQ(data.uses_super_property,
scope->AsDeclarationScope()->uses_super_property());
- DCHECK_EQ(data.calls_eval, scope->calls_eval());
- int index_from_data = -1;
+ uint32_t index_from_data = 0;
FindFunctionData(scope->start_position(), &index_from_data);
DCHECK_EQ(index_from_data, index);
}
@@ -140,16 +151,19 @@ void PreParsedScopeData::RestoreData(Scope* scope, int* index_ptr) const {
// This scope is a function scope representing a function we want to
// skip. So just skip over its data.
DCHECK(!scope->must_use_preparsed_scope_data());
+ // Check that we're moving forward (not backward) in the data.
+ DCHECK_GT(backing_store_[index + 2], index);
index = backing_store_[index + 2];
return;
}
+ DCHECK_GE(backing_store_.size(), index + 3);
DCHECK_EQ(backing_store_[index++], scope->scope_type());
if (backing_store_[index++]) {
scope->RecordEvalCall();
}
- int data_end_index = backing_store_[index++];
+ uint32_t data_end_index = backing_store_[index++];
USE(data_end_index);
if (!scope->is_hidden()) {
@@ -165,13 +179,14 @@ void PreParsedScopeData::RestoreData(Scope* scope, int* index_ptr) const {
DCHECK_EQ(data_end_index, index);
}
-FixedUint32Array* PreParsedScopeData::Serialize(Isolate* isolate) const {
+Handle<PodArray<uint32_t>> PreParsedScopeData::Serialize(
+ Isolate* isolate) const {
// FIXME(marja): save space by using a byte array and converting
// function_index_ to bytes.
- Handle<JSTypedArray> js_array = isolate->factory()->NewJSTypedArray(
- UINT32_ELEMENTS,
- function_index_.size() * kFunctionDataSize + backing_store_.size() + 1);
- FixedUint32Array* array = FixedUint32Array::cast(js_array->elements());
+ size_t length =
+ function_index_.size() * kFunctionDataSize + backing_store_.size() + 1;
+ Handle<PodArray<uint32_t>> array =
+ PodArray<uint32_t>::New(isolate, static_cast<int>(length), TENURED);
array->set(0, static_cast<uint32_t>(function_index_.size()));
int i = 1;
@@ -183,51 +198,56 @@ FixedUint32Array* PreParsedScopeData::Serialize(Isolate* isolate) const {
array->set(i++, it->second); // position in data
array->set(i++, function_data.end);
array->set(i++, function_data.num_parameters);
- array->set(i++, function_data.function_length);
array->set(i++, function_data.num_inner_functions);
array->set(i++, function_data.language_mode);
array->set(i++, function_data.uses_super_property);
- array->set(i++, function_data.calls_eval);
+ array->set(i++, skippable_functions_.find(item.first) !=
+ skippable_functions_.end());
}
for (size_t j = 0; j < backing_store_.size(); ++j) {
array->set(i++, static_cast<uint32_t>(backing_store_[j]));
}
+ DCHECK_EQ(array->length(), length);
return array;
}
-void PreParsedScopeData::Deserialize(Handle<FixedUint32Array> array) {
+void PreParsedScopeData::Deserialize(PodArray<uint32_t>* array) {
has_data_ = true;
- DCHECK(!array.is_null());
+ DCHECK_NOT_NULL(array);
if (array->length() == 0) {
return;
}
- int function_count = array->get_scalar(0);
+ int function_count = array->get(0);
CHECK(array->length() > function_count * kFunctionDataSize);
if (function_count == 0) {
return;
}
int i = 1;
for (; i < function_count * kFunctionDataSize + 1; i += kFunctionDataSize) {
- int start = array->get_scalar(i);
- function_data_positions_[start] = array->get_scalar(i + 1);
+ int start = array->get(i);
+ function_data_positions_[start] = array->get(i + 1);
function_index_.AddFunctionData(
start, PreParseData::FunctionData(
- array->get_scalar(i + 2), array->get_scalar(i + 3),
- array->get_scalar(i + 4), array->get_scalar(i + 5),
- LanguageMode(array->get_scalar(i + 6)),
- array->get_scalar(i + 7), array->get_scalar(i + 8)));
+ array->get(i + 2), array->get(i + 3), array->get(i + 4),
+ LanguageMode(array->get(i + 5)), array->get(i + 6)));
+ if (array->get(i + 7)) {
+ skippable_functions_.insert(start);
+ }
}
CHECK_EQ(function_index_.size(), function_count);
backing_store_.reserve(array->length() - i);
for (; i < array->length(); ++i) {
- backing_store_.push_back(array->get_scalar(i));
+ backing_store_.push_back(array->get(i));
}
}
-PreParseData::FunctionData PreParsedScopeData::FindFunction(
+PreParseData::FunctionData PreParsedScopeData::FindSkippableFunction(
int start_pos) const {
+ if (skippable_functions_.find(start_pos) == skippable_functions_.end()) {
+ return PreParseData::FunctionData();
+ }
return function_index_.GetFunctionData(start_pos);
}
@@ -252,15 +272,17 @@ void PreParsedScopeData::SaveDataForVariable(Variable* var) {
}
void PreParsedScopeData::RestoreDataForVariable(Variable* var,
- int* index_ptr) const {
- int& index = *index_ptr;
+ uint32_t* index_ptr) const {
+ uint32_t& index = *index_ptr;
#ifdef DEBUG
const AstRawString* name = var->raw_name();
- DCHECK_EQ(backing_store_[index++], name->length());
+ DCHECK_GT(backing_store_.size(), index + name->length());
+ DCHECK_EQ(backing_store_[index++], static_cast<uint32_t>(name->length()));
for (int i = 0; i < name->length(); ++i) {
DCHECK_EQ(backing_store_[index++], name->raw_data()[i]);
}
#endif
+ DCHECK_GT(backing_store_.size(), index);
byte variable_data = backing_store_[index++];
if (VariableIsUsedField::decode(variable_data)) {
var->set_is_used();
@@ -288,7 +310,7 @@ void PreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
}
void PreParsedScopeData::RestoreDataForInnerScopes(Scope* scope,
- int* index_ptr) const {
+ uint32_t* index_ptr) const {
std::vector<Scope*> scopes;
for (Scope* inner = scope->inner_scope(); inner != nullptr;
inner = inner->sibling()) {
@@ -299,7 +321,8 @@ void PreParsedScopeData::RestoreDataForInnerScopes(Scope* scope,
}
}
-bool PreParsedScopeData::FindFunctionData(int start_pos, int* index) const {
+bool PreParsedScopeData::FindFunctionData(int start_pos,
+ uint32_t* index) const {
auto it = function_data_positions_.find(start_pos);
if (it == function_data_positions_.end()) {
return false;
@@ -310,7 +333,9 @@ bool PreParsedScopeData::FindFunctionData(int start_pos, int* index) const {
bool PreParsedScopeData::ScopeNeedsData(Scope* scope) {
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
- return true;
+ // Default constructors don't need data (they cannot contain inner functions
+ // defined by the user). Other functions do.
+ return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
}
if (!scope->is_hidden()) {
for (Variable* var : *scope->locals()) {
diff --git a/deps/v8/src/parsing/preparsed-scope-data.h b/deps/v8/src/parsing/preparsed-scope-data.h
index fb8acab696..5d4fc3a3a0 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.h
+++ b/deps/v8/src/parsing/preparsed-scope-data.h
@@ -5,6 +5,7 @@
#ifndef V8_PARSING_PREPARSED_SCOPE_DATA_H_
#define V8_PARSING_PREPARSED_SCOPE_DATA_H_
+#include <set>
#include <unordered_map>
#include <vector>
@@ -65,40 +66,60 @@ class PreParsedScopeData {
// subscopes') variables.
void SaveData(Scope* scope);
+ // Save data for a function we might skip later. The data is used later for
+ // creating a FunctionLiteral.
+ void AddSkippableFunction(int start_position,
+ const PreParseData::FunctionData& function_data);
+
+ // Save variable allocation data for function which contains skippable
+ // functions.
+ void AddFunction(int start_position,
+ const PreParseData::FunctionData& function_data);
+
+ // FIXME(marja): We need different kinds of data for the two types of
+ // functions. For a skippable function we need the end position + the data
+ // needed for creating a FunctionLiteral. For a function which contains
+ // skippable functions, we need the data affecting context allocation status
+ // of the variables (but e.g., no end position). Currently we just save the
+ // same data for both. Here we can save less data.
+
// Restores the information needed for allocating the Scopes's (and its
// subscopes') variables.
- void RestoreData(Scope* scope, int* index_ptr) const;
+ void RestoreData(Scope* scope, uint32_t* index_ptr) const;
void RestoreData(DeclarationScope* scope) const;
- FixedUint32Array* Serialize(Isolate* isolate) const;
- void Deserialize(Handle<FixedUint32Array> array);
+ Handle<PodArray<uint32_t>> Serialize(Isolate* isolate) const;
+ void Deserialize(PodArray<uint32_t>* array);
bool Consuming() const { return has_data_; }
bool Producing() const { return !has_data_; }
- PreParseData::FunctionData FindFunction(int start_pos) const;
+ PreParseData::FunctionData FindSkippableFunction(int start_pos) const;
private:
friend class ScopeTestHelper;
void SaveDataForVariable(Variable* var);
- void RestoreDataForVariable(Variable* var, int* index_ptr) const;
+ void RestoreDataForVariable(Variable* var, uint32_t* index_ptr) const;
void SaveDataForInnerScopes(Scope* scope);
- void RestoreDataForInnerScopes(Scope* scope, int* index_ptr) const;
- bool FindFunctionData(int start_pos, int* index) const;
+ void RestoreDataForInnerScopes(Scope* scope, uint32_t* index_ptr) const;
+ bool FindFunctionData(int start_pos, uint32_t* index) const;
static bool ScopeNeedsData(Scope* scope);
static bool IsSkippedFunctionScope(Scope* scope);
// TODO(marja): Make the backing store more efficient once we know exactly
// what data is needed.
- std::vector<byte> backing_store_;
+ std::vector<uint32_t> backing_store_;
- // Start pos -> FunctionData.
+ // Start pos -> FunctionData. Used for creating FunctionLiterals for skipped
+ // functions (when they're actually skipped).
PreParseData function_index_;
// Start pos -> position in backing_store_.
std::unordered_map<uint32_t, uint32_t> function_data_positions_;
+ // Start positions of skippable functions.
+ std::set<uint32_t> skippable_functions_;
bool has_data_ = false;
diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc
index 95cf8caefd..c408af88c9 100644
--- a/deps/v8/src/parsing/preparser.cc
+++ b/deps/v8/src/parsing/preparser.cc
@@ -14,6 +14,7 @@
#include "src/parsing/parser-base.h"
#include "src/parsing/preparse-data-format.h"
#include "src/parsing/preparse-data.h"
+#include "src/parsing/preparsed-scope-data.h"
#include "src/parsing/preparser.h"
#include "src/unicode.h"
#include "src/utils.h"
@@ -100,10 +101,8 @@ PreParserIdentifier PreParser::GetSymbol() const {
return symbol;
}
-PreParser::PreParseResult PreParser::PreParseProgram(bool is_module,
- int* use_counts) {
+PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
DCHECK_NULL(scope_);
- use_counts_ = use_counts;
DeclarationScope* scope = NewScriptScope();
#ifdef DEBUG
scope->set_is_being_lazily_parsed(true);
@@ -122,7 +121,6 @@ PreParser::PreParseResult PreParser::PreParseProgram(bool is_module,
PreParserStatementList body;
ParseStatementList(body, Token::EOS, &ok);
original_scope_ = nullptr;
- use_counts_ = nullptr;
if (stack_overflow()) return kPreParseStackOverflow;
if (!ok) {
ReportUnexpectedToken(scanner()->current_token());
@@ -213,6 +211,18 @@ PreParser::PreParseResult PreParser::PreParseFunction(
// masks the arguments object. Declare arguments before declaring the
// function var since the arguments object masks 'function arguments'.
function_scope->DeclareArguments(ast_value_factory());
+
+ if (FLAG_experimental_preparser_scope_analysis &&
+ preparsed_scope_data_ != nullptr) {
+ // We're not going to skip this function, but it might contain skippable
+ // functions inside it.
+ preparsed_scope_data_->AddFunction(
+ scope()->start_position(),
+ PreParseData::FunctionData(
+ scanner()->peek_location().end_pos, scope()->num_parameters(),
+ GetLastFunctionLiteralId(), scope()->language_mode(),
+ scope()->AsDeclarationScope()->uses_super_property()));
+ }
}
use_counts_ = nullptr;
@@ -276,9 +286,6 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
runtime_call_stats_,
counters[track_unresolved_variables_][parsing_on_main_thread_]);
- bool is_top_level =
- scope()->AllowsLazyParsingWithoutUnresolvedVariables(original_scope_);
-
DeclarationScope* function_scope = NewFunctionScope(kind);
function_scope->SetLanguageMode(language_mode);
FunctionState function_state(&function_state_, &scope_, function_scope);
@@ -326,24 +333,15 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
- if (FLAG_use_parse_tasks && is_top_level && preparse_data_) {
- preparse_data_->AddFunctionData(
+ if (FLAG_experimental_preparser_scope_analysis &&
+ track_unresolved_variables_ && preparsed_scope_data_ != nullptr) {
+ preparsed_scope_data_->AddSkippableFunction(
start_position,
PreParseData::FunctionData(
- end_position, formals.num_parameters(), formals.function_length,
- GetLastFunctionLiteralId() - func_id, language_mode,
- function_scope->uses_super_property(),
- function_scope->calls_eval()));
- // TODO(wiktorg) spin-off a parse task
- if (FLAG_trace_parse_tasks) {
- PrintF("Saved function at %d to %d with:\n", start_position,
- end_position);
- PrintF("\t- %d params\n", formals.num_parameters());
- PrintF("\t- %d function length\n", formals.function_length);
- PrintF("\t- %d inner-funcs\n", GetLastFunctionLiteralId() - func_id);
- }
+ end_position, scope()->num_parameters(),
+ GetLastFunctionLiteralId() - func_id, scope()->language_mode(),
+ scope()->AsDeclarationScope()->uses_super_property()));
}
-
if (FLAG_trace_preparse) {
PrintF(" [%s]: %i-%i\n",
track_unresolved_variables_ ? "Preparse resolution"
@@ -366,7 +364,7 @@ PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction(
int body_end = scanner()->peek_location().end_pos;
DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
log_.LogFunction(body_end, formals->num_parameters(),
- formals->function_length, GetLastFunctionLiteralId());
+ GetLastFunctionLiteralId());
return kLazyParsingComplete;
}
@@ -374,13 +372,9 @@ PreParserExpression PreParser::ExpressionFromIdentifier(
PreParserIdentifier name, int start_position, InferName infer) {
VariableProxy* proxy = nullptr;
if (track_unresolved_variables_) {
- AstNodeFactory factory(ast_value_factory());
- // Setting the Zone is necessary because zone_ might be the temp Zone, and
- // AstValueFactory doesn't know about it.
- factory.set_zone(zone());
DCHECK_NOT_NULL(name.string_);
- proxy = scope()->NewUnresolved(&factory, name.string_, start_position,
- NORMAL_VARIABLE);
+ proxy = scope()->NewUnresolved(factory()->ast_node_factory(), name.string_,
+ start_position, NORMAL_VARIABLE);
}
return PreParserExpression::FromIdentifier(name, proxy, zone());
}
@@ -397,7 +391,7 @@ void PreParser::DeclareAndInitializeVariables(
declaration_descriptor->scope->RemoveUnresolved(variable);
Variable* var = scope()->DeclareVariableName(
variable->raw_name(), declaration_descriptor->mode);
- if (FLAG_preparser_scope_analysis) {
+ if (FLAG_experimental_preparser_scope_analysis) {
MarkLoopVariableAsAssigned(declaration_descriptor->scope, var);
// This is only necessary if there is an initializer, but we don't have
// that information here. Consequently, the preparser sometimes says
diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h
index 637efa2655..3bb85f0b20 100644
--- a/deps/v8/src/parsing/preparser.h
+++ b/deps/v8/src/parsing/preparser.h
@@ -178,6 +178,11 @@ class PreParserExpression {
variables);
}
+ static PreParserExpression NewTargetExpression() {
+ return PreParserExpression(TypeField::encode(kExpression) |
+ ExpressionTypeField::encode(kNewTarget));
+ }
+
static PreParserExpression ObjectLiteral(
ZoneList<VariableProxy*>* variables) {
return PreParserExpression(TypeField::encode(kObjectLiteralExpression),
@@ -358,7 +363,8 @@ class PreParserExpression {
kCallEvalExpression,
kSuperCallReference,
kNoTemplateTagExpression,
- kAssignment
+ kAssignment,
+ kNewTarget
};
explicit PreParserExpression(uint32_t expression_code,
@@ -387,7 +393,7 @@ class PreParserExpression {
// The rest of the bits are interpreted depending on the value
// of the Type field, so they can share the storage.
- typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField;
+ typedef BitField<ExpressionType, TypeField::kNext, 4> ExpressionTypeField;
typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseAsmField;
typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10>
@@ -538,11 +544,15 @@ class PreParserStatement {
class PreParserFactory {
public:
- explicit PreParserFactory(AstValueFactory* ast_value_factory)
- : ast_value_factory_(ast_value_factory),
- zone_(ast_value_factory->zone()) {}
+ explicit PreParserFactory(AstValueFactory* ast_value_factory, Zone* zone)
+ : ast_node_factory_(ast_value_factory, zone), zone_(zone) {}
+
+ void set_zone(Zone* zone) {
+ ast_node_factory_.set_zone(zone);
+ zone_ = zone;
+ }
- void set_zone(Zone* zone) { zone_ = zone; }
+ AstNodeFactory* ast_node_factory() { return &ast_node_factory_; }
PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
int pos) {
@@ -551,10 +561,8 @@ class PreParserFactory {
PreParserExpression expression = PreParserExpression::Default();
if (identifier.string_ != nullptr) {
DCHECK(FLAG_lazy_inner_functions);
- AstNodeFactory factory(ast_value_factory_);
- factory.set_zone(zone_);
- VariableProxy* variable =
- factory.NewVariableProxy(identifier.string_, NORMAL_VARIABLE);
+ VariableProxy* variable = ast_node_factory_.NewVariableProxy(
+ identifier.string_, NORMAL_VARIABLE);
expression.AddVariable(variable, zone_);
}
return expression;
@@ -789,7 +797,9 @@ class PreParserFactory {
}
private:
- AstValueFactory* ast_value_factory_;
+ // For creating VariableProxy objects (if
+ // PreParser::track_unresolved_variables_ is used).
+ AstNodeFactory ast_node_factory_;
Zone* zone_;
};
@@ -889,12 +899,12 @@ class PreParser : public ParserBase<PreParser> {
AstValueFactory* ast_value_factory,
PendingCompilationErrorHandler* pending_error_handler,
RuntimeCallStats* runtime_call_stats,
+ PreParsedScopeData* preparsed_scope_data = nullptr,
bool parsing_on_main_thread = true)
: ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
ast_value_factory, runtime_call_stats,
- parsing_on_main_thread),
+ preparsed_scope_data, parsing_on_main_thread),
use_counts_(nullptr),
- preparse_data_(FLAG_use_parse_tasks ? new PreParseData() : nullptr),
track_unresolved_variables_(false),
pending_error_handler_(pending_error_handler) {}
@@ -906,8 +916,7 @@ class PreParser : public ParserBase<PreParser> {
// success (even if parsing failed, the pre-parse data successfully
// captured the syntax error), and false if a stack-overflow happened
// during parsing.
- PreParseResult PreParseProgram(bool is_module = false,
- int* use_counts = nullptr);
+ PreParseResult PreParseProgram(bool is_module = false);
// Parses a single function literal, from the opening parentheses before
// parameters to the closing brace after the body.
@@ -923,8 +932,6 @@ class PreParser : public ParserBase<PreParser> {
bool track_unresolved_variables,
bool may_abort, int* use_counts);
- const PreParseData* preparse_data() const { return preparse_data_.get(); }
-
private:
// These types form an algebra over syntactic categories that is just
// rich enough to let us recognize and propagate the constructs that
@@ -941,9 +948,11 @@ class PreParser : public ParserBase<PreParser> {
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
bool parse_lazily() const { return false; }
- V8_INLINE LazyParsingResult SkipFunction(
- FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
- int* function_length, bool is_inner_function, bool may_abort, bool* ok) {
+ V8_INLINE LazyParsingResult SkipFunction(FunctionKind kind,
+ DeclarationScope* function_scope,
+ int* num_parameters,
+ bool is_inner_function,
+ bool may_abort, bool* ok) {
UNREACHABLE();
return kLazyParsingComplete;
}
@@ -1122,16 +1131,23 @@ class PreParser : public ParserBase<PreParser> {
}
V8_INLINE void DeclareClassVariable(PreParserIdentifier name,
ClassInfo* class_info,
- int class_token_pos, bool* ok) {}
+ int class_token_pos, bool* ok) {
+ if (name.string_ != nullptr) {
+ DCHECK(track_unresolved_variables_);
+ scope()->DeclareVariableName(name.string_, CONST);
+ }
+ }
V8_INLINE void DeclareClassProperty(PreParserIdentifier class_name,
PreParserExpression property,
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
ClassInfo* class_info, bool* ok) {
}
- V8_INLINE PreParserExpression RewriteClassLiteral(PreParserIdentifier name,
+ V8_INLINE PreParserExpression RewriteClassLiteral(Scope* scope,
+ PreParserIdentifier name,
ClassInfo* class_info,
- int pos, bool* ok) {
+ int pos, int end_pos,
+ bool* ok) {
bool has_default_constructor = !class_info->has_seen_constructor;
// Account for the default constructor.
if (has_default_constructor) GetNextFunctionLiteralId();
@@ -1494,12 +1510,9 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE PreParserExpression ThisExpression(int pos = kNoSourcePosition) {
ZoneList<VariableProxy*>* variables = nullptr;
if (track_unresolved_variables_) {
- AstNodeFactory factory(ast_value_factory());
- // Setting the Zone is necessary because zone_ might be the temp Zone, and
- // AstValueFactory doesn't know about it.
- factory.set_zone(zone());
VariableProxy* proxy = scope()->NewUnresolved(
- &factory, ast_value_factory()->this_string(), pos, THIS_VARIABLE);
+ factory()->ast_node_factory(), ast_value_factory()->this_string(),
+ pos, THIS_VARIABLE);
variables = new (zone()) ZoneList<VariableProxy*>(1, zone());
variables->Add(proxy, zone());
@@ -1508,15 +1521,34 @@ class PreParser : public ParserBase<PreParser> {
}
V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) {
+ if (track_unresolved_variables_) {
+ scope()->NewUnresolved(factory()->ast_node_factory(),
+ ast_value_factory()->this_function_string(), pos,
+ NORMAL_VARIABLE);
+ scope()->NewUnresolved(factory()->ast_node_factory(),
+ ast_value_factory()->this_string(), pos,
+ THIS_VARIABLE);
+ }
return PreParserExpression::Default();
}
V8_INLINE PreParserExpression NewSuperCallReference(int pos) {
+ if (track_unresolved_variables_) {
+ scope()->NewUnresolved(factory()->ast_node_factory(),
+ ast_value_factory()->this_function_string(), pos,
+ NORMAL_VARIABLE);
+ scope()->NewUnresolved(factory()->ast_node_factory(),
+ ast_value_factory()->new_target_string(), pos,
+ NORMAL_VARIABLE);
+ scope()->NewUnresolved(factory()->ast_node_factory(),
+ ast_value_factory()->this_string(), pos,
+ THIS_VARIABLE);
+ }
return PreParserExpression::SuperCallReference();
}
V8_INLINE PreParserExpression NewTargetExpression(int pos) {
- return PreParserExpression::Default();
+ return PreParserExpression::NewTargetExpression();
}
V8_INLINE PreParserExpression FunctionSentExpression(int pos) {
@@ -1660,7 +1692,6 @@ class PreParser : public ParserBase<PreParser> {
// Preparser's private field members.
int* use_counts_;
- std::unique_ptr<PreParseData> preparse_data_;
bool track_unresolved_variables_;
PreParserLogger log_;
PendingCompilationErrorHandler* pending_error_handler_;
diff --git a/deps/v8/src/parsing/rewriter.cc b/deps/v8/src/parsing/rewriter.cc
index 87359f79ac..00eb29550a 100644
--- a/deps/v8/src/parsing/rewriter.cc
+++ b/deps/v8/src/parsing/rewriter.cc
@@ -24,7 +24,7 @@ class Processor final : public AstVisitor<Processor> {
breakable_(false),
zone_(ast_value_factory->zone()),
closure_scope_(closure_scope),
- factory_(ast_value_factory) {
+ factory_(ast_value_factory, ast_value_factory->zone()) {
DCHECK_EQ(closure_scope, closure_scope->GetClosureScope());
InitializeAstVisitor(stack_limit);
}
@@ -38,7 +38,7 @@ class Processor final : public AstVisitor<Processor> {
breakable_(false),
zone_(ast_value_factory->zone()),
closure_scope_(closure_scope),
- factory_(ast_value_factory) {
+ factory_(ast_value_factory, zone_) {
DCHECK_EQ(closure_scope, closure_scope->GetClosureScope());
InitializeAstVisitor(parser->stack_limit());
}
diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc
index d3162dfbb2..e22308e8d5 100644
--- a/deps/v8/src/parsing/scanner-character-streams.cc
+++ b/deps/v8/src/parsing/scanner-character-streams.cc
@@ -387,8 +387,10 @@ void Utf8ExternalStreamingStream::SearchPosition(size_t position) {
// checking whether the # bytes in a chunk are equal to the # chars, and if
// so avoid the expensive SkipToPosition.)
bool ascii_only_chunk =
+ chunks_[chunk_no].start.incomplete_char ==
+ unibrow::Utf8::Utf8IncrementalBuffer(0) &&
(chunks_[chunk_no + 1].start.bytes - chunks_[chunk_no].start.bytes) ==
- (chunks_[chunk_no + 1].start.chars - chunks_[chunk_no].start.chars);
+ (chunks_[chunk_no + 1].start.chars - chunks_[chunk_no].start.chars);
if (ascii_only_chunk) {
size_t skip = position - chunks_[chunk_no].start.chars;
current_ = {chunk_no,
@@ -816,16 +818,20 @@ Utf16CharacterStream* ScannerStream::For(Handle<String> data) {
Utf16CharacterStream* ScannerStream::For(Handle<String> data, int start_pos,
int end_pos) {
DCHECK(start_pos >= 0);
+ DCHECK(start_pos <= end_pos);
DCHECK(end_pos <= data->length());
if (data->IsExternalOneByteString()) {
return new ExternalOneByteStringUtf16CharacterStream(
- Handle<ExternalOneByteString>::cast(data), start_pos, end_pos);
+ Handle<ExternalOneByteString>::cast(data),
+ static_cast<size_t>(start_pos), static_cast<size_t>(end_pos));
} else if (data->IsExternalTwoByteString()) {
return new ExternalTwoByteStringUtf16CharacterStream(
- Handle<ExternalTwoByteString>::cast(data), start_pos, end_pos);
+ Handle<ExternalTwoByteString>::cast(data),
+ static_cast<size_t>(start_pos), static_cast<size_t>(end_pos));
} else {
// TODO(vogelheim): Maybe call data.Flatten() first?
- return new GenericStringUtf16CharacterStream(data, start_pos, end_pos);
+ return new GenericStringUtf16CharacterStream(
+ data, static_cast<size_t>(start_pos), static_cast<size_t>(end_pos));
}
}
diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc
index 81839990c6..8dfb74c06a 100644
--- a/deps/v8/src/parsing/scanner.cc
+++ b/deps/v8/src/parsing/scanner.cc
@@ -182,16 +182,14 @@ Scanner::Scanner(UnicodeCache* unicode_cache)
octal_message_(MessageTemplate::kNone),
found_html_comment_(false) {}
-void Scanner::Initialize(Utf16CharacterStream* source) {
+void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
DCHECK_NOT_NULL(source);
source_ = source;
+ is_module_ = is_module;
// Need to capture identifiers in order to recognize "get" and "set"
// in object literals.
Init();
- // Skip initial whitespace allowing HTML comment ends just like
- // after a newline and scan first token.
has_line_terminator_before_next_ = true;
- SkipWhiteSpace();
Scan();
}
@@ -443,7 +441,7 @@ static inline bool IsLittleEndianByteOrderMark(uc32 c) {
return c == 0xFFFE;
}
-bool Scanner::SkipWhiteSpace() {
+Token::Value Scanner::SkipWhiteSpace() {
int start_position = source_pos();
while (true) {
@@ -481,11 +479,26 @@ bool Scanner::SkipWhiteSpace() {
}
// Treat the rest of the line as a comment.
- SkipSingleLineComment();
+ Token::Value token = SkipSingleHTMLComment();
+ if (token == Token::ILLEGAL) {
+ return token;
+ }
}
// Return whether or not we skipped any characters.
- return source_pos() != start_position;
+ if (source_pos() == start_position) {
+ return Token::ILLEGAL;
+ }
+
+ return Token::WHITESPACE;
+}
+
+Token::Value Scanner::SkipSingleHTMLComment() {
+ if (is_module_) {
+ ReportScannerError(source_pos(), MessageTemplate::kHtmlCommentInModule);
+ return Token::ILLEGAL;
+ }
+ return SkipSingleLineComment();
}
Token::Value Scanner::SkipSingleLineComment() {
@@ -606,7 +619,7 @@ Token::Value Scanner::ScanHtmlComment() {
}
found_html_comment_ = true;
- return SkipSingleLineComment();
+ return SkipSingleHTMLComment();
}
void Scanner::Scan() {
@@ -712,7 +725,7 @@ void Scanner::Scan() {
if (c0_ == '>' && HasAnyLineTerminatorBeforeNext()) {
// For compatibility with SpiderMonkey, we skip lines that
// start with an HTML comment end '-->'.
- token = SkipSingleLineComment();
+ token = SkipSingleHTMLComment();
} else {
token = Token::DEC;
}
@@ -864,10 +877,11 @@ void Scanner::Scan() {
token = ScanIdentifierOrKeyword();
} else if (IsDecimalDigit(c0_)) {
token = ScanNumber(false);
- } else if (SkipWhiteSpace()) {
- token = Token::WHITESPACE;
} else {
- token = Select(Token::ILLEGAL);
+ token = SkipWhiteSpace();
+ if (token == Token::ILLEGAL) {
+ Advance();
+ }
}
break;
}
@@ -1777,13 +1791,6 @@ double Scanner::DoubleValue() {
ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
}
-
-bool Scanner::ContainsDot() {
- DCHECK(is_literal_one_byte());
- Vector<const uint8_t> str = literal_one_byte_string();
- return std::find(str.begin(), str.end(), '.') != str.end();
-}
-
bool Scanner::IsDuplicateSymbol(DuplicateFinder* duplicate_finder,
AstValueFactory* ast_value_factory) const {
DCHECK_NOT_NULL(duplicate_finder);
diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h
index 5b3b671523..03b3f316c2 100644
--- a/deps/v8/src/parsing/scanner.h
+++ b/deps/v8/src/parsing/scanner.h
@@ -197,7 +197,7 @@ class Scanner {
explicit Scanner(UnicodeCache* scanner_contants);
- void Initialize(Utf16CharacterStream* source);
+ void Initialize(Utf16CharacterStream* source, bool is_module);
// Returns the next token and advances input.
Token::Value Next();
@@ -247,7 +247,6 @@ class Scanner {
AstValueFactory* ast_value_factory) const;
double DoubleValue();
- bool ContainsDot();
inline bool CurrentMatches(Token::Value token) const {
DCHECK(Token::IsKeyword(token));
@@ -689,7 +688,8 @@ class Scanner {
// Scans a single JavaScript token.
void Scan();
- bool SkipWhiteSpace();
+ Token::Value SkipWhiteSpace();
+ Token::Value SkipSingleHTMLComment();
Token::Value SkipSingleLineComment();
Token::Value SkipSourceURLComment();
void TryToParseSourceURLComment();
@@ -717,6 +717,8 @@ class Scanner {
template <bool capture_raw>
uc32 ScanUnicodeEscape();
+ bool is_module_;
+
Token::Value ScanTemplateSpan();
// Return the current source position.