diff options
author | Myles Borins <mylesborins@google.com> | 2018-04-10 21:39:51 -0400 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-04-11 13:22:42 -0400 |
commit | 12a1b9b8049462e47181a298120243dc83e81c55 (patch) | |
tree | 8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/parsing | |
parent | 78cd8263354705b767ef8c6a651740efe4931ba0 (diff) | |
download | android-node-v8-12a1b9b8049462e47181a298120243dc83e81c55.tar.gz android-node-v8-12a1b9b8049462e47181a298120243dc83e81c55.tar.bz2 android-node-v8-12a1b9b8049462e47181a298120243dc83e81c55.zip |
deps: update V8 to 6.6.346.23
PR-URL: https://github.com/nodejs/node/pull/19201
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Myles Borins <myles.borins@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/OWNERS | 1 | ||||
-rw-r--r-- | deps/v8/src/parsing/background-parsing-task.cc | 112 | ||||
-rw-r--r-- | deps/v8/src/parsing/background-parsing-task.h | 74 | ||||
-rw-r--r-- | deps/v8/src/parsing/expression-classifier.h | 6 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/parsing/parse-info.h | 14 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser-base.h | 207 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 290 | ||||
-rw-r--r-- | deps/v8/src/parsing/parser.h | 70 | ||||
-rw-r--r-- | deps/v8/src/parsing/parsing.cc | 7 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data-format.h | 32 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data.cc | 43 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparse-data.h | 53 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparsed-scope-data.cc | 19 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/parsing/preparser.h | 80 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.cc | 127 | ||||
-rw-r--r-- | deps/v8/src/parsing/scanner.h | 6 | ||||
-rw-r--r-- | deps/v8/src/parsing/token.h | 2 |
19 files changed, 371 insertions, 777 deletions
diff --git a/deps/v8/src/parsing/OWNERS b/deps/v8/src/parsing/OWNERS index fbbdd8b715..24218df199 100644 --- a/deps/v8/src/parsing/OWNERS +++ b/deps/v8/src/parsing/OWNERS @@ -5,7 +5,6 @@ gsathya@chromium.org littledan@chromium.org marja@chromium.org neis@chromium.org -rossberg@chromium.org verwaest@chromium.org # COMPONENT: Blink>JavaScript>Parser diff --git a/deps/v8/src/parsing/background-parsing-task.cc b/deps/v8/src/parsing/background-parsing-task.cc deleted file mode 100644 index cb811566df..0000000000 --- a/deps/v8/src/parsing/background-parsing-task.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/parsing/background-parsing-task.h" - -#include "src/counters.h" -#include "src/objects-inl.h" -#include "src/parsing/parser.h" -#include "src/parsing/scanner-character-streams.h" -#include "src/vm-state-inl.h" - -namespace v8 { -namespace internal { - -void StreamedSource::Release() { - parser.reset(); - info.reset(); -} - -BackgroundParsingTask::BackgroundParsingTask( - StreamedSource* source, ScriptCompiler::CompileOptions options, - int stack_size, Isolate* isolate) - : source_(source), - stack_size_(stack_size), - script_data_(nullptr), - timer_(isolate->counters()->compile_script_on_background()) { - // We don't set the context to the CompilationInfo yet, because the background - // thread cannot do anything with it anyway. We set it just before compilation - // on the foreground thread. - DCHECK(options == ScriptCompiler::kProduceParserCache || - options == ScriptCompiler::kProduceCodeCache || - options == ScriptCompiler::kProduceFullCodeCache || - options == ScriptCompiler::kNoCompileOptions || - options == ScriptCompiler::kEagerCompile); - - VMState<PARSER> state(isolate); - - // Prepare the data for the internalization phase and compilation phase, which - // will happen in the main thread after parsing. - ParseInfo* info = new ParseInfo(isolate->allocator()); - info->InitFromIsolate(isolate); - if (V8_UNLIKELY(FLAG_runtime_stats)) { - info->set_runtime_call_stats(new (info->zone()) RuntimeCallStats()); - } else { - info->set_runtime_call_stats(nullptr); - } - info->set_toplevel(); - std::unique_ptr<Utf16CharacterStream> stream( - ScannerStream::For(source->source_stream.get(), source->encoding, - info->runtime_call_stats())); - info->set_character_stream(std::move(stream)); - info->set_unicode_cache(&source_->unicode_cache); - info->set_compile_options(options); - info->set_allow_lazy_parsing(); - if (V8_UNLIKELY(info->block_coverage_enabled())) { - info->AllocateSourceRangeMap(); - } - info->set_cached_data(&script_data_); - LanguageMode language_mode = construct_language_mode(FLAG_use_strict); - info->set_language_mode( - stricter_language_mode(info->language_mode(), language_mode)); - - source->info.reset(info); - allocator_ = isolate->allocator(); - - // Parser needs to stay alive for finalizing the parsing on the main - // thread. - source_->parser.reset(new Parser(source_->info.get())); - source_->parser->DeserializeScopeChain(source_->info.get(), - MaybeHandle<ScopeInfo>()); -} - -void BackgroundParsingTask::Run() { - TimedHistogramScope timer(timer_); - DisallowHeapAllocation no_allocation; - DisallowHandleAllocation no_handles; - DisallowHandleDereference no_deref; - - source_->info->set_on_background_thread(true); - - // Reset the stack limit of the parser to reflect correctly that we're on a - // background thread. - uintptr_t old_stack_limit = source_->info->stack_limit(); - uintptr_t stack_limit = GetCurrentStackPosition() - stack_size_ * KB; - source_->info->set_stack_limit(stack_limit); - source_->parser->set_stack_limit(stack_limit); - - source_->parser->ParseOnBackground(source_->info.get()); - if (FLAG_background_compile && source_->info->literal() != nullptr) { - // Parsing has succeeded, compile. - source_->outer_function_job = Compiler::CompileTopLevelOnBackgroundThread( - source_->info.get(), allocator_, &source_->inner_function_jobs); - } - - if (script_data_ != nullptr) { - source_->cached_data.reset(new ScriptCompiler::CachedData( - script_data_->data(), script_data_->length(), - ScriptCompiler::CachedData::BufferOwned)); - script_data_->ReleaseDataOwnership(); - delete script_data_; - script_data_ = nullptr; - } - - source_->info->EmitBackgroundParseStatisticsOnBackgroundThread(); - - source_->info->set_on_background_thread(false); - source_->info->set_stack_limit(old_stack_limit); -} - -} // namespace internal -} // namespace v8 diff --git a/deps/v8/src/parsing/background-parsing-task.h b/deps/v8/src/parsing/background-parsing-task.h deleted file mode 100644 index eb3ed61e2e..0000000000 --- a/deps/v8/src/parsing/background-parsing-task.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_PARSING_BACKGROUND_PARSING_TASK_H_ -#define V8_PARSING_BACKGROUND_PARSING_TASK_H_ - -#include <memory> - -#include "include/v8.h" -#include "src/base/platform/platform.h" -#include "src/base/platform/semaphore.h" -#include "src/compiler.h" -#include "src/parsing/parse-info.h" -#include "src/unicode-cache.h" - -namespace v8 { -namespace internal { - -class Parser; -class ScriptData; -class TimedHistogram; - -// Internal representation of v8::ScriptCompiler::StreamedSource. Contains all -// data which needs to be transmitted between threads for background parsing, -// finalizing it on the main thread, and compiling on the main thread. -struct StreamedSource { - StreamedSource(ScriptCompiler::ExternalSourceStream* source_stream, - ScriptCompiler::StreamedSource::Encoding encoding) - : source_stream(source_stream), encoding(encoding) {} - - void Release(); - - // Internal implementation of v8::ScriptCompiler::StreamedSource. - std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream; - ScriptCompiler::StreamedSource::Encoding encoding; - std::unique_ptr<ScriptCompiler::CachedData> cached_data; - - // Data needed for parsing, and data needed to to be passed between thread - // between parsing and compilation. These need to be initialized before the - // compilation starts. - UnicodeCache unicode_cache; - std::unique_ptr<ParseInfo> info; - std::unique_ptr<Parser> parser; - - // Data needed for finalizing compilation after background compilation. - std::unique_ptr<CompilationJob> outer_function_job; - CompilationJobList inner_function_jobs; - - // Prevent copying. - StreamedSource(const StreamedSource&) = delete; - StreamedSource& operator=(const StreamedSource&) = delete; -}; - -class BackgroundParsingTask : public ScriptCompiler::ScriptStreamingTask { - public: - BackgroundParsingTask(StreamedSource* source, - ScriptCompiler::CompileOptions options, int stack_size, - Isolate* isolate); - - virtual void Run(); - - private: - StreamedSource* source_; // Not owned. - int stack_size_; - ScriptData* script_data_; - AccountingAllocator* allocator_; - TimedHistogram* timer_; -}; - -} // namespace internal -} // namespace v8 - -#endif // V8_PARSING_BACKGROUND_PARSING_TASK_H_ diff --git a/deps/v8/src/parsing/expression-classifier.h b/deps/v8/src/parsing/expression-classifier.h index 709d5736b5..522b650be7 100644 --- a/deps/v8/src/parsing/expression-classifier.h +++ b/deps/v8/src/parsing/expression-classifier.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H -#define V8_PARSING_EXPRESSION_CLASSIFIER_H +#ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H_ +#define V8_PARSING_EXPRESSION_CLASSIFIER_H_ #include "src/messages.h" #include "src/parsing/scanner.h" @@ -433,4 +433,4 @@ class ExpressionClassifier { } // namespace internal } // namespace v8 -#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H +#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H_ diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc index b8f191dd5a..8657dab7f2 100644 --- a/deps/v8/src/parsing/parse-info.cc +++ b/deps/v8/src/parsing/parse-info.cc @@ -20,7 +20,6 @@ ParseInfo::ParseInfo(AccountingAllocator* zone_allocator) : zone_(std::make_shared<Zone>(zone_allocator, ZONE_NAME)), flags_(0), extension_(nullptr), - compile_options_(ScriptCompiler::kNoCompileOptions), script_scope_(nullptr), unicode_cache_(nullptr), stack_limit_(0), @@ -32,7 +31,6 @@ ParseInfo::ParseInfo(AccountingAllocator* zone_allocator) function_literal_id_(FunctionLiteral::kIdTypeInvalid), max_function_literal_id_(FunctionLiteral::kIdTypeInvalid), character_stream_(nullptr), - cached_data_(nullptr), ast_value_factory_(nullptr), ast_string_constants_(nullptr), function_name_(nullptr), diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h index e93c7137ca..5a0cf138c1 100644 --- a/deps/v8/src/parsing/parse-info.h +++ b/deps/v8/src/parsing/parse-info.h @@ -29,7 +29,6 @@ class DeclarationScope; class FunctionLiteral; class RuntimeCallStats; class Logger; -class ScriptData; class SourceRangeMap; class UnicodeCache; class Utf16CharacterStream; @@ -85,6 +84,7 @@ class V8_EXPORT_PRIVATE ParseInfo { set_on_background_thread) FLAG_ACCESSOR(kWrappedAsFunction, is_wrapped_as_function, set_wrapped_as_function) + FLAG_ACCESSOR(kAllowEvalCache, allow_eval_cache, set_allow_eval_cache) #undef FLAG_ACCESSOR void set_parse_restriction(ParseRestriction restriction) { @@ -106,20 +106,11 @@ class V8_EXPORT_PRIVATE ParseInfo { v8::Extension* extension() const { return extension_; } void set_extension(v8::Extension* extension) { extension_ = extension; } - ScriptData** cached_data() const { return cached_data_; } - void set_cached_data(ScriptData** cached_data) { cached_data_ = cached_data; } ConsumedPreParsedScopeData* consumed_preparsed_scope_data() { return &consumed_preparsed_scope_data_; } - ScriptCompiler::CompileOptions compile_options() const { - return compile_options_; - } - void set_compile_options(ScriptCompiler::CompileOptions compile_options) { - compile_options_ = compile_options; - } - DeclarationScope* script_scope() const { return script_scope_; } void set_script_scope(DeclarationScope* script_scope) { script_scope_ = script_scope; @@ -263,13 +254,13 @@ class V8_EXPORT_PRIVATE ParseInfo { kIsAsmWasmBroken = 1 << 12, kOnBackgroundThread = 1 << 13, kWrappedAsFunction = 1 << 14, // Implicitly wrapped as function. + kAllowEvalCache = 1 << 15, }; //------------- Inputs to parsing and scope analysis ----------------------- std::shared_ptr<Zone> zone_; unsigned flags_; v8::Extension* extension_; - ScriptCompiler::CompileOptions compile_options_; DeclarationScope* script_scope_; UnicodeCache* unicode_cache_; uintptr_t stack_limit_; @@ -287,7 +278,6 @@ class V8_EXPORT_PRIVATE ParseInfo { //----------- Inputs+Outputs of parsing and scope analysis ----------------- std::unique_ptr<Utf16CharacterStream> character_stream_; - ScriptData** cached_data_; // used if available, populated if requested. ConsumedPreParsedScopeData consumed_preparsed_scope_data_; std::shared_ptr<AstValueFactory> ast_value_factory_; const class AstStringConstants* ast_string_constants_; diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h index faefe44011..2d608d5f40 100644 --- a/deps/v8/src/parsing/parser-base.h +++ b/deps/v8/src/parsing/parser-base.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_PARSING_PARSER_BASE_H -#define V8_PARSING_PARSER_BASE_H +#ifndef V8_PARSING_PARSER_BASE_H_ +#define V8_PARSING_PARSER_BASE_H_ #include <vector> @@ -12,6 +12,7 @@ #include "src/ast/scopes.h" #include "src/bailout-reason.h" #include "src/base/hashmap.h" +#include "src/base/v8-fallthrough.h" #include "src/counters.h" #include "src/globals.h" #include "src/log.h" @@ -277,13 +278,13 @@ class ParserBase { script_id_(script_id), allow_natives_(false), allow_harmony_do_expressions_(false), - allow_harmony_function_sent_(false), allow_harmony_public_fields_(false), allow_harmony_static_fields_(false), allow_harmony_dynamic_import_(false), allow_harmony_import_meta_(false), allow_harmony_optional_catch_binding_(false), - allow_harmony_private_fields_(false) {} + allow_harmony_private_fields_(false), + allow_eval_cache_(true) {} #define ALLOW_ACCESSORS(name) \ bool allow_##name() const { return allow_##name##_; } \ @@ -291,12 +292,12 @@ class ParserBase { ALLOW_ACCESSORS(natives); ALLOW_ACCESSORS(harmony_do_expressions); - ALLOW_ACCESSORS(harmony_function_sent); ALLOW_ACCESSORS(harmony_public_fields); ALLOW_ACCESSORS(harmony_static_fields); ALLOW_ACCESSORS(harmony_dynamic_import); ALLOW_ACCESSORS(harmony_import_meta); ALLOW_ACCESSORS(harmony_optional_catch_binding); + ALLOW_ACCESSORS(eval_cache); #undef ALLOW_ACCESSORS @@ -398,6 +399,9 @@ class ParserBase { } BailoutReason dont_optimize_reason() { return dont_optimize_reason_; } + void AddSuspend() { suspend_count_++; } + int suspend_count() const { return suspend_count_; } + FunctionKind kind() const { return scope()->function_kind(); } void RewindDestructuringAssignments(int pos) { @@ -425,10 +429,6 @@ class ParserBase { return &reported_errors_; } - ZoneList<RewritableExpressionT>* non_patterns_to_rewrite() { - return &non_patterns_to_rewrite_; - } - bool next_function_is_likely_called() const { return next_function_is_likely_called_; } @@ -478,13 +478,15 @@ class ParserBase { DeclarationScope* scope_; ZoneList<RewritableExpressionT> destructuring_assignments_to_rewrite_; - ZoneList<RewritableExpressionT> non_patterns_to_rewrite_; ZoneList<typename ExpressionClassifier::Error> reported_errors_; // A reason, if any, why this function should not be optimized. BailoutReason dont_optimize_reason_; + // How many suspends are needed for this function. + int suspend_count_; + // Record whether the next (=== immediately following) function literal is // preceded by a parenthesis / exclamation mark. Also record the previous // state. @@ -1084,6 +1086,8 @@ class ParserBase { IdentifierT ParseIdentifierName(bool* ok); + ExpressionT ParseIdentifierNameOrPrivateName(bool* ok); + ExpressionT ParseRegExpLiteral(bool* ok); ExpressionT ParsePrimaryExpression(bool* is_async, bool* ok); @@ -1124,10 +1128,10 @@ class ParserBase { bool* ok); ExpressionT ParseObjectLiteral(bool* ok); ClassLiteralPropertyT ParseClassPropertyDefinition( - ClassLiteralChecker* checker, ClassInfo* class_info, bool has_extends, - bool* is_computed_name, bool* has_seen_constructor, - ClassLiteralProperty::Kind* property_kind, bool* is_static, - bool* has_name_static_property, bool* ok); + ClassLiteralChecker* checker, ClassInfo* class_info, + IdentifierT* property_name, bool has_extends, bool* is_computed_name, + bool* has_seen_constructor, ClassLiteralProperty::Kind* property_kind, + bool* is_static, bool* has_name_static_property, bool* ok); ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, bool is_static, bool* ok); ObjectLiteralPropertyT ParseObjectPropertyDefinition( @@ -1407,6 +1411,7 @@ class ParserBase { // In async generators, if there is an explicit operand to the return // statement, await the operand. expr = factory()->NewAwait(expr, kNoSourcePosition); + function_state_->AddSuspend(); } if (is_async_function()) { return factory()->NewAsyncReturnStatement(expr, pos, end_pos); @@ -1451,6 +1456,10 @@ class ParserBase { return this->scanner()->CurrentMatchesContextualEscaped( Token::CONSTRUCTOR); } + bool IsPrivateConstructor() { + return this->scanner()->CurrentMatchesContextualEscaped( + Token::PRIVATE_CONSTRUCTOR); + } bool IsPrototype() { return this->scanner()->CurrentMatchesContextualEscaped(Token::PROTOTYPE); } @@ -1542,13 +1551,13 @@ class ParserBase { bool allow_natives_; bool allow_harmony_do_expressions_; - bool allow_harmony_function_sent_; bool allow_harmony_public_fields_; bool allow_harmony_static_fields_; bool allow_harmony_dynamic_import_; bool allow_harmony_import_meta_; bool allow_harmony_optional_catch_binding_; bool allow_harmony_private_fields_; + bool allow_eval_cache_; friend class DiscardableZoneScope; }; @@ -1563,9 +1572,9 @@ ParserBase<Impl>::FunctionState::FunctionState( outer_function_state_(*function_state_stack), scope_(scope), destructuring_assignments_to_rewrite_(16, scope->zone()), - non_patterns_to_rewrite_(0, scope->zone()), reported_errors_(16, scope->zone()), dont_optimize_reason_(BailoutReason::kNoReason), + suspend_count_(0), next_function_is_likely_called_(false), previous_function_was_likely_called_(false), contains_function_or_eval_(false) { @@ -1778,6 +1787,27 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName( } template <typename Impl> +typename ParserBase<Impl>::ExpressionT +ParserBase<Impl>::ParseIdentifierNameOrPrivateName(bool* ok) { + int pos = position(); + IdentifierT name; + ExpressionT key; + if (allow_harmony_private_fields() && peek() == Token::PRIVATE_NAME) { + Consume(Token::PRIVATE_NAME); + name = impl()->GetSymbol(); + auto key_proxy = + impl()->ExpressionFromIdentifier(name, pos, InferName::kNo); + key_proxy->set_is_private_field(); + key = key_proxy; + } else { + name = ParseIdentifierName(CHECK_OK); + key = factory()->NewStringLiteral(name, pos); + } + impl()->PushLiteralName(name); + return key; +} + +template <typename Impl> typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseRegExpLiteral( bool* ok) { int pos = peek_position(); @@ -1847,7 +1877,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( } // CoverCallExpressionAndAsyncArrowHead *is_async = true; - /* falls through */ + V8_FALLTHROUGH; case Token::IDENTIFIER: case Token::LET: case Token::STATIC: @@ -2237,7 +2267,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( } return expression; } - // Fall-through. + V8_FALLTHROUGH; default: *name = ParseIdentifierName(CHECK_OK); @@ -2263,8 +2293,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName( template <typename Impl> typename ParserBase<Impl>::ClassLiteralPropertyT ParserBase<Impl>::ParseClassPropertyDefinition( - ClassLiteralChecker* checker, ClassInfo* class_info, bool has_extends, - bool* is_computed_name, bool* has_seen_constructor, + ClassLiteralChecker* checker, ClassInfo* class_info, IdentifierT* name, + bool has_extends, bool* is_computed_name, bool* has_seen_constructor, ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* has_name_static_property, bool* ok) { DCHECK_NOT_NULL(has_seen_constructor); @@ -2282,19 +2312,19 @@ ParserBase<Impl>::ParseClassPropertyDefinition( allow_harmony_private_fields()); int name_token_position = scanner()->peek_location().beg_pos; - IdentifierT name = impl()->NullIdentifier(); + *name = impl()->NullIdentifier(); ExpressionT name_expression; if (name_token == Token::STATIC) { Consume(Token::STATIC); name_token_position = scanner()->peek_location().beg_pos; if (peek() == Token::LPAREN) { kind = PropertyKind::kMethodProperty; - name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' - name_expression = factory()->NewStringLiteral(name, position()); + *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' + name_expression = factory()->NewStringLiteral(*name, position()); } else if (peek() == Token::ASSIGN || peek() == Token::SEMICOLON || peek() == Token::RBRACE) { - name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' - name_expression = factory()->NewStringLiteral(name, position()); + *name = impl()->GetSymbol(); // TODO(bakkot) specialize on 'static' + name_expression = factory()->NewStringLiteral(*name, position()); } else if (peek() == Token::PRIVATE_NAME) { DCHECK(allow_harmony_private_fields()); // TODO(gsathya): Make a better error message for this. @@ -2303,21 +2333,21 @@ ParserBase<Impl>::ParseClassPropertyDefinition( return impl()->NullLiteralProperty(); } else { *is_static = true; - name_expression = ParsePropertyName(&name, &kind, &is_generator, &is_get, + name_expression = ParsePropertyName(name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, CHECK_OK_CUSTOM(NullLiteralProperty)); } } else if (name_token == Token::PRIVATE_NAME) { Consume(Token::PRIVATE_NAME); - name = impl()->GetSymbol(); - name_expression = factory()->NewStringLiteral(name, position()); + *name = impl()->GetSymbol(); + name_expression = factory()->NewStringLiteral(*name, position()); } else { - name_expression = ParsePropertyName(&name, &kind, &is_generator, &is_get, + name_expression = ParsePropertyName(name, &kind, &is_generator, &is_get, &is_set, &is_async, is_computed_name, CHECK_OK_CUSTOM(NullLiteralProperty)); } - if (!*has_name_static_property && *is_static && impl()->IsName(name)) { + if (!*has_name_static_property && *is_static && impl()->IsName(*name)) { *has_name_static_property = true; } @@ -2333,13 +2363,15 @@ ParserBase<Impl>::ParseClassPropertyDefinition( case PropertyKind::kShorthandProperty: case PropertyKind::kValueProperty: if (allow_harmony_public_fields() || allow_harmony_private_fields()) { - *property_kind = ClassLiteralProperty::FIELD; + *property_kind = name_token == Token::PRIVATE_NAME + ? ClassLiteralProperty::PRIVATE_FIELD + : ClassLiteralProperty::PUBLIC_FIELD; if (*is_static && !allow_harmony_static_fields()) { ReportUnexpectedToken(Next()); *ok = false; return impl()->NullLiteralProperty(); } - if (!*is_computed_name && name_token != Token::PRIVATE_NAME) { + if (!*is_computed_name) { checker->CheckClassFieldName(*is_static, CHECK_OK_CUSTOM(NullLiteralProperty)); } @@ -2349,7 +2381,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition( ClassLiteralPropertyT result = factory()->NewClassLiteralProperty( name_expression, initializer, *property_kind, *is_static, *is_computed_name); - impl()->SetFunctionNameFromPropertyName(result, name); + impl()->SetFunctionNameFromPropertyName(result, *name); return result; } else { @@ -2377,14 +2409,14 @@ ParserBase<Impl>::ParseClassPropertyDefinition( FunctionKind kind = MethodKindFor(is_generator, is_async); - if (!*is_static && impl()->IsConstructor(name)) { + if (!*is_static && impl()->IsConstructor(*name)) { *has_seen_constructor = true; kind = has_extends ? FunctionKind::kDerivedConstructor : FunctionKind::kBaseConstructor; } ExpressionT value = impl()->ParseFunctionLiteral( - name, scanner()->location(), kSkipFunctionNameCheck, kind, + *name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? name_token_position : kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, @@ -2394,7 +2426,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition( ClassLiteralPropertyT result = factory()->NewClassLiteralProperty( name_expression, value, *property_kind, *is_static, *is_computed_name); - impl()->SetFunctionNameFromPropertyName(result, name); + impl()->SetFunctionNameFromPropertyName(result, *name); return result; } @@ -2409,14 +2441,14 @@ ParserBase<Impl>::ParseClassPropertyDefinition( // Runtime_DefineAccessorPropertyUnchecked and since we can determine // this statically we can skip the extra runtime check. name_expression = - factory()->NewStringLiteral(name, name_expression->position()); + factory()->NewStringLiteral(*name, name_expression->position()); } FunctionKind kind = is_get ? FunctionKind::kGetterFunction : FunctionKind::kSetterFunction; FunctionLiteralT value = impl()->ParseFunctionLiteral( - name, scanner()->location(), kSkipFunctionNameCheck, kind, + *name, scanner()->location(), kSkipFunctionNameCheck, kind, FLAG_harmony_function_tostring ? name_token_position : kNoSourcePosition, FunctionLiteral::kAccessorOrMethod, language_mode(), nullptr, @@ -2430,7 +2462,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition( const AstRawString* prefix = is_get ? ast_value_factory()->get_space_string() : ast_value_factory()->set_space_string(); - impl()->SetFunctionNameFromPropertyName(result, name, prefix); + impl()->SetFunctionNameFromPropertyName(result, *name, prefix); return result; } case PropertyKind::kSpreadProperty: @@ -3035,6 +3067,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression( // a regular yield, given only one look-ahead token. if (!delegating) break; // Delegating yields require an RHS; fall through. + V8_FALLTHROUGH; default: expression = ParseAssignmentExpression(accept_IN, CHECK_OK); ValidateExpression(CHECK_OK); @@ -3045,6 +3078,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression( if (delegating) { ExpressionT yieldstar = factory()->NewYieldStar(expression, pos); impl()->RecordSuspendSourceRange(yieldstar, PositionAfterSemicolon()); + function_state_->AddSuspend(); + if (IsAsyncGeneratorFunction(function_state_->kind())) { + // iterator_close and delegated_iterator_output suspend ids. + function_state_->AddSuspend(); + function_state_->AddSuspend(); + } return yieldstar; } @@ -3053,6 +3092,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression( ExpressionT yield = factory()->NewYield(expression, pos, Suspend::kOnExceptionThrow); impl()->RecordSuspendSourceRange(yield, PositionAfterSemicolon()); + function_state_->AddSuspend(); return yield; } @@ -3191,13 +3231,19 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( ExpressionT expression = ParseUnaryExpression(CHECK_OK); ValidateExpression(CHECK_OK); - if (op == Token::DELETE && is_strict(language_mode())) { - if (impl()->IsIdentifier(expression)) { + if (op == Token::DELETE) { + if (impl()->IsIdentifier(expression) && is_strict(language_mode())) { // "delete identifier" is a syntax error in strict mode. ReportMessage(MessageTemplate::kStrictDelete); *ok = false; return impl()->NullExpression(); } + + if (impl()->IsPropertyWithPrivateFieldKey(expression)) { + ReportMessage(MessageTemplate::kDeletePrivateField); + *ok = false; + return impl()->NullExpression(); + } } if (peek() == Token::EXP) { @@ -3239,6 +3285,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseUnaryExpression( MessageTemplate::kInvalidDestructuringTarget); ExpressionT expr = factory()->NewAwait(value, await_pos); + function_state_->AddSuspend(); impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon()); return expr; } else { @@ -3399,10 +3446,8 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) { ArrowFormalParametersUnexpectedToken(); Consume(Token::PERIOD); int pos = position(); - IdentifierT name = ParseIdentifierName(CHECK_OK); - result = factory()->NewProperty( - result, factory()->NewStringLiteral(name, pos), pos); - impl()->PushLiteralName(name); + ExpressionT key = ParseIdentifierNameOrPrivateName(CHECK_OK); + result = factory()->NewProperty(result, key, pos); break; } @@ -3513,22 +3558,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseMemberExpression( Consume(Token::FUNCTION); int function_token_position = position(); - if (allow_harmony_function_sent() && peek() == Token::PERIOD) { - // function.sent - int pos = position(); - ExpectMetaProperty(Token::SENT, "function.sent", pos, CHECK_OK); - - if (!is_generator()) { - // TODO(neis): allow escaping into closures? - impl()->ReportMessageAt(scanner()->location(), - MessageTemplate::kUnexpectedFunctionSent); - *ok = false; - return impl()->NullExpression(); - } - - return impl()->FunctionSentExpression(pos); - } - FunctionKind function_kind = Check(Token::MUL) ? FunctionKind::kGeneratorFunction : FunctionKind::kNormalFunction; @@ -3699,16 +3728,8 @@ ParserBase<Impl>::ParseMemberExpressionContinuation(ExpressionT expression, Consume(Token::PERIOD); int pos = peek_position(); - IdentifierT name; - if (allow_harmony_private_fields() && peek() == Token::PRIVATE_NAME) { - Consume(Token::PRIVATE_NAME); - name = impl()->GetSymbol(); - } else { - name = ParseIdentifierName(CHECK_OK); - } - expression = factory()->NewProperty( - expression, factory()->NewStringLiteral(name, pos), pos); - impl()->PushLiteralName(name); + ExpressionT key = ParseIdentifierNameOrPrivateName(CHECK_OK); + expression = factory()->NewProperty(expression, key, pos); break; } case Token::TEMPLATE_SPAN: @@ -4354,6 +4375,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( StatementListT body = impl()->NullStatementList(); int expected_property_count = -1; + int suspend_count = 0; int function_literal_id = GetNextFunctionLiteralId(); FunctionKind kind = formal_parameters.scope->function_kind(); @@ -4440,6 +4462,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); impl()->RewriteDestructuringAssignments(); + suspend_count = function_state.suspend_count(); } FunctionLiteralT function_literal = factory()->NewFunctionLiteral( @@ -4451,6 +4474,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( formal_parameters.scope->start_position(), has_braces, function_literal_id, produced_preparsed_scope_data); + function_literal->set_suspend_count(suspend_count); function_literal->set_function_token_position( formal_parameters.scope->start_position()); @@ -4522,27 +4546,29 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral( bool is_static; ClassLiteralProperty::Kind property_kind; ExpressionClassifier property_classifier(this); + IdentifierT property_name; // If we haven't seen the constructor yet, it potentially is the next // property. bool is_constructor = !class_info.has_seen_constructor; ClassLiteralPropertyT property = ParseClassPropertyDefinition( - &checker, &class_info, has_extends, &is_computed_name, + &checker, &class_info, &property_name, has_extends, &is_computed_name, &class_info.has_seen_constructor, &property_kind, &is_static, &class_info.has_name_static_property, CHECK_OK); if (!class_info.has_static_computed_names && is_static && is_computed_name) { class_info.has_static_computed_names = true; } - if (is_computed_name && property_kind == ClassLiteralProperty::FIELD) { + if (is_computed_name && + property_kind == ClassLiteralProperty::PUBLIC_FIELD) { class_info.computed_field_count++; } is_constructor &= class_info.has_seen_constructor; ValidateExpression(CHECK_OK); AccumulateFormalParameterContainmentErrors(); - impl()->DeclareClassProperty(name, property, property_kind, is_static, - is_constructor, is_computed_name, &class_info, - CHECK_OK); + impl()->DeclareClassProperty(name, property, property_name, property_kind, + is_static, is_constructor, is_computed_name, + &class_info, CHECK_OK); impl()->InferFunctionName(); } @@ -4644,6 +4670,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( // TEMPLATE_SPAN, or a TEMPLATE_TAIL. DCHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); + if (tagged) { + // TaggedTemplate expressions prevent the eval compilation cache from being + // used. This flag is only used if an eval is being parsed. + set_allow_eval_cache(false); + } + bool forbid_illegal_escapes = !tagged; // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. @@ -4794,7 +4826,12 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic( ExpressionClassifier classifier(this); ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK); - DCHECK(!spread_pos.IsValid()); + if (spread_pos.IsValid()) { + *ok = false; + ReportMessageAt(spread_pos, MessageTemplate::kIntrinsicWithSpread, + kSyntaxError); + return impl()->NullExpression(); + } return impl()->NewV8Intrinsic(name, args, pos, ok); } @@ -4943,7 +4980,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem( Consume(Token::ASYNC); return ParseAsyncFunctionDeclaration(nullptr, false, ok); } - /* falls through */ + break; default: break; } @@ -5044,7 +5081,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement( *ok = false; return impl()->NullStatement(); } - // Falls through + V8_FALLTHROUGH; default: return ParseExpressionOrLabelledStatement(labels, allow_function, ok); } @@ -5653,6 +5690,14 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement( template <typename Impl> typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( ZoneList<const AstRawString*>* labels, bool* ok) { + // Either a standard for loop + // for (<init>; <cond>; <next>) { ... } + // or a for-each loop + // for (<each> of|in <iterable>) { ... } + // + // We parse a declaration/expression after the 'for (' and then read the first + // expression/declaration before we know if this is a for or a for-each. + int stmt_pos = peek_position(); ForInfo for_info(this); @@ -6187,7 +6232,7 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static, return; } - if (IsConstructor()) { + if (IsConstructor() || IsPrivateConstructor()) { this->parser()->ReportMessage(MessageTemplate::kConstructorClassField); *ok = false; return; @@ -6201,4 +6246,4 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static, } // namespace internal } // namespace v8 -#endif // V8_PARSING_PARSER_BASE_H +#endif // V8_PARSING_PARSER_BASE_H_ diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 0497958c82..8dc16a8b35 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -29,82 +29,8 @@ namespace v8 { namespace internal { -ScriptData::ScriptData(const byte* data, int length) - : owns_data_(false), rejected_(false), data_(data), length_(length) { - if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) { - byte* copy = NewArray<byte>(length); - DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment)); - CopyBytes(copy, data, length); - data_ = copy; - AcquireDataOwnership(); - } -} - -FunctionEntry ParseData::GetFunctionEntry(int start) { - // The current pre-data entry must be a FunctionEntry with the given - // start position. - if ((function_index_ + FunctionEntry::kSize <= Length()) && - (static_cast<int>(Data()[function_index_]) == start)) { - int index = function_index_; - function_index_ += FunctionEntry::kSize; - Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize); - return FunctionEntry(subvector); - } - return FunctionEntry(); -} - - -int ParseData::FunctionCount() { - int functions_size = FunctionsSize(); - if (functions_size < 0) return 0; - if (functions_size % FunctionEntry::kSize != 0) return 0; - return functions_size / FunctionEntry::kSize; -} - - -bool ParseData::IsSane() { - if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false; - // Check that the header data is valid and doesn't specify - // point to positions outside the store. - int data_length = Length(); - if (data_length < PreparseDataConstants::kHeaderSize) return false; - if (Magic() != PreparseDataConstants::kMagicNumber) return false; - if (Version() != PreparseDataConstants::kCurrentVersion) return false; - // Check that the space allocated for function entries is sane. - int functions_size = FunctionsSize(); - if (functions_size < 0) return false; - if (functions_size % FunctionEntry::kSize != 0) return false; - // Check that the total size has room for header and function entries. - int minimum_size = - PreparseDataConstants::kHeaderSize + functions_size; - if (data_length < minimum_size) return false; - return true; -} - - -void ParseData::Initialize() { - // Prepares state for use. - int data_length = Length(); - if (data_length >= PreparseDataConstants::kHeaderSize) { - function_index_ = PreparseDataConstants::kHeaderSize; - } -} - - -unsigned ParseData::Magic() { - return Data()[PreparseDataConstants::kMagicOffset]; -} - - -unsigned ParseData::Version() { - return Data()[PreparseDataConstants::kVersionOffset]; -} -int ParseData::FunctionsSize() { - return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]); -} - // Helper for putting parts of the parse results into a temporary zone when // parsing inner function bodies. class DiscardableZoneScope { @@ -153,17 +79,6 @@ class DiscardableZoneScope { DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope); }; -void Parser::SetCachedData(ParseInfo* info) { - DCHECK_NULL(cached_parse_data_); - if (consume_cached_parse_data()) { - if (allow_lazy_) { - cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); - if (cached_parse_data_ != nullptr) return; - } - compile_options_ = ScriptCompiler::kNoCompileOptions; - } -} - FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, bool call_super, int pos, int end_pos) { @@ -403,16 +318,6 @@ Expression* Parser::NewTargetExpression(int pos) { return proxy; } -Expression* Parser::FunctionSentExpression(int pos) { - // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator). - ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); - VariableProxy* generator = factory()->NewVariableProxy( - function_state_->scope()->generator_object_var()); - args->Add(generator, zone()); - return factory()->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, - args, pos); -} - Expression* Parser::ImportMetaExpression(int pos) { return factory()->NewCallRuntime( Runtime::kInlineGetImportMetaObject, @@ -511,11 +416,8 @@ Parser::Parser(ParseInfo* info) mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. source_range_map_(info->source_range_map()), target_stack_(nullptr), - compile_options_(info->compile_options()), - cached_parse_data_(nullptr), total_preparse_skipped_(0), temp_zoned_(false), - log_(nullptr), consumed_preparsed_scope_data_(info->consumed_preparsed_scope_data()), parameters_end_pos_(info->parameters_end_pos()) { // Even though we were passed ParseInfo, we should not store it in @@ -541,7 +443,6 @@ Parser::Parser(ParseInfo* info) info->extension() == nullptr && can_compile_lazily; set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); - set_allow_harmony_function_sent(FLAG_harmony_function_sent); set_allow_harmony_public_fields(FLAG_harmony_public_fields); set_allow_harmony_static_fields(FLAG_harmony_static_fields); set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); @@ -603,18 +504,6 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); // Initialize parser state. - ParserLogger logger; - - if (produce_cached_parse_data()) { - if (allow_lazy_) { - log_ = &logger; - } else { - compile_options_ = ScriptCompiler::kNoCompileOptions; - } - } else if (consume_cached_parse_data()) { - cached_parse_data_->Initialize(); - } - DeserializeScopeChain(info, info->maybe_outer_scope_info()); scanner_.Initialize(info->character_stream(), info->is_module()); @@ -623,11 +512,6 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { HandleSourceURLComments(isolate, info->script()); - if (produce_cached_parse_data() && result != nullptr) { - *info->cached_data() = logger.GetScriptData(); - } - log_ = nullptr; - if (V8_UNLIKELY(FLAG_log_function_events) && result != nullptr) { double ms = timer.Elapsed().InMillisecondsF(); const char* event_name = "parse-eval"; @@ -742,6 +626,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { result = factory()->NewScriptOrEvalFunctionLiteral( scope, body, function_state.expected_property_count(), parameter_count); + result->set_suspend_count(function_state.suspend_count()); } } @@ -904,8 +789,9 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, scope->set_start_position(info->start_position()); ExpressionClassifier formals_classifier(this); ParserFormalParameters formals(scope); - int rewritable_length = - function_state.destructuring_assignments_to_rewrite().length(); + // The outer FunctionState should not contain destructuring assignments. + DCHECK_EQ(0, + function_state.destructuring_assignments_to_rewrite().length()); { // Parsing patterns as variable reference expression creates // NewUnresolved references in current scope. Enter arrow function @@ -943,8 +829,12 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should // not be observable, or else the preparser would have failed. - Expression* expression = - ParseArrowFunctionLiteral(true, formals, rewritable_length, &ok); + const bool accept_IN = true; + // Any destructuring assignments in the current FunctionState + // actually belong to the arrow function itself. + const int rewritable_length = 0; + Expression* expression = ParseArrowFunctionLiteral( + accept_IN, formals, rewritable_length, &ok); if (ok) { // Scanning must end at the same position that was recorded // previously. If not, parsing has been interrupted due to a stack @@ -957,10 +847,6 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, // must produce a FunctionLiteral. DCHECK(expression->IsFunctionLiteral()); result = expression->AsFunctionLiteral(); - // Rewrite destructuring assignments in the parameters. (The ones - // inside the function body are rewritten by - // ParseArrowFunctionLiteral.) - RewriteDestructuringAssignments(); } else { ok = false; } @@ -1293,7 +1179,7 @@ Statement* Parser::ParseExportDefault(bool* ok) { result = ParseAsyncFunctionDeclaration(&local_names, true, CHECK_OK); break; } - /* falls through */ + V8_FALLTHROUGH; default: { int pos = position(); @@ -1531,8 +1417,7 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name, ZoneList<const AstRawString*>* names, bool* ok) { VariableProxy* proxy = - factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE); - + factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE, pos); Declaration* declaration = factory()->NewFunctionDeclaration(proxy, function, pos); Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized, @@ -1831,6 +1716,8 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody( // Don't create iterator result for async generators, as the resume methods // will create it. + // TODO(leszeks): This will create another suspend point, which is unnecessary + // if there is already an unconditional return in the body. Statement* final_return = BuildReturnStatement( factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition); try_block->statements()->Add(final_return, zone()); @@ -1900,6 +1787,7 @@ Expression* Parser::BuildIteratorNextResult(VariableProxy* iterator, Expression* next_call = factory()->NewCall(next_property, next_arguments, kNoSourcePosition); if (type == IteratorType::kAsync) { + function_state_->AddSuspend(); next_call = factory()->NewAwait(next_call, pos); } Expression* result_proxy = factory()->NewVariableProxy(result); @@ -2681,6 +2569,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ZoneList<Statement*>* body = nullptr; int expected_property_count = -1; + int suspend_count = -1; int num_parameters = -1; int function_length = -1; bool has_duplicate_parameters = false; @@ -2747,10 +2636,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (should_preparse) { scope->AnalyzePartially(&previous_zone_ast_node_factory); } else { - body = ParseFunction(function_name, pos, kind, function_type, scope, - &num_parameters, &function_length, - &has_duplicate_parameters, &expected_property_count, - arguments_for_wrapped_function, CHECK_OK); + body = ParseFunction( + function_name, pos, kind, function_type, scope, &num_parameters, + &function_length, &has_duplicate_parameters, &expected_property_count, + &suspend_count, arguments_for_wrapped_function, CHECK_OK); } DCHECK_EQ(should_preparse, temp_zoned_); @@ -2808,6 +2697,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( function_length, duplicate_parameters, function_type, eager_compile_hint, pos, true, function_literal_id, produced_preparsed_scope_data); function_literal->set_function_token_position(function_token_pos); + function_literal->set_suspend_count(suspend_count); if (should_infer_name) { DCHECK_NOT_NULL(fni_); @@ -2826,38 +2716,11 @@ Parser::LazyParsingResult Parser::SkipFunction( DCHECK_NE(kNoSourcePosition, function_scope->start_position()); DCHECK_EQ(kNoSourcePosition, parameters_end_pos_); - if (produce_cached_parse_data()) CHECK(log_); DCHECK_IMPLIES(IsArrowFunction(kind), scanner()->current_token() == Token::ARROW); - // Inner functions are not part of the cached data. - if (!is_inner_function && consume_cached_parse_data() && - !cached_parse_data_->rejected()) { - // If we have cached data, we use it to skip parsing the function. The data - // contains the information we need to construct the lazy function. - FunctionEntry entry = - cached_parse_data_->GetFunctionEntry(function_scope->start_position()); - // Check that cached data is valid. If not, mark it as invalid (the embedder - // handles it). Note that end position greater than end of stream is safe, - // and hard to check. - if (entry.is_valid() && - entry.end_pos() > function_scope->start_position()) { - total_preparse_skipped_ += entry.end_pos() - position(); - function_scope->set_end_position(entry.end_pos()); - scanner()->SeekForward(entry.end_pos() - 1); - Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); - *num_parameters = entry.num_parameters(); - SetLanguageMode(function_scope, entry.language_mode()); - if (entry.uses_super_property()) - function_scope->RecordSuperPropertyUsage(); - SkipFunctionLiterals(entry.num_inner_functions()); - return kLazyParsingComplete; - } - cached_parse_data_->Reject(); - } - - // FIXME(marja): There are 3 ways to skip functions now. Unify them. + // FIXME(marja): There are 2 ways to skip functions now. Unify them. DCHECK_NOT_NULL(consumed_preparsed_scope_data_); if (consumed_preparsed_scope_data_->HasData()) { DCHECK(FLAG_preparser_scope_analysis); @@ -2908,6 +2771,9 @@ Parser::LazyParsingResult Parser::SkipFunction( *ok = false; return kLazyParsingComplete; } + + set_allow_eval_cache(reusable_preparser()->allow_eval_cache()); + PreParserLogger* logger = reusable_preparser()->logger(); function_scope->set_end_position(logger->end()); Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete)); @@ -2915,13 +2781,6 @@ Parser::LazyParsingResult Parser::SkipFunction( function_scope->end_position() - function_scope->start_position(); *num_parameters = logger->num_parameters(); 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, - language_mode(), function_scope->NeedsHomeObject(), - logger->num_inner_functions()); - } return kLazyParsingComplete; } @@ -3136,7 +2995,7 @@ Expression* Parser::BuildResolvePromise(Expression* value, int pos) { args->Add(factory()->NewVariableProxy(PromiseVariable()), zone()); args->Add(value, zone()); Expression* call_runtime = - factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos); + factory()->NewCallRuntime(Runtime::kInlineResolvePromise, args, pos); return factory()->NewBinaryOperation( Token::COMMA, call_runtime, factory()->NewVariableProxy(PromiseVariable()), pos); @@ -3150,8 +3009,8 @@ Expression* Parser::BuildRejectPromise(Expression* value, int pos) { args->Add(factory()->NewVariableProxy(PromiseVariable()), zone()); args->Add(value, zone()); args->Add(factory()->NewBooleanLiteral(false, pos), zone()); - Expression* call_runtime = factory()->NewCallRuntime( - Context::PROMISE_INTERNAL_REJECT_INDEX, args, pos); + Expression* call_runtime = + factory()->NewCallRuntime(Runtime::kInlineRejectPromise, args, pos); return factory()->NewBinaryOperation( Token::COMMA, call_runtime, factory()->NewVariableProxy(PromiseVariable()), pos); @@ -3175,6 +3034,7 @@ Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) { // 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). + function_state_->AddSuspend(); return factory()->NewYield(yield_result, scope()->start_position(), Suspend::kOnExceptionThrow); } @@ -3184,6 +3044,7 @@ ZoneList<Statement*>* Parser::ParseFunction( FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope, int* num_parameters, int* function_length, bool* has_duplicate_parameters, int* expected_property_count, + int* suspend_count, ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok) { ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); @@ -3268,6 +3129,7 @@ ZoneList<Statement*>* Parser::ParseFunction( !classifier()->is_valid_formal_parameter_list_without_duplicates(); *expected_property_count = function_state.expected_property_count(); + *suspend_count = function_state.suspend_count(); return body; } @@ -3308,6 +3170,7 @@ Variable* Parser::CreateSyntheticContextVariable(const AstRawString* name, // - properties void Parser::DeclareClassProperty(const AstRawString* class_name, ClassLiteralProperty* property, + const AstRawString* property_name, ClassLiteralProperty::Kind kind, bool is_static, bool is_constructor, bool is_computed_name, ClassInfo* class_info, @@ -3322,7 +3185,8 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, return; } - if (kind != ClassLiteralProperty::FIELD) { + if (kind != ClassLiteralProperty::PUBLIC_FIELD && + kind != ClassLiteralProperty::PRIVATE_FIELD) { class_info->properties->Add(property, zone()); return; } @@ -3331,12 +3195,14 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, if (is_static) { DCHECK(allow_harmony_static_fields()); + DCHECK_EQ(kind, ClassLiteralProperty::PUBLIC_FIELD); class_info->static_fields->Add(property, zone()); } else { class_info->instance_fields->Add(property, zone()); } if (is_computed_name) { + DCHECK_EQ(kind, ClassLiteralProperty::PUBLIC_FIELD); // We create a synthetic variable name here so that scope // analysis doesn't dedupe the vars. Variable* computed_name_var = CreateSyntheticContextVariable( @@ -3346,6 +3212,13 @@ void Parser::DeclareClassProperty(const AstRawString* class_name, property->set_computed_name_var(computed_name_var); class_info->properties->Add(property, zone()); } + + if (kind == ClassLiteralProperty::PRIVATE_FIELD) { + Variable* private_field_name_var = + CreateSyntheticContextVariable(property_name, CHECK_OK_VOID); + property->set_private_field_name_var(private_field_name_var); + class_info->properties->Add(property, zone()); + } } FunctionLiteral* Parser::CreateInitializerFunction( @@ -3432,6 +3305,15 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { } } +bool Parser::IsPropertyWithPrivateFieldKey(Expression* expression) { + if (!expression->IsProperty()) return false; + Property* property = expression->AsProperty(); + + if (!property->key()->IsVariableProxy()) return false; + VariableProxy* key = property->key()->AsVariableProxy(); + + return key->is_private_field(); +} void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { // For each var-binding that shadows a parameter, insert an assignment @@ -3550,15 +3432,6 @@ void Parser::ParseOnBackground(ParseInfo* info) { DCHECK_NULL(info->literal()); FunctionLiteral* result = nullptr; - ParserLogger logger; - if (produce_cached_parse_data()) { - if (allow_lazy_) { - log_ = &logger; - } else { - compile_options_ = ScriptCompiler::kNoCompileOptions; - } - } - scanner_.Initialize(info->character_stream(), info->is_module()); DCHECK(info->maybe_outer_scope_info().is_null()); @@ -3582,11 +3455,6 @@ void Parser::ParseOnBackground(ParseInfo* info) { // We cannot internalize on a background thread; a foreground task will take // care of calling AstValueFactory::Internalize just before compilation. - - if (produce_cached_parse_data()) { - if (result != nullptr) *info->cached_data() = logger.GetScriptData(); - log_ = nullptr; - } } Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { @@ -3654,9 +3522,8 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, return expr; } else { // GetTemplateObject - const int32_t hash = ComputeTemplateLiteralHash(lit); Expression* template_object = - factory()->NewGetTemplateObject(cooked_strings, raw_strings, hash, pos); + factory()->NewGetTemplateObject(cooked_strings, raw_strings, pos); // Call TagFn ZoneList<Expression*>* call_args = @@ -3669,51 +3536,6 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, namespace { -// http://burtleburtle.net/bob/hash/integer.html -uint32_t HalfAvalance(uint32_t a) { - a = (a + 0x479AB41D) + (a << 8); - a = (a ^ 0xE4AA10CE) ^ (a >> 5); - a = (a + 0x9942F0A6) - (a << 14); - a = (a ^ 0x5AEDD67D) ^ (a >> 3); - a = (a + 0x17BEA992) + (a << 7); - return a; -} - -} // namespace - -int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { - const ZoneList<const AstRawString*>* raw_strings = lit->raw(); - int total = raw_strings->length(); - DCHECK_GT(total, 0); - - uint32_t running_hash = 0; - - for (int index = 0; index < total; ++index) { - if (index) { - running_hash = StringHasher::ComputeRunningHashOneByte( - running_hash, "${}", 3); - } - - const AstRawString* raw_string = raw_strings->at(index); - if (raw_string->is_one_byte()) { - const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); - running_hash = StringHasher::ComputeRunningHashOneByte( - running_hash, data, raw_string->length()); - } else { - const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); - running_hash = StringHasher::ComputeRunningHash(running_hash, data, - raw_string->length()); - } - } - - // Pass {running_hash} throught a decent 'half avalance' hash function - // and take the most significant bits (in Smi range). - return static_cast<int32_t>(HalfAvalance(running_hash)) >> - (sizeof(int32_t) * CHAR_BIT - kSmiValueSize); -} - -namespace { - bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { for (int i = 0; i < args->length() - 1; i++) { if (args->at(i)->IsSpread()) { @@ -3911,6 +3733,9 @@ void Parser::RewriteDestructuringAssignments() { // pair.scope may already have been removed by FinalizeBlockScope in the // meantime. Scope* scope = to_rewrite->scope()->GetUnremovedScope(); + // Scope at the time of the rewriting and the original parsing + // should be in the same function. + DCHECK(scope->GetClosureScope() == scope_->GetClosureScope()); BlockState block_state(&scope_, scope); RewriteDestructuringAssignment(to_rewrite); } @@ -4070,6 +3895,7 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements, Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); if (type == IteratorType::kAsync) { + function_state_->AddSuspend(); call = factory()->NewAwait(call, nopos); } Expression* output_proxy = factory()->NewVariableProxy(var_output); @@ -4288,6 +4114,7 @@ void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); if (type == IteratorType::kAsync) { + function_state_->AddSuspend(); call = factory()->NewAwait(call, nopos); } @@ -4315,6 +4142,7 @@ void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements, Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); if (type == IteratorType::kAsync) { + function_state_->AddSuspend(); call = factory()->NewAwait(call, nopos); } diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h index f92eddcd9d..dcc222da0f 100644 --- a/deps/v8/src/parsing/parser.h +++ b/deps/v8/src/parsing/parser.h @@ -14,7 +14,6 @@ #include "src/globals.h" #include "src/parsing/parser-base.h" #include "src/parsing/parsing.h" -#include "src/parsing/preparse-data-format.h" #include "src/parsing/preparse-data.h" #include "src/parsing/preparser.h" #include "src/utils.h" @@ -27,7 +26,6 @@ namespace internal { class ConsumedPreParsedScopeData; class ParseInfo; -class ScriptData; class ParserTarget; class ParserTargetScope; class PendingCompilationErrorHandler; @@ -77,47 +75,6 @@ class FunctionEntry BASE_EMBEDDED { }; -// Wrapper around ScriptData to provide parser-specific functionality. -class ParseData { - public: - static ParseData* FromCachedData(ScriptData* cached_data) { - ParseData* pd = new ParseData(cached_data); - if (pd->IsSane()) return pd; - cached_data->Reject(); - delete pd; - return nullptr; - } - - void Initialize(); - FunctionEntry GetFunctionEntry(int start); - int FunctionCount(); - - unsigned* Data() { // Writable data as unsigned int array. - return reinterpret_cast<unsigned*>(const_cast<byte*>(script_data_->data())); - } - - void Reject() { script_data_->Reject(); } - - bool rejected() const { return script_data_->rejected(); } - - private: - explicit ParseData(ScriptData* script_data) : script_data_(script_data) {} - - bool IsSane(); - unsigned Magic(); - unsigned Version(); - int FunctionsSize(); - int Length() const { - // Script data length is already checked to be a multiple of unsigned size. - return script_data_->length() / sizeof(unsigned); - } - - ScriptData* script_data_; - int function_index_; - - DISALLOW_COPY_AND_ASSIGN(ParseData); -}; - // ---------------------------------------------------------------------------- // JAVASCRIPT PARSING @@ -192,8 +149,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ~Parser() { delete reusable_preparser_; reusable_preparser_ = nullptr; - delete cached_parse_data_; - cached_parse_data_ = nullptr; } static bool IsPreParser() { return false; } @@ -276,20 +231,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ZoneList<const AstRawString*>* PrepareWrappedArguments(ParseInfo* info, Zone* zone); - void SetCachedData(ParseInfo* info); - void StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate); - ScriptCompiler::CompileOptions compile_options() const { - return compile_options_; - } - bool consume_cached_parse_data() const { - return compile_options_ == ScriptCompiler::kConsumeParserCache; - } - bool produce_cached_parse_data() const { - return compile_options_ == ScriptCompiler::kProduceParserCache; - } - PreParser* reusable_preparser() { if (reusable_preparser_ == nullptr) { reusable_preparser_ = @@ -299,7 +242,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); SET_ALLOW(natives); SET_ALLOW(harmony_do_expressions); - SET_ALLOW(harmony_function_sent); SET_ALLOW(harmony_public_fields); SET_ALLOW(harmony_static_fields); SET_ALLOW(harmony_dynamic_import); @@ -307,6 +249,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { SET_ALLOW(harmony_bigint); SET_ALLOW(harmony_optional_catch_binding); SET_ALLOW(harmony_private_fields); + SET_ALLOW(eval_cache); #undef SET_ALLOW } return reusable_preparser_; @@ -377,6 +320,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { int class_token_pos, bool* ok); V8_INLINE void DeclareClassProperty(const AstRawString* class_name, ClassLiteralProperty* property, + const AstRawString* property_name, ClassLiteralProperty::Kind kind, bool is_static, bool is_constructor, bool is_computed_name, @@ -456,6 +400,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { // hoisted over such a scope. void CheckConflictingVarDeclarations(Scope* scope, bool* ok); + bool IsPropertyWithPrivateFieldKey(Expression* property); + // Insert initializer statements for var-bindings shadowing parameter bindings // from a non-simple parameter list. void InsertShadowingVarBindingInitializers(Block* block); @@ -506,7 +452,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope, int* num_parameters, int* function_length, bool* has_duplicate_parameters, - int* expected_property_count, + int* expected_property_count, int* suspend_count, ZoneList<const AstRawString*>* arguments_for_wrapped_function, bool* ok); void ThrowPendingError(Isolate* isolate, Handle<Script> script); @@ -555,7 +501,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { Expression* expression); Expression* CloseTemplateLiteral(TemplateLiteralState* state, int start, Expression* tag); - int32_t ComputeTemplateLiteralHash(const TemplateLiteral* lit); ZoneList<Expression*>* PrepareSpreadArguments(ZoneList<Expression*>* list); Expression* SpreadCall(Expression* function, ZoneList<Expression*>* args, @@ -883,12 +828,11 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { Expression* NewSuperPropertyReference(int pos); Expression* NewSuperCallReference(int pos); Expression* NewTargetExpression(int pos); - Expression* FunctionSentExpression(int pos); Expression* ImportMetaExpression(int pos); Literal* ExpressionFromLiteral(Token::Value token, int pos); - V8_INLINE Expression* ExpressionFromIdentifier( + V8_INLINE VariableProxy* ExpressionFromIdentifier( const AstRawString* name, int start_position, InferName infer = InferName::kYes) { if (infer == InferName::kYes) { @@ -1144,7 +1088,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { ParserTarget* target_stack_; // for break, continue statements ScriptCompiler::CompileOptions compile_options_; - ParseData* cached_parse_data_; // Other information which will be stored in Parser and moved to Isolate after // parsing. @@ -1152,7 +1095,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) { int total_preparse_skipped_; bool allow_lazy_; bool temp_zoned_; - ParserLogger* log_; ConsumedPreParsedScopeData* consumed_preparsed_scope_data_; // If not kNoSourcePosition, indicates that the first function literal diff --git a/deps/v8/src/parsing/parsing.cc b/deps/v8/src/parsing/parsing.cc index bc3c6dec7b..d34f826a23 100644 --- a/deps/v8/src/parsing/parsing.cc +++ b/deps/v8/src/parsing/parsing.cc @@ -36,7 +36,6 @@ bool ParseProgram(ParseInfo* info, Isolate* isolate) { // Ok to use Isolate here; this function is only called in the main thread. DCHECK(parser.parsing_on_main_thread_); - parser.SetCachedData(info); result = parser.ParseProgram(isolate, info); info->set_literal(result); if (result == nullptr) { @@ -45,6 +44,9 @@ bool ParseProgram(ParseInfo* info, Isolate* isolate) { } else { result->scope()->AttachOuterScopeInfo(info, isolate); info->set_language_mode(info->literal()->language_mode()); + if (info->is_eval()) { + info->set_allow_eval_cache(parser.allow_eval_cache()); + } } parser.UpdateStatistics(isolate, info->script()); return (result != nullptr); @@ -79,6 +81,9 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info, info->ast_value_factory()); } else { result->scope()->AttachOuterScopeInfo(info, isolate); + if (info->is_eval()) { + info->set_allow_eval_cache(parser.allow_eval_cache()); + } } parser.UpdateStatistics(isolate, info->script()); return (result != nullptr); diff --git a/deps/v8/src/parsing/preparse-data-format.h b/deps/v8/src/parsing/preparse-data-format.h deleted file mode 100644 index 2f317ce75f..0000000000 --- a/deps/v8/src/parsing/preparse-data-format.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_PARSING_PREPARSE_DATA_FORMAT_H_ -#define V8_PARSING_PREPARSE_DATA_FORMAT_H_ - -namespace v8 { -namespace internal { - -// Generic and general data used by preparse data recorders and readers. - -struct PreparseDataConstants { - public: - // Layout and constants of the preparse data exchange format. - static const unsigned kMagicNumber = 0xBadDead; - static const unsigned kCurrentVersion = 17; - - static const int kMagicOffset = 0; - static const int kVersionOffset = 1; - static const int kFunctionsSizeOffset = 2; - static const int kSizeOffset = 3; - static const int kHeaderSize = 4; - - static const unsigned char kNumberTerminator = 0x80u; -}; - - -} // namespace internal -} // namespace v8. - -#endif // V8_PARSING_PREPARSE_DATA_FORMAT_H_ diff --git a/deps/v8/src/parsing/preparse-data.cc b/deps/v8/src/parsing/preparse-data.cc index f11eb7b21e..e39218111d 100644 --- a/deps/v8/src/parsing/preparse-data.cc +++ b/deps/v8/src/parsing/preparse-data.cc @@ -8,53 +8,10 @@ #include "src/globals.h" #include "src/objects-inl.h" #include "src/parsing/parser.h" -#include "src/parsing/preparse-data-format.h" namespace v8 { namespace internal { -void ParserLogger::LogFunction(int start, int end, int num_parameters, - 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( - FunctionEntry::EncodeFlags(language_mode, uses_super_property)); - function_store_.Add(num_inner_functions); -} - -ParserLogger::ParserLogger() { - preamble_[PreparseDataConstants::kMagicOffset] = - PreparseDataConstants::kMagicNumber; - preamble_[PreparseDataConstants::kVersionOffset] = - PreparseDataConstants::kCurrentVersion; - preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0; - preamble_[PreparseDataConstants::kSizeOffset] = 0; - DCHECK_EQ(4, PreparseDataConstants::kHeaderSize); -#ifdef DEBUG - prev_start_ = -1; -#endif -} - -ScriptData* ParserLogger::GetScriptData() { - int function_size = function_store_.size(); - int total_size = PreparseDataConstants::kHeaderSize + function_size; - unsigned* data = NewArray<unsigned>(total_size); - preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size; - MemCopy(data, preamble_, sizeof(preamble_)); - if (function_size > 0) { - function_store_.WriteTo(Vector<unsigned>( - data + PreparseDataConstants::kHeaderSize, function_size)); - } - DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); - ScriptData* result = new ScriptData(reinterpret_cast<byte*>(data), - total_size * sizeof(unsigned)); - result->AcquireDataOwnership(); - return result; -} - PreParseData::FunctionData PreParseData::GetFunctionData(int start) const { auto it = functions_.find(start); if (it != functions_.end()) { diff --git a/deps/v8/src/parsing/preparse-data.h b/deps/v8/src/parsing/preparse-data.h index b5db652c9c..0e40c76927 100644 --- a/deps/v8/src/parsing/preparse-data.h +++ b/deps/v8/src/parsing/preparse-data.h @@ -11,43 +11,9 @@ #include "src/base/hashmap.h" #include "src/collector.h" #include "src/messages.h" -#include "src/parsing/preparse-data-format.h" - namespace v8 { namespace internal { -class ScriptData { - public: - ScriptData(const byte* data, int length); - ~ScriptData() { - if (owns_data_) DeleteArray(data_); - } - - const byte* data() const { return data_; } - int length() const { return length_; } - bool rejected() const { return rejected_; } - - void Reject() { rejected_ = true; } - - void AcquireDataOwnership() { - DCHECK(!owns_data_); - owns_data_ = true; - } - - void ReleaseDataOwnership() { - DCHECK(owns_data_); - owns_data_ = false; - } - - private: - bool owns_data_ : 1; - bool rejected_ : 1; - const byte* data_; - int length_; - - DISALLOW_COPY_AND_ASSIGN(ScriptData); -}; - class PreParserLogger final { public: PreParserLogger() @@ -74,25 +40,6 @@ class PreParserLogger final { int num_inner_functions_; }; -class ParserLogger final { - public: - ParserLogger(); - - void LogFunction(int start, int end, int num_parameters, - LanguageMode language_mode, bool uses_super_property, - int num_inner_functions); - - ScriptData* GetScriptData(); - - private: - Collector<unsigned> function_store_; - unsigned preamble_[PreparseDataConstants::kHeaderSize]; - -#ifdef DEBUG - int prev_start_; -#endif -}; - class PreParseData final { public: struct FunctionData { diff --git a/deps/v8/src/parsing/preparsed-scope-data.cc b/deps/v8/src/parsing/preparsed-scope-data.cc index 786be3f0e5..70880f55c4 100644 --- a/deps/v8/src/parsing/preparsed-scope-data.cc +++ b/deps/v8/src/parsing/preparsed-scope-data.cc @@ -396,6 +396,7 @@ void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) { // Store the variable name in debug mode; this way we can check that we // restore data to the correct variable. const AstRawString* name = var->raw_name(); + byte_data_->WriteUint8(name->is_one_byte()); byte_data_->WriteUint32(name->length()); for (int i = 0; i < name->length(); ++i) { byte_data_->WriteUint8(name->raw_data()[i]); @@ -571,8 +572,7 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope) { if (scope_data_->RemainingBytes() < kUint8Size) { // Temporary debugging code for detecting inconsistent data. Write debug // information on the stack, then crash. - data_->GetIsolate()->PushStackTraceAndDie(0xC0DEFEE, nullptr, nullptr, - 0xC0DEFEE); + data_->GetIsolate()->PushStackTraceAndDie(); } // scope_type is stored only in debug mode. @@ -606,9 +606,20 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope) { void ConsumedPreParsedScopeData::RestoreDataForVariable(Variable* var) { #ifdef DEBUG const AstRawString* name = var->raw_name(); + bool data_one_byte = scope_data_->ReadUint8(); + DCHECK_IMPLIES(name->is_one_byte(), data_one_byte); DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length())); - for (int i = 0; i < name->length(); ++i) { - DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]); + if (!name->is_one_byte() && data_one_byte) { + // It's possible that "name" is a two-byte representation of the string + // stored in the data. + for (int i = 0; i < 2 * name->length(); i += 2) { + DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]); + DCHECK_EQ(0, name->raw_data()[i + 1]); + } + } else { + for (int i = 0; i < name->length(); ++i) { + DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]); + } } #endif uint8_t variable_data = scope_data_->ReadQuarter(); diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc index b28eab2e75..5bb58a03aa 100644 --- a/deps/v8/src/parsing/preparser.cc +++ b/deps/v8/src/parsing/preparser.cc @@ -11,7 +11,6 @@ #include "src/globals.h" #include "src/parsing/duplicate-finder.h" #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" @@ -50,6 +49,8 @@ PreParserIdentifier GetSymbolHelper(Scanner* scanner) { return PreParserIdentifier::Await(); case Token::ASYNC: return PreParserIdentifier::Async(); + case Token::PRIVATE_NAME: + return PreParserIdentifier::PrivateName(); default: break; } diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h index 705cd011ee..86fa7d1150 100644 --- a/deps/v8/src/parsing/preparser.h +++ b/deps/v8/src/parsing/preparser.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_PARSING_PREPARSER_H -#define V8_PARSING_PREPARSER_H +#ifndef V8_PARSING_PREPARSER_H_ +#define V8_PARSING_PREPARSER_H_ #include "src/ast/ast.h" #include "src/ast/scopes.h" @@ -51,6 +51,9 @@ class PreParserIdentifier { static PreParserIdentifier Name() { return PreParserIdentifier(kNameIdentifier); } + static PreParserIdentifier PrivateName() { + return PreParserIdentifier(kPrivateNameIdentifier); + } bool IsNull() const { return type_ == kNullIdentifier; } bool IsEval() const { return type_ == kEvalIdentifier; } bool IsArguments() const { return type_ == kArgumentsIdentifier; } @@ -58,6 +61,7 @@ class PreParserIdentifier { bool IsConstructor() const { return type_ == kConstructorIdentifier; } bool IsAwait() const { return type_ == kAwaitIdentifier; } bool IsName() const { return type_ == kNameIdentifier; } + bool IsPrivateName() const { return type_ == kPrivateNameIdentifier; } private: enum Type { @@ -68,7 +72,8 @@ class PreParserIdentifier { kConstructorIdentifier, kAwaitIdentifier, kAsyncIdentifier, - kNameIdentifier + kNameIdentifier, + kPrivateNameIdentifier }; explicit PreParserIdentifier(Type type) : type_(type), string_(nullptr) {} @@ -169,6 +174,12 @@ class PreParserExpression { variables); } + static PreParserExpression ThisPropertyWithPrivateFieldKey() { + return PreParserExpression(TypeField::encode(kExpression) | + ExpressionTypeField::encode( + kThisPropertyExpressionWithPrivateFieldKey)); + } + static PreParserExpression ThisProperty() { return PreParserExpression( TypeField::encode(kExpression) | @@ -181,6 +192,12 @@ class PreParserExpression { ExpressionTypeField::encode(kPropertyExpression)); } + static PreParserExpression PropertyWithPrivateFieldKey() { + return PreParserExpression( + TypeField::encode(kExpression) | + ExpressionTypeField::encode(kPropertyExpressionWithPrivateFieldKey)); + } + static PreParserExpression Call() { return PreParserExpression(TypeField::encode(kExpression) | ExpressionTypeField::encode(kCallExpression)); @@ -254,13 +271,27 @@ class PreParserExpression { bool IsThisProperty() const { return TypeField::decode(code_) == kExpression && - ExpressionTypeField::decode(code_) == kThisPropertyExpression; + (ExpressionTypeField::decode(code_) == kThisPropertyExpression || + ExpressionTypeField::decode(code_) == + kThisPropertyExpressionWithPrivateFieldKey); } bool IsProperty() const { return TypeField::decode(code_) == kExpression && (ExpressionTypeField::decode(code_) == kPropertyExpression || - ExpressionTypeField::decode(code_) == kThisPropertyExpression); + ExpressionTypeField::decode(code_) == kThisPropertyExpression || + ExpressionTypeField::decode(code_) == + kPropertyExpressionWithPrivateFieldKey || + ExpressionTypeField::decode(code_) == + kThisPropertyExpressionWithPrivateFieldKey); + } + + bool IsPropertyWithPrivateFieldKey() const { + return TypeField::decode(code_) == kExpression && + (ExpressionTypeField::decode(code_) == + kPropertyExpressionWithPrivateFieldKey || + ExpressionTypeField::decode(code_) == + kThisPropertyExpressionWithPrivateFieldKey); } bool IsCall() const { @@ -298,12 +329,22 @@ class PreParserExpression { // and PreParser. PreParserExpression* operator->() { return this; } + void set_is_private_field() { + if (variables_ != nullptr) { + DCHECK(IsIdentifier()); + DCHECK(AsIdentifier().IsPrivateName()); + DCHECK_EQ(1, variables_->length()); + variables_->first()->set_is_private_field(); + } + } + // More dummy implementations of things PreParser doesn't need to track: void SetShouldEagerCompile() {} int position() const { return kNoSourcePosition; } void set_function_token_position(int position) {} void set_scope(Scope* scope) {} + void set_suspend_count(int suspend_count) {} private: enum Type { @@ -319,7 +360,9 @@ class PreParserExpression { enum ExpressionType { kThisExpression, kThisPropertyExpression, + kThisPropertyExpressionWithPrivateFieldKey, kPropertyExpression, + kPropertyExpressionWithPrivateFieldKey, kCallExpression, kCallEvalExpression, kCallTaggedTemplateExpression, @@ -580,8 +623,16 @@ class PreParserFactory { PreParserExpression NewVariableProxy(void* variable) { return PreParserExpression::Default(); } + PreParserExpression NewProperty(const PreParserExpression& obj, const PreParserExpression& key, int pos) { + if (key.IsIdentifier() && key.AsIdentifier().IsPrivateName()) { + if (obj.IsThis()) { + return PreParserExpression::ThisPropertyWithPrivateFieldKey(); + } + return PreParserExpression::PropertyWithPrivateFieldKey(); + } + if (obj.IsThis()) { return PreParserExpression::ThisProperty(); } @@ -984,6 +1035,10 @@ class PreParser : public ParserBase<PreParser> { TemplateLiteralState* state, int start, const PreParserExpression& tag) { return PreParserExpression::Default(); } + V8_INLINE bool IsPropertyWithPrivateFieldKey( + const PreParserExpression& expression) { + return expression.IsPropertyWithPrivateFieldKey(); + } V8_INLINE void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {} V8_INLINE void SetLanguageMode(Scope* scope, LanguageMode mode) { @@ -1142,16 +1197,23 @@ class PreParser : public ParserBase<PreParser> { } V8_INLINE void DeclareClassProperty(const PreParserIdentifier& class_name, const PreParserExpression& property, + const PreParserIdentifier& property_name, ClassLiteralProperty::Kind kind, bool is_static, bool is_constructor, bool is_computed_name, ClassInfo* class_info, bool* ok) { - if (kind == ClassLiteralProperty::FIELD && is_computed_name) { + if (kind == ClassLiteralProperty::PUBLIC_FIELD && is_computed_name) { scope()->DeclareVariableName( ClassFieldVariableName(ast_value_factory(), class_info->computed_field_count), CONST); } + + if (kind == ClassLiteralProperty::PRIVATE_FIELD && + property_name.string_ != nullptr) { + DCHECK(track_unresolved_variables_); + scope()->DeclareVariableName(property_name.string_, CONST); + } } V8_INLINE PreParserExpression @@ -1528,10 +1590,6 @@ class PreParser : public ParserBase<PreParser> { return PreParserExpression::NewTargetExpression(); } - V8_INLINE PreParserExpression FunctionSentExpression(int pos) { - return PreParserExpression::Default(); - } - V8_INLINE PreParserExpression ImportMetaExpression(int pos) { return PreParserExpression::Default(); } @@ -1707,4 +1765,4 @@ PreParserExpression PreParser::SpreadCallNew( } // namespace internal } // namespace v8 -#endif // V8_PARSING_PREPARSER_H +#endif // V8_PARSING_PREPARSER_H_ diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc index 3152ab184e..a6dd075fec 100644 --- a/deps/v8/src/parsing/scanner.cc +++ b/deps/v8/src/parsing/scanner.cc @@ -1071,8 +1071,11 @@ Token::Value Scanner::ScanString() { AddLiteralChar(c); } - while (c0_ != quote && c0_ != kEndOfInput && - !unibrow::IsLineTerminator(c0_)) { + bool (*line_terminator_func)(unsigned int) = + FLAG_harmony_subsume_json ? unibrow::IsStringLiteralLineTerminator + : unibrow::IsLineTerminator; + + while (c0_ != quote && c0_ != kEndOfInput && !line_terminator_func(c0_)) { uc32 c = c0_; Advance(); if (c == '\\') { @@ -1225,6 +1228,56 @@ void Scanner::ScanDecimalDigits() { AddLiteralCharAdvance(); } +bool Scanner::ScanBinaryDigits() { + // we must have at least one binary digit after 'b'/'B' + if (!IsBinaryDigit(c0_)) return false; + while (IsBinaryDigit(c0_)) { + AddLiteralCharAdvance(); + } + return true; +} + +bool Scanner::ScanOctalDigits() { + // we must have at least one octal digit after 'o'/'O' + if (!IsOctalDigit(c0_)) return false; + while (IsOctalDigit(c0_)) { + AddLiteralCharAdvance(); + } + + return true; +} + +bool Scanner::ScanImplicitOctalDigits(int start_pos) { + // (possible) octal number + while (true) { + if (c0_ == '8' || c0_ == '9') return false; + if (c0_ < '0' || '7' < c0_) { + // Octal literal finished. + octal_pos_ = Location(start_pos, source_pos()); + octal_message_ = MessageTemplate::kStrictOctalLiteral; + break; + } + AddLiteralCharAdvance(); + } + return true; +} + +bool Scanner::ScanHexDigits() { + // we must have at least one hex digit after 'x'/'X' + if (!IsHexDigit(c0_)) return false; + while (IsHexDigit(c0_)) { + AddLiteralCharAdvance(); + } + return true; +} + +bool Scanner::ScanSignedInteger() { + if (c0_ == '+' || c0_ == '-') AddLiteralCharAdvance(); + // we must have at least one decimal digit after 'e'/'E' + if (!IsDecimalDigit(c0_)) return false; + ScanDecimalDigits(); + return true; +} Token::Value Scanner::ScanNumber(bool seen_period) { DCHECK(IsDecimalDigit(c0_)); // the first digit of the number or the fraction @@ -1254,52 +1307,22 @@ Token::Value Scanner::ScanNumber(bool seen_period) { // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or // an octal number. if (c0_ == 'x' || c0_ == 'X') { - // hex number - kind = HEX; AddLiteralCharAdvance(); - if (!IsHexDigit(c0_)) { - // we must have at least one hex digit after 'x'/'X' - return Token::ILLEGAL; - } - while (IsHexDigit(c0_)) { - AddLiteralCharAdvance(); - } + kind = HEX; + if (!ScanHexDigits()) return Token::ILLEGAL; } else if (c0_ == 'o' || c0_ == 'O') { - kind = OCTAL; AddLiteralCharAdvance(); - if (!IsOctalDigit(c0_)) { - // we must have at least one octal digit after 'o'/'O' - return Token::ILLEGAL; - } - while (IsOctalDigit(c0_)) { - AddLiteralCharAdvance(); - } + kind = OCTAL; + if (!ScanOctalDigits()) return Token::ILLEGAL; } else if (c0_ == 'b' || c0_ == 'B') { - kind = BINARY; AddLiteralCharAdvance(); - if (!IsBinaryDigit(c0_)) { - // we must have at least one binary digit after 'b'/'B' - return Token::ILLEGAL; - } - while (IsBinaryDigit(c0_)) { - AddLiteralCharAdvance(); - } + kind = BINARY; + if (!ScanBinaryDigits()) return Token::ILLEGAL; } else if ('0' <= c0_ && c0_ <= '7') { - // (possible) octal number kind = IMPLICIT_OCTAL; - while (true) { - if (c0_ == '8' || c0_ == '9') { - at_start = false; - kind = DECIMAL_WITH_LEADING_ZERO; - break; - } - if (c0_ < '0' || '7' < c0_) { - // Octal literal finished. - octal_pos_ = Location(start_pos, source_pos()); - octal_message_ = MessageTemplate::kStrictOctalLiteral; - break; - } - AddLiteralCharAdvance(); + if (!ScanImplicitOctalDigits(start_pos)) { + kind = DECIMAL_WITH_LEADING_ZERO; + at_start = false; } } else if (c0_ == '8' || c0_ == '9') { kind = DECIMAL_WITH_LEADING_ZERO; @@ -1308,6 +1331,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) { // Parse decimal digits and allow trailing fractional part. if (kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO) { + // This is an optimization for parsing Decimal numbers as Smi's. if (at_start) { uint64_t value = 0; while (IsDecimalDigit(c0_)) { @@ -1362,17 +1386,14 @@ Token::Value Scanner::ScanNumber(bool seen_period) { } else if (c0_ == 'e' || c0_ == 'E') { // scan exponent, if any DCHECK(kind != HEX); // 'e'/'E' must be scanned as part of the hex number + if (!(kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO)) return Token::ILLEGAL; + // scan exponent AddLiteralCharAdvance(); - if (c0_ == '+' || c0_ == '-') - AddLiteralCharAdvance(); - if (!IsDecimalDigit(c0_)) { - // we must have at least one decimal digit after 'e'/'E' - return Token::ILLEGAL; - } - ScanDecimalDigits(); + + if (!ScanSignedInteger()) return Token::ILLEGAL; } // The source character immediately following a numeric literal must @@ -1487,7 +1508,6 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD_GROUP('r') \ KEYWORD("return", Token::RETURN) \ KEYWORD_GROUP('s') \ - KEYWORD("sent", Token::SENT) \ KEYWORD("set", Token::SET) \ KEYWORD("static", Token::STATIC) \ KEYWORD("super", Token::SUPER) \ @@ -1510,13 +1530,15 @@ uc32 Scanner::ScanUnicodeEscape() { KEYWORD_GROUP('y') \ KEYWORD("yield", Token::YIELD) \ KEYWORD_GROUP('_') \ - KEYWORD("__proto__", Token::PROTO_UNDERSCORED) + KEYWORD("__proto__", Token::PROTO_UNDERSCORED) \ + KEYWORD_GROUP('#') \ + KEYWORD("#constructor", Token::PRIVATE_CONSTRUCTOR) static Token::Value KeywordOrIdentifierToken(const uint8_t* input, int input_length) { DCHECK_GE(input_length, 1); const int kMinLength = 2; - const int kMaxLength = 11; + const int kMaxLength = 12; if (input_length < kMinLength || input_length > kMaxLength) { return Token::IDENTIFIER; } @@ -1551,6 +1573,9 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input, KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD) } return Token::IDENTIFIER; +#undef KEYWORDS +#undef KEYWORD +#undef KEYWORD_GROUP_CASE } Token::Value Scanner::ScanIdentifierOrKeyword() { diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h index f5106990ff..fe7d754319 100644 --- a/deps/v8/src/parsing/scanner.h +++ b/deps/v8/src/parsing/scanner.h @@ -721,6 +721,12 @@ class Scanner { Token::Value ScanHtmlComment(); void ScanDecimalDigits(); + bool ScanHexDigits(); + bool ScanBinaryDigits(); + bool ScanSignedInteger(); + bool ScanOctalDigits(); + bool ScanImplicitOctalDigits(int start_pos); + Token::Value ScanNumber(bool seen_period); Token::Value ScanIdentifierOrKeyword(); Token::Value ScanIdentifierOrKeywordInner(LiteralScope* literal); diff --git a/deps/v8/src/parsing/token.h b/deps/v8/src/parsing/token.h index 07974edf41..660f24361c 100644 --- a/deps/v8/src/parsing/token.h +++ b/deps/v8/src/parsing/token.h @@ -188,13 +188,13 @@ namespace internal { C(SET, "set", 0) \ C(OF, "of", 0) \ C(TARGET, "target", 0) \ - C(SENT, "sent", 0) \ C(META, "meta", 0) \ C(AS, "as", 0) \ C(FROM, "from", 0) \ C(NAME, "name", 0) \ C(PROTO_UNDERSCORED, "__proto__", 0) \ C(CONSTRUCTOR, "constructor", 0) \ + C(PRIVATE_CONSTRUCTOR, "#constructor", 0) \ C(PROTOTYPE, "prototype", 0) \ C(EVAL, "eval", 0) \ C(ARGUMENTS, "arguments", 0) \ |