summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing
diff options
context:
space:
mode:
authorMichaƫl Zasso <targos@protonmail.com>2018-01-24 20:16:06 +0100
committerMyles Borins <mylesborins@google.com>2018-01-24 15:02:20 -0800
commit4c4af643e5042d615a60c6bbc05aee9d81b903e5 (patch)
tree3fb0a97988fe4439ae3ae06f26915d1dcf8cab92 /deps/v8/src/parsing
parentfa9f31a4fda5a3782c652e56e394465805ebb50f (diff)
downloadnode-new-4c4af643e5042d615a60c6bbc05aee9d81b903e5.tar.gz
deps: update V8 to 6.4.388.40
PR-URL: https://github.com/nodejs/node/pull/17489 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r--deps/v8/src/parsing/background-parsing-task.cc111
-rw-r--r--deps/v8/src/parsing/background-parsing-task.h74
-rw-r--r--deps/v8/src/parsing/expression-classifier.h2
-rw-r--r--deps/v8/src/parsing/expression-scope-reparenter.cc12
-rw-r--r--deps/v8/src/parsing/func-name-inferrer.cc2
-rw-r--r--deps/v8/src/parsing/parse-info.cc29
-rw-r--r--deps/v8/src/parsing/parse-info.h32
-rw-r--r--deps/v8/src/parsing/parser-base.h402
-rw-r--r--deps/v8/src/parsing/parser.cc578
-rw-r--r--deps/v8/src/parsing/parser.h163
-rw-r--r--deps/v8/src/parsing/parsing.cc6
-rw-r--r--deps/v8/src/parsing/pattern-rewriter.cc10
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.cc98
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.h18
-rw-r--r--deps/v8/src/parsing/preparser.cc42
-rw-r--r--deps/v8/src/parsing/preparser.h155
-rw-r--r--deps/v8/src/parsing/rewriter.cc11
-rw-r--r--deps/v8/src/parsing/scanner-character-streams.cc8
-rw-r--r--deps/v8/src/parsing/scanner.cc59
-rw-r--r--deps/v8/src/parsing/scanner.h30
-rw-r--r--deps/v8/src/parsing/token.h397
21 files changed, 1331 insertions, 908 deletions
diff --git a/deps/v8/src/parsing/background-parsing-task.cc b/deps/v8/src/parsing/background-parsing-task.cc
new file mode 100644
index 0000000000..387cd3a1c6
--- /dev/null
+++ b/deps/v8/src/parsing/background-parsing-task.cc
@@ -0,0 +1,111 @@
+// 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);
+
+ 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
new file mode 100644
index 0000000000..eb3ed61e2e
--- /dev/null
+++ b/deps/v8/src/parsing/background-parsing-task.h
@@ -0,0 +1,74 @@
+// 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 d2dc6fa170..6c6c813b3e 100644
--- a/deps/v8/src/parsing/expression-classifier.h
+++ b/deps/v8/src/parsing/expression-classifier.h
@@ -424,7 +424,7 @@ class ExpressionClassifier {
typename Types::Base* base_;
ExpressionClassifier* previous_;
Zone* zone_;
- ZoneList<typename Types::Expression>* non_patterns_to_rewrite_;
+ ZoneList<typename Types::RewritableExpression>* non_patterns_to_rewrite_;
ZoneList<Error>* reported_errors_;
DuplicateFinder* duplicate_finder_;
// The uint16_t for non_pattern_begin_ will not be enough in the case,
diff --git a/deps/v8/src/parsing/expression-scope-reparenter.cc b/deps/v8/src/parsing/expression-scope-reparenter.cc
index 6ca29611c1..18c52add11 100644
--- a/deps/v8/src/parsing/expression-scope-reparenter.cc
+++ b/deps/v8/src/parsing/expression-scope-reparenter.cc
@@ -27,6 +27,7 @@ class Reparenter final : public AstTraversalVisitor<Reparenter> {
void VisitFunctionLiteral(FunctionLiteral* expr);
void VisitClassLiteral(ClassLiteral* expr);
void VisitVariableProxy(VariableProxy* expr);
+ void VisitRewritableExpression(RewritableExpression* expr);
void VisitBlock(Block* stmt);
void VisitTryCatchStatement(TryCatchStatement* stmt);
@@ -45,6 +46,12 @@ void Reparenter::VisitClassLiteral(ClassLiteral* class_literal) {
// scope on its scope chain.
DCHECK_EQ(class_literal->constructor()->scope()->outer_scope(),
class_literal->scope());
+
+ if (class_literal->static_fields_initializer() != nullptr) {
+ DCHECK_EQ(
+ class_literal->static_fields_initializer()->scope()->outer_scope(),
+ class_literal->scope());
+ }
#if DEBUG
// The same goes for the rest of the class, but we do some
// sanity checking in debug mode.
@@ -72,6 +79,11 @@ void Reparenter::VisitVariableProxy(VariableProxy* proxy) {
}
}
+void Reparenter::VisitRewritableExpression(RewritableExpression* expr) {
+ Visit(expr->expression());
+ expr->set_scope(scope_);
+}
+
void Reparenter::VisitBlock(Block* stmt) {
if (stmt->scope() != nullptr)
stmt->scope()->ReplaceOuterScope(scope_);
diff --git a/deps/v8/src/parsing/func-name-inferrer.cc b/deps/v8/src/parsing/func-name-inferrer.cc
index a6cc179b82..b55c5ddd5d 100644
--- a/deps/v8/src/parsing/func-name-inferrer.cc
+++ b/deps/v8/src/parsing/func-name-inferrer.cc
@@ -46,7 +46,7 @@ void FuncNameInferrer::PushVariableName(const AstRawString* name) {
void FuncNameInferrer::RemoveAsyncKeywordFromEnd() {
if (IsOpen()) {
- CHECK(names_stack_.length() > 0);
+ CHECK_GT(names_stack_.length(), 0);
CHECK(names_stack_.last().name->IsOneByteEqualTo("async"));
names_stack_.RemoveLast();
}
diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc
index f17916ccb6..1c9d648a1e 100644
--- a/deps/v8/src/parsing/parse-info.cc
+++ b/deps/v8/src/parsing/parse-info.cc
@@ -53,13 +53,16 @@ ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared)
set_end_position(shared->end_position());
function_literal_id_ = shared->function_literal_id();
set_language_mode(shared->language_mode());
- set_module(shared->kind() == FunctionKind::kModule);
set_asm_wasm_broken(shared->is_asm_wasm_broken());
+ set_requires_instance_fields_initializer(
+ shared->requires_instance_fields_initializer());
Handle<Script> script(Script::cast(shared->script()));
set_script(script);
set_native(script->type() == Script::TYPE_NATIVE);
set_eval(script->compilation_type() == Script::COMPILATION_TYPE_EVAL);
+ set_module(script->origin_options().IsModule());
+ DCHECK(!(is_eval() && is_module()));
Handle<HeapObject> scope_info(shared->outer_scope_info());
if (!scope_info->IsTheHole(isolate) &&
@@ -90,6 +93,8 @@ ParseInfo::ParseInfo(Handle<Script> script)
set_native(script->type() == Script::TYPE_NATIVE);
set_eval(script->compilation_type() == Script::COMPILATION_TYPE_EVAL);
+ set_module(script->origin_options().IsModule());
+ DCHECK(!(is_eval() && is_module()));
set_collect_type_profile(script->GetIsolate()->is_collecting_type_profile() &&
script->IsUserJavaScript());
@@ -114,7 +119,6 @@ ParseInfo* ParseInfo::AllocateWithoutScript(Handle<SharedFunctionInfo> shared) {
p->set_end_position(shared->end_position());
p->function_literal_id_ = shared->function_literal_id();
p->set_language_mode(shared->language_mode());
- p->set_module(shared->kind() == FunctionKind::kModule);
// BUG(5946): This function exists as a workaround until we can
// get rid of %SetCode in our native functions. The ParseInfo
@@ -126,6 +130,8 @@ ParseInfo* ParseInfo::AllocateWithoutScript(Handle<SharedFunctionInfo> shared) {
// We tolerate a ParseInfo without a Script in this case.
p->set_native(true);
p->set_eval(false);
+ p->set_module(false);
+ DCHECK_NE(shared->kind(), FunctionKind::kModule);
Handle<HeapObject> scope_info(shared->outer_scope_info());
if (!scope_info->IsTheHole(isolate) &&
@@ -151,12 +157,27 @@ void ParseInfo::InitFromIsolate(Isolate* isolate) {
set_stack_limit(isolate->stack_guard()->real_climit());
set_unicode_cache(isolate->unicode_cache());
set_runtime_call_stats(isolate->counters()->runtime_call_stats());
+ set_logger(isolate->logger());
set_ast_string_constants(isolate->ast_string_constants());
if (isolate->is_block_code_coverage()) set_block_coverage_enabled();
if (isolate->is_collecting_type_profile()) set_collect_type_profile();
}
-void ParseInfo::UpdateStatisticsAfterBackgroundParse(Isolate* isolate) {
+void ParseInfo::EmitBackgroundParseStatisticsOnBackgroundThread() {
+ // If runtime call stats was enabled by tracing, emit a trace event at the
+ // end of background parsing on the background thread.
+ if (runtime_call_stats_ &&
+ (FLAG_runtime_stats &
+ v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
+ auto value = v8::tracing::TracedValue::Create();
+ runtime_call_stats_->Dump(value.get());
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats"),
+ "V8.RuntimeStats", TRACE_EVENT_SCOPE_THREAD,
+ "runtime-call-stats", std::move(value));
+ }
+}
+
+void ParseInfo::UpdateBackgroundParseStatisticsOnMainThread(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();
@@ -197,7 +218,7 @@ void ParseInfo::ResetCharacterStream() { character_stream_.reset(); }
void ParseInfo::set_character_stream(
std::unique_ptr<Utf16CharacterStream> character_stream) {
- DCHECK(character_stream_.get() == nullptr);
+ DCHECK_NULL(character_stream_);
character_stream_.swap(character_stream);
}
diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h
index 1426f94bbf..9deea1ecac 100644
--- a/deps/v8/src/parsing/parse-info.h
+++ b/deps/v8/src/parsing/parse-info.h
@@ -13,6 +13,7 @@
#include "src/globals.h"
#include "src/handles.h"
#include "src/parsing/preparsed-scope-data.h"
+#include "src/pending-compilation-error-handler.h"
namespace v8 {
@@ -27,6 +28,7 @@ class AstValueFactory;
class DeclarationScope;
class FunctionLiteral;
class RuntimeCallStats;
+class Logger;
class ScriptData;
class SourceRangeMap;
class UnicodeCache;
@@ -73,13 +75,17 @@ class V8_EXPORT_PRIVATE ParseInfo {
FLAG_ACCESSOR(kAllowLazyParsing, allow_lazy_parsing, set_allow_lazy_parsing)
FLAG_ACCESSOR(kIsNamedExpression, is_named_expression,
set_is_named_expression)
- FLAG_ACCESSOR(kSerializing, will_serialize, set_will_serialize)
FLAG_ACCESSOR(kLazyCompile, lazy_compile, set_lazy_compile)
FLAG_ACCESSOR(kCollectTypeProfile, collect_type_profile,
set_collect_type_profile)
FLAG_ACCESSOR(kIsAsmWasmBroken, is_asm_wasm_broken, set_asm_wasm_broken)
+ FLAG_ACCESSOR(kRequiresInstanceFieldsInitializer,
+ requires_instance_fields_initializer,
+ set_requires_instance_fields_initializer)
FLAG_ACCESSOR(kBlockCoverageEnabled, block_coverage_enabled,
set_block_coverage_enabled)
+ FLAG_ACCESSOR(kOnBackgroundThread, on_background_thread,
+ set_on_background_thread)
#undef FLAG_ACCESSOR
void set_parse_restriction(ParseRestriction restriction) {
@@ -186,6 +192,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
void set_runtime_call_stats(RuntimeCallStats* runtime_call_stats) {
runtime_call_stats_ = runtime_call_stats;
}
+ Logger* logger() const { return logger_; }
+ void set_logger(Logger* logger) { logger_ = logger; }
void AllocateSourceRangeMap();
SourceRangeMap* source_range_map() const { return source_range_map_; }
@@ -193,6 +201,10 @@ class V8_EXPORT_PRIVATE ParseInfo {
source_range_map_ = source_range_map;
}
+ PendingCompilationErrorHandler* pending_error_handler() {
+ return &pending_error_handler_;
+ }
+
// Getters for individual compiler hints.
bool is_declaration() const;
FunctionKind function_kind() const;
@@ -215,7 +227,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
return construct_language_mode(is_strict_mode());
}
void set_language_mode(LanguageMode language_mode) {
- STATIC_ASSERT(LANGUAGE_END == 2);
+ STATIC_ASSERT(LanguageModeSize == 2);
set_strict_mode(is_strict(language_mode));
}
@@ -229,7 +241,8 @@ class V8_EXPORT_PRIVATE ParseInfo {
}
}
- void UpdateStatisticsAfterBackgroundParse(Isolate* isolate);
+ void EmitBackgroundParseStatisticsOnBackgroundThread();
+ void UpdateBackgroundParseStatisticsOnMainThread(Isolate* isolate);
private:
// Various configuration flags for parsing.
@@ -244,11 +257,12 @@ class V8_EXPORT_PRIVATE ParseInfo {
kModule = 1 << 6,
kAllowLazyParsing = 1 << 7,
kIsNamedExpression = 1 << 8,
- kSerializing = 1 << 9,
- kLazyCompile = 1 << 10,
- kCollectTypeProfile = 1 << 11,
- kBlockCoverageEnabled = 1 << 12,
- kIsAsmWasmBroken = 1 << 13,
+ kLazyCompile = 1 << 9,
+ kCollectTypeProfile = 1 << 10,
+ kBlockCoverageEnabled = 1 << 11,
+ kIsAsmWasmBroken = 1 << 12,
+ kRequiresInstanceFieldsInitializer = 1 << 13,
+ kOnBackgroundThread = 1 << 14,
};
//------------- Inputs to parsing and scope analysis -----------------------
@@ -279,11 +293,13 @@ class V8_EXPORT_PRIVATE ParseInfo {
const class AstStringConstants* ast_string_constants_;
const AstRawString* function_name_;
RuntimeCallStats* runtime_call_stats_;
+ Logger* logger_;
SourceRangeMap* source_range_map_; // Used when block coverage is enabled.
//----------- Output of parsing and scope analysis ------------------------
FunctionLiteral* literal_;
std::shared_ptr<DeferredHandles> deferred_handles_;
+ PendingCompilationErrorHandler pending_error_handler_;
void SetFlag(Flag f) { flags_ |= f; }
void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index b211b85d2a..c393bc5ec2 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -14,6 +14,7 @@
#include "src/base/hashmap.h"
#include "src/counters.h"
#include "src/globals.h"
+#include "src/log.h"
#include "src/messages.h"
#include "src/parsing/expression-classifier.h"
#include "src/parsing/func-name-inferrer.h"
@@ -236,6 +237,7 @@ class ParserBase {
typedef typename Types::ObjectLiteralProperty ObjectLiteralPropertyT;
typedef typename Types::ClassLiteralProperty ClassLiteralPropertyT;
typedef typename Types::Suspend SuspendExpressionT;
+ typedef typename Types::RewritableExpression RewritableExpressionT;
typedef typename Types::ExpressionList ExpressionListT;
typedef typename Types::FormalParameters FormalParametersT;
typedef typename Types::Statement StatementT;
@@ -251,8 +253,9 @@ class ParserBase {
ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
v8::Extension* extension, AstValueFactory* ast_value_factory,
- RuntimeCallStats* runtime_call_stats,
- bool parsing_on_main_thread = true)
+ PendingCompilationErrorHandler* pending_error_handler,
+ RuntimeCallStats* runtime_call_stats, Logger* logger,
+ int script_id, bool parsing_module, bool parsing_on_main_thread)
: scope_(nullptr),
original_scope_(nullptr),
function_state_(nullptr),
@@ -261,25 +264,24 @@ class ParserBase {
ast_value_factory_(ast_value_factory),
ast_node_factory_(ast_value_factory, zone),
runtime_call_stats_(runtime_call_stats),
+ logger_(logger),
parsing_on_main_thread_(parsing_on_main_thread),
- parsing_module_(false),
+ parsing_module_(parsing_module),
stack_limit_(stack_limit),
+ pending_error_handler_(pending_error_handler),
zone_(zone),
classifier_(nullptr),
scanner_(scanner),
- stack_overflow_(false),
default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile),
function_literal_id_(0),
+ script_id_(script_id),
allow_natives_(false),
allow_harmony_do_expressions_(false),
allow_harmony_function_sent_(false),
- allow_harmony_restrictive_generators_(false),
- allow_harmony_class_fields_(false),
- allow_harmony_object_rest_spread_(false),
+ allow_harmony_public_fields_(false),
allow_harmony_dynamic_import_(false),
allow_harmony_import_meta_(false),
- allow_harmony_async_iteration_(false),
- allow_harmony_template_escapes_(false) {}
+ allow_harmony_async_iteration_(false) {}
#define ALLOW_ACCESSORS(name) \
bool allow_##name() const { return allow_##name##_; } \
@@ -288,16 +290,20 @@ class ParserBase {
ALLOW_ACCESSORS(natives);
ALLOW_ACCESSORS(harmony_do_expressions);
ALLOW_ACCESSORS(harmony_function_sent);
- ALLOW_ACCESSORS(harmony_restrictive_generators);
- ALLOW_ACCESSORS(harmony_class_fields);
- ALLOW_ACCESSORS(harmony_object_rest_spread);
+ ALLOW_ACCESSORS(harmony_public_fields);
ALLOW_ACCESSORS(harmony_dynamic_import);
ALLOW_ACCESSORS(harmony_import_meta);
ALLOW_ACCESSORS(harmony_async_iteration);
- ALLOW_ACCESSORS(harmony_template_escapes);
#undef ALLOW_ACCESSORS
+ bool allow_harmony_bigint() const {
+ return scanner()->allow_harmony_bigint();
+ }
+ void set_allow_harmony_bigint(bool allow) {
+ scanner()->set_allow_harmony_bigint(allow);
+ }
+
uintptr_t stack_limit() const { return stack_limit_; }
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
@@ -366,15 +372,6 @@ class ParserBase {
Scope* const outer_scope_;
};
- struct DestructuringAssignment {
- public:
- DestructuringAssignment(ExpressionT expression, Scope* scope)
- : assignment(expression), scope(scope) {}
-
- ExpressionT assignment;
- Scope* scope;
- };
-
class FunctionState final : public BlockState {
public:
FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
@@ -396,12 +393,12 @@ class ParserBase {
void SetDestructuringAssignmentsScope(int pos, Scope* scope) {
for (int i = pos; i < destructuring_assignments_to_rewrite_.length();
++i) {
- destructuring_assignments_to_rewrite_[i].scope = scope;
+ destructuring_assignments_to_rewrite_[i]->set_scope(scope);
}
}
- const ZoneList<DestructuringAssignment>&
- destructuring_assignments_to_rewrite() const {
+ const ZoneList<RewritableExpressionT>&
+ destructuring_assignments_to_rewrite() const {
return destructuring_assignments_to_rewrite_;
}
@@ -409,7 +406,7 @@ class ParserBase {
return &reported_errors_;
}
- ZoneList<ExpressionT>* non_patterns_to_rewrite() {
+ ZoneList<RewritableExpressionT>* non_patterns_to_rewrite() {
return &non_patterns_to_rewrite_;
}
@@ -450,15 +447,16 @@ class ParserBase {
};
private:
- void AddDestructuringAssignment(DestructuringAssignment pair) {
- destructuring_assignments_to_rewrite_.Add(pair, scope_->zone());
+ void AddDestructuringAssignment(RewritableExpressionT expr) {
+ destructuring_assignments_to_rewrite_.Add(expr, scope_->zone());
}
- void AddNonPatternForRewriting(ExpressionT expr, bool* ok) {
+ void AddNonPatternForRewriting(RewritableExpressionT expr, bool* ok) {
non_patterns_to_rewrite_.Add(expr, scope_->zone());
if (non_patterns_to_rewrite_.length() >=
- std::numeric_limits<uint16_t>::max())
+ std::numeric_limits<uint16_t>::max()) {
*ok = false;
+ }
}
// Properties count estimation.
@@ -468,8 +466,8 @@ class ParserBase {
FunctionState* outer_function_state_;
DeclarationScope* scope_;
- ZoneList<DestructuringAssignment> destructuring_assignments_to_rewrite_;
- ZoneList<ExpressionT> non_patterns_to_rewrite_;
+ ZoneList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
+ ZoneList<RewritableExpressionT> non_patterns_to_rewrite_;
ZoneList<typename ExpressionClassifier::Error> reported_errors_;
@@ -556,21 +554,43 @@ class ParserBase {
: variable(nullptr),
extends(parser->impl()->NullExpression()),
properties(parser->impl()->NewClassPropertyList(4)),
+ static_fields(parser->impl()->NewClassPropertyList(4)),
+ instance_fields(parser->impl()->NewClassPropertyList(4)),
constructor(parser->impl()->NullExpression()),
has_seen_constructor(false),
has_name_static_property(false),
has_static_computed_names(false),
- is_anonymous(false) {}
+ has_static_class_fields(false),
+ has_instance_class_fields(false),
+ is_anonymous(false),
+ static_fields_scope(nullptr),
+ instance_fields_scope(nullptr),
+ computed_field_count(0) {}
Variable* variable;
ExpressionT extends;
typename Types::ClassPropertyList properties;
+ typename Types::ClassPropertyList static_fields;
+ typename Types::ClassPropertyList instance_fields;
FunctionLiteralT constructor;
+
+ // TODO(gsathya): Use a bitfield store all the booleans.
bool has_seen_constructor;
bool has_name_static_property;
bool has_static_computed_names;
+ bool has_static_class_fields;
+ bool has_instance_class_fields;
bool is_anonymous;
+ DeclarationScope* static_fields_scope;
+ DeclarationScope* instance_fields_scope;
+ int computed_field_count;
};
+ const AstRawString* ClassFieldVariableName(AstValueFactory* ast_value_factory,
+ int index) {
+ std::string name = ".class-field-" + std::to_string(index);
+ return ast_value_factory->GetOneByteString(name.c_str());
+ }
+
DeclarationScope* NewScriptScope() const {
return new (zone()) DeclarationScope(zone(), ast_value_factory());
}
@@ -635,11 +655,15 @@ class ParserBase {
AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
int position() const { return scanner_->location().beg_pos; }
int peek_position() const { return scanner_->peek_location().beg_pos; }
- bool stack_overflow() const { return stack_overflow_; }
- void set_stack_overflow() { stack_overflow_ = true; }
+ bool stack_overflow() const {
+ return pending_error_handler()->stack_overflow();
+ }
+ void set_stack_overflow() { pending_error_handler()->set_stack_overflow(); }
+ int script_id() { return script_id_; }
+ void set_script_id(int id) { script_id_ = id; }
INLINE(Token::Value peek()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ if (stack_overflow()) return Token::ILLEGAL;
return scanner()->peek();
}
@@ -651,18 +675,18 @@ class ParserBase {
}
INLINE(Token::Value PeekAhead()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ if (stack_overflow()) return Token::ILLEGAL;
return scanner()->PeekAhead();
}
INLINE(Token::Value Next()) {
- if (stack_overflow_) return Token::ILLEGAL;
+ if (stack_overflow()) return Token::ILLEGAL;
{
if (GetCurrentStackPosition() < stack_limit_) {
// Any further calls to Next or peek will return the illegal token.
// The current call must return the next token, which might already
// have been peek'ed.
- stack_overflow_ = true;
+ set_stack_overflow();
}
}
return scanner()->Next();
@@ -874,6 +898,13 @@ class ParserBase {
return IsResumableFunction(function_state_->kind());
}
+ const PendingCompilationErrorHandler* pending_error_handler() const {
+ return pending_error_handler_;
+ }
+ PendingCompilationErrorHandler* pending_error_handler() {
+ return pending_error_handler_;
+ }
+
// Report syntax errors.
void ReportMessage(MessageTemplate::Template message) {
Scanner::Location source_location = scanner()->location();
@@ -1049,8 +1080,8 @@ class ParserBase {
// This method wraps the parsing of the expression inside a new expression
// classifier and calls RewriteNonPattern if parsing is successful.
- // It should be used whenever we're parsing an expression that will be
- // used as a non-pattern (i.e., in most cases).
+ // It should be used whenever we're parsing an expression that is known
+ // to not be a pattern or part of a pattern.
V8_INLINE ExpressionT ParseExpression(bool accept_IN, bool* ok);
// This method does not wrap the parsing of the expression inside a
@@ -1081,11 +1112,12 @@ class ParserBase {
bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
ClassLiteralPropertyT ParseClassPropertyDefinition(
- ClassLiteralChecker* checker, 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);
- FunctionLiteralT ParseClassFieldForInitializer(bool has_initializer,
- bool* ok);
+ 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);
+ ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, bool is_static,
+ bool* ok);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
ObjectLiteralChecker* checker, bool* is_computed_name,
bool* is_rest_property, bool* ok);
@@ -1357,7 +1389,7 @@ class ParserBase {
inline StatementT BuildReturnStatement(ExpressionT expr, int pos,
int end_pos = kNoSourcePosition) {
if (impl()->IsNull(expr)) {
- expr = impl()->GetLiteralUndefined(kNoSourcePosition);
+ expr = factory()->NewUndefinedLiteral(kNoSourcePosition);
} else if (is_async_generator()) {
// In async generators, if there is an explicit operand to the return
// statement, await the operand.
@@ -1399,6 +1431,7 @@ class ParserBase {
void CheckClassMethodName(Token::Value property, PropertyKind type,
bool is_generator, bool is_async, bool is_static,
bool* ok);
+ void CheckClassFieldName(bool is_static, bool* ok);
private:
bool IsConstructor() {
@@ -1478,9 +1511,11 @@ class ParserBase {
AstValueFactory* ast_value_factory_; // Not owned.
typename Types::Factory ast_node_factory_;
RuntimeCallStats* runtime_call_stats_;
+ internal::Logger* logger_;
bool parsing_on_main_thread_;
- bool parsing_module_;
+ const bool parsing_module_;
uintptr_t stack_limit_;
+ PendingCompilationErrorHandler* pending_error_handler_;
// Parser base's private field members.
@@ -1489,22 +1524,19 @@ class ParserBase {
ExpressionClassifier* classifier_;
Scanner* scanner_;
- bool stack_overflow_;
FunctionLiteral::EagerCompileHint default_eager_compile_hint_;
int function_literal_id_;
+ int script_id_;
bool allow_natives_;
bool allow_harmony_do_expressions_;
bool allow_harmony_function_sent_;
- bool allow_harmony_restrictive_generators_;
- bool allow_harmony_class_fields_;
- bool allow_harmony_object_rest_spread_;
+ bool allow_harmony_public_fields_;
bool allow_harmony_dynamic_import_;
bool allow_harmony_import_meta_;
bool allow_harmony_async_iteration_;
- bool allow_harmony_template_escapes_;
friend class DiscardableZoneScope;
};
@@ -1549,6 +1581,7 @@ void ParserBase<Impl>::GetUnexpectedTokenMessage(
break;
case Token::SMI:
case Token::NUMBER:
+ case Token::BIGINT:
*message = MessageTemplate::kUnexpectedTokenNumber;
break;
case Token::STRING:
@@ -1590,7 +1623,7 @@ void ParserBase<Impl>::GetUnexpectedTokenMessage(
break;
default:
const char* name = Token::String(token);
- DCHECK(name != NULL);
+ DCHECK_NOT_NULL(name);
*arg = name;
break;
}
@@ -1780,6 +1813,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::FALSE_LITERAL:
case Token::SMI:
case Token::NUMBER:
+ case Token::BIGINT:
BindingPatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos);
@@ -1881,7 +1915,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
return ParseTemplateLiteral(impl()->NullExpression(), beg_pos, false, ok);
case Token::MOD:
- if (allow_natives() || extension_ != NULL) {
+ if (allow_natives() || extension_ != nullptr) {
BindingPatternUnexpectedToken();
return ParseV8Intrinsic(ok);
}
@@ -1951,6 +1985,10 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
if (impl()->IsNull(result)) {
// First time through the loop.
result = right;
+ } else if (impl()->CollapseNaryExpression(&result, right, Token::COMMA,
+ comma_pos,
+ SourceRange::Empty())) {
+ // Do nothing, "result" is already updated.
} else {
result =
factory()->NewBinaryOperation(Token::COMMA, result, right, comma_pos);
@@ -1992,7 +2030,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
while (peek() != Token::RBRACK) {
ExpressionT elem;
if (peek() == Token::COMMA) {
- elem = impl()->GetLiteralTheHole(peek_position());
+ elem = factory()->NewTheHoleLiteral();
} else if (peek() == Token::ELLIPSIS) {
int start_pos = peek_position();
Consume(Token::ELLIPSIS);
@@ -2033,8 +2071,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
ExpressionT result =
factory()->NewArrayLiteral(values, first_spread_index, pos);
if (first_spread_index >= 0) {
- result = factory()->NewRewritableExpression(result);
- impl()->QueueNonPatternForRewriting(result, ok);
+ auto rewritable = factory()->NewRewritableExpression(result, scope());
+ impl()->QueueNonPatternForRewriting(rewritable, ok);
if (!*ok) {
// If the non-pattern rewriting mechanism is used in the future for
// rewriting other things than spreads, this error message will have
@@ -2043,6 +2081,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseArrayLiteral(
ReportMessage(MessageTemplate::kTooManySpreads);
return impl()->NullExpression();
}
+ result = rewritable;
}
return result;
}
@@ -2079,7 +2118,7 @@ template <class Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
IdentifierT* name, PropertyKind* kind, bool* is_generator, bool* is_get,
bool* is_set, bool* is_async, bool* is_computed_name, bool* ok) {
- DCHECK(*kind == PropertyKind::kNotSet);
+ DCHECK_EQ(*kind, PropertyKind::kNotSet);
DCHECK(!*is_generator);
DCHECK(!*is_get);
DCHECK(!*is_set);
@@ -2166,8 +2205,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
}
case Token::ELLIPSIS:
- if (allow_harmony_object_rest_spread() && !*is_generator && !*is_async &&
- !*is_get && !*is_set) {
+ if (!*is_generator && !*is_async && !*is_get && !*is_set) {
*name = impl()->NullIdentifier();
Consume(Token::ELLIPSIS);
expression = ParseAssignmentExpression(true, CHECK_OK);
@@ -2217,9 +2255,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
template <typename Impl>
typename ParserBase<Impl>::ClassLiteralPropertyT
ParserBase<Impl>::ParseClassPropertyDefinition(
- ClassLiteralChecker* checker, 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, 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);
DCHECK_NOT_NULL(has_name_static_property);
bool is_get = false;
@@ -2273,14 +2312,17 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
// as an uninitialized field.
case PropertyKind::kShorthandProperty:
case PropertyKind::kValueProperty:
- if (allow_harmony_class_fields()) {
- bool has_initializer = Check(Token::ASSIGN);
- ExpressionT function_literal = ParseClassFieldForInitializer(
- has_initializer, CHECK_OK_CUSTOM(NullLiteralProperty));
- ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
+ if (allow_harmony_public_fields()) {
*property_kind = ClassLiteralProperty::FIELD;
+ if (!*is_computed_name) {
+ checker->CheckClassFieldName(*is_static,
+ CHECK_OK_CUSTOM(NullLiteralProperty));
+ }
+ ExpressionT initializer = ParseClassFieldInitializer(
+ class_info, *is_static, CHECK_OK_CUSTOM(NullLiteralProperty));
+ ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
ClassLiteralPropertyT result = factory()->NewClassLiteralProperty(
- name_expression, function_literal, *property_kind, *is_static,
+ name_expression, initializer, *property_kind, *is_static,
*is_computed_name);
impl()->SetFunctionNameFromPropertyName(result, name);
return result;
@@ -2377,36 +2419,43 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
}
template <typename Impl>
-typename ParserBase<Impl>::FunctionLiteralT
-ParserBase<Impl>::ParseClassFieldForInitializer(bool has_initializer,
- bool* ok) {
- // Makes a concise method which evaluates and returns the initialized value
- // (or undefined if absent).
- FunctionKind kind = FunctionKind::kConciseMethod;
- DeclarationScope* initializer_scope = NewFunctionScope(kind);
- initializer_scope->set_start_position(scanner()->location().end_pos);
- FunctionState initializer_state(&function_state_, &scope_, initializer_scope);
- DCHECK_EQ(initializer_scope, scope());
- scope()->SetLanguageMode(STRICT);
- ExpressionClassifier expression_classifier(this);
- ExpressionT value;
- if (has_initializer) {
- value =
- this->ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression));
+typename ParserBase<Impl>::ExpressionT
+ParserBase<Impl>::ParseClassFieldInitializer(ClassInfo* class_info,
+ bool is_static, bool* ok) {
+ DeclarationScope* initializer_scope = is_static
+ ? class_info->static_fields_scope
+ : class_info->instance_fields_scope;
+
+ if (initializer_scope == nullptr) {
+ initializer_scope = NewFunctionScope(FunctionKind::kConciseMethod);
+ // TODO(gsathya): Make scopes be non contiguous.
+ initializer_scope->set_start_position(scanner()->location().end_pos);
+ initializer_scope->SetLanguageMode(LanguageMode::kStrict);
+ }
+
+ ExpressionT initializer;
+ if (Check(Token::ASSIGN)) {
+ FunctionState initializer_state(&function_state_, &scope_,
+ initializer_scope);
+ ExpressionClassifier expression_classifier(this);
+
+ initializer =
+ ParseAssignmentExpression(true, CHECK_OK_CUSTOM(NullExpression));
impl()->RewriteNonPattern(CHECK_OK_CUSTOM(NullExpression));
} else {
- value = factory()->NewUndefinedLiteral(kNoSourcePosition);
+ initializer = factory()->NewUndefinedLiteral(kNoSourcePosition);
}
+
initializer_scope->set_end_position(scanner()->location().end_pos);
- typename Types::StatementList body = impl()->NewStatementList(1);
- body->Add(factory()->NewReturnStatement(value, kNoSourcePosition), zone());
- FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
- impl()->EmptyIdentifierString(), initializer_scope, body,
- initializer_state.expected_property_count(), 0, 0,
- FunctionLiteral::kNoDuplicateParameters,
- FunctionLiteral::kAnonymousExpression, default_eager_compile_hint_,
- initializer_scope->start_position(), true, GetNextFunctionLiteralId());
- return function_literal;
+ if (is_static) {
+ class_info->static_fields_scope = initializer_scope;
+ class_info->has_static_class_fields = true;
+ } else {
+ class_info->instance_fields_scope = initializer_scope;
+ class_info->has_instance_class_fields = true;
+ }
+
+ return initializer;
}
template <typename Impl>
@@ -2432,7 +2481,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
switch (kind) {
case PropertyKind::kSpreadProperty:
- DCHECK(allow_harmony_object_rest_spread());
DCHECK(!is_get && !is_set && !is_generator && !is_async &&
!*is_computed_name);
DCHECK(name_token == Token::ELLIPSIS);
@@ -2441,7 +2489,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ObjectLiteralChecker* checker,
*is_rest_property = true;
return factory()->NewObjectLiteralProperty(
- impl()->GetLiteralTheHole(kNoSourcePosition), name_expression,
+ factory()->NewTheHoleLiteral(), name_expression,
ObjectLiteralProperty::SPREAD, true);
case PropertyKind::kValueProperty: {
@@ -2910,7 +2958,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
- if (fni_ != NULL) {
+ if (fni_ != nullptr) {
// Check if the right hand side is a call to avoid inferring a
// name if we're dealing with "a = function(){...}();"-like
// expression.
@@ -2925,17 +2973,14 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->SetFunctionNameFromIdentifierRef(right, expression);
}
- if (op == Token::ASSIGN_EXP) {
- DCHECK(!is_destructuring_assignment);
- return impl()->RewriteAssignExponentiation(expression, right, pos);
- }
-
DCHECK_NE(op, Token::INIT);
ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
if (is_destructuring_assignment) {
- result = factory()->NewRewritableExpression(result);
- impl()->QueueDestructuringAssignmentForRewriting(result);
+ DCHECK_NE(op, Token::ASSIGN_EXP);
+ auto rewritable = factory()->NewRewritableExpression(result, scope());
+ impl()->QueueDestructuringAssignmentForRewriting(rewritable);
+ result = rewritable;
}
return result;
@@ -3010,11 +3055,11 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
impl()->RewriteNonPattern(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
- Consume(Token::CONDITIONAL);
ExpressionT left;
{
SourceRangeScope range_scope(scanner(), &then_range);
+ Consume(Token::CONDITIONAL);
ExpressionClassifier classifier(this);
// In parsing the first assignment expression in conditional
// expressions we always accept the 'in' keyword; see ECMA-262,
@@ -3023,10 +3068,10 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
AccumulateNonBindingPatternErrors();
}
impl()->RewriteNonPattern(CHECK_OK);
- Expect(Token::COLON, CHECK_OK);
ExpressionT right;
{
SourceRangeScope range_scope(scanner(), &else_range);
+ Expect(Token::COLON, CHECK_OK);
ExpressionClassifier classifier(this);
right = ParseAssignmentExpression(accept_IN, CHECK_OK);
AccumulateNonBindingPatternErrors();
@@ -3042,7 +3087,8 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
template <typename Impl>
typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
int prec, bool accept_IN, bool* ok) {
- DCHECK(prec >= 4);
+ DCHECK_GE(prec, 4);
+ SourceRange right_range;
ExpressionT x = ParseUnaryExpression(CHECK_OK);
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
// prec1 >= 4
@@ -3050,12 +3096,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
impl()->RewriteNonPattern(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
+
+ SourceRangeScope right_range_scope(scanner(), &right_range);
Token::Value op = Next();
int pos = position();
const bool is_right_associative = op == Token::EXP;
const int next_prec = is_right_associative ? prec1 : prec1 + 1;
ExpressionT y = ParseBinaryExpression(next_prec, accept_IN, CHECK_OK);
+ right_range_scope.Finalize();
impl()->RewriteNonPattern(CHECK_OK);
if (impl()->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos)) {
@@ -3078,11 +3127,14 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
- } else if (op == Token::EXP) {
- x = impl()->RewriteExponentiation(x, y, pos);
+ } else if (impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
+ continue;
} else {
// We have a "normal" binary operation.
x = factory()->NewBinaryOperation(op, x, y, pos);
+ if (op == Token::OR || op == Token::AND) {
+ impl()->RecordBinaryOperationSourceRange(x, right_range);
+ }
}
}
}
@@ -3316,7 +3368,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
factory()->NewAssignment(Token::INIT, this_expr, result, pos);
}
- if (fni_ != NULL) fni_->RemoveLastFunction();
+ if (fni_ != nullptr) fni_->RemoveLastFunction();
break;
}
@@ -3518,9 +3570,15 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseImportExpressions(
return impl()->NullExpression();
}
- return impl()->ExpressionFromLiteral(Token::NULL_LITERAL, pos);
+ return impl()->ImportMetaExpression(pos);
}
Expect(Token::LPAREN, CHECK_OK);
+ if (peek() == Token::RPAREN) {
+ impl()->ReportMessageAt(scanner()->location(),
+ MessageTemplate::kImportMissingSpecifier);
+ *ok = false;
+ return impl()->NullExpression();
+ }
ExpressionT arg = ParseAssignmentExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
return factory()->NewImportCallExpression(arg, pos);
@@ -3666,6 +3724,7 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters,
// BindingElement[?Yield, ?GeneratorParameter]
bool is_rest = parameters->has_rest;
+ FuncNameInferrer::State fni_state(fni_);
ExpressionT pattern = ParsePrimaryExpression(CHECK_OK_CUSTOM(Void));
ValidateBindingPattern(CHECK_OK_CUSTOM(Void));
@@ -3775,12 +3834,12 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
break;
case Token::CONST:
Consume(Token::CONST);
- DCHECK(var_context != kStatement);
+ DCHECK_NE(var_context, kStatement);
parsing_result->descriptor.mode = CONST;
break;
case Token::LET:
Consume(Token::LET);
- DCHECK(var_context != kStatement);
+ DCHECK_NE(var_context, kStatement);
parsing_result->descriptor.mode = LET;
break;
default:
@@ -3857,7 +3916,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
}
// 'let x' initializes 'x' to undefined.
if (parsing_result->descriptor.mode == LET) {
- value = impl()->GetLiteralUndefined(position());
+ value = factory()->NewUndefinedLiteral(position());
}
}
@@ -3979,9 +4038,9 @@ ParserBase<Impl>::ParseHoistableDeclaration(
// sloppy_block_function_map. Don't add them to the map for async functions.
// Generators are also supposed to be prohibited; currently doing this behind
// a flag and UseCounting violations to assess web compatibility.
- bool is_sloppy_block_function =
- is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
- !is_async && !(allow_harmony_restrictive_generators() && is_generator);
+ bool is_sloppy_block_function = is_sloppy(language_mode()) &&
+ !scope()->is_declaration_scope() &&
+ !is_async && !is_generator;
return impl()->DeclareFunction(variable_name, function, mode, pos,
is_sloppy_block_function, names, ok);
@@ -4078,18 +4137,6 @@ void ParserBase<Impl>::ParseFunctionBody(
typename ParserBase<Impl>::StatementListT result, IdentifierT function_name,
int pos, const FormalParametersT& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
- static const int kFunctionNameAssignmentIndex = 0;
- if (function_type == FunctionLiteral::kNamedExpression) {
- DCHECK(!impl()->IsNull(function_name));
- // If we have a named function expression, we add a local variable
- // declaration to the body of the function with the name of the
- // function and let it refer to the function itself (closure).
- // Not having parsed the function body, the language mode may still change,
- // so we reserve a spot and create the actual const assignment later.
- DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
- result->Add(impl()->NullStatement(), zone());
- }
-
DeclarationScope* function_scope = scope()->AsDeclarationScope();
DeclarationScope* inner_scope = function_scope;
BlockT inner_block = impl()->NullStatement();
@@ -4170,9 +4217,7 @@ void ParserBase<Impl>::ParseFunctionBody(
function_scope->DeclareArguments(ast_value_factory());
}
- impl()->CreateFunctionNameAssignment(function_name, pos, function_type,
- function_scope, result,
- kFunctionNameAssignmentIndex);
+ impl()->DeclareFunctionNameVar(function_name, function_type, function_scope);
}
template <typename Impl>
@@ -4233,9 +4278,10 @@ template <typename Impl>
bool ParserBase<Impl>::IsTrivialExpression() {
Token::Value peek_token = peek();
if (peek_token == Token::SMI || peek_token == Token::NUMBER ||
- peek_token == Token::NULL_LITERAL || peek_token == Token::TRUE_LITERAL ||
- peek_token == Token::FALSE_LITERAL || peek_token == Token::STRING ||
- peek_token == Token::IDENTIFIER || peek_token == Token::THIS) {
+ peek_token == Token::BIGINT || peek_token == Token::NULL_LITERAL ||
+ peek_token == Token::TRUE_LITERAL || peek_token == Token::FALSE_LITERAL ||
+ peek_token == Token::STRING || peek_token == Token::IDENTIFIER ||
+ peek_token == Token::THIS) {
// PeekAhead() is expensive & may not always be called, so we only call it
// after checking peek().
Token::Value peek_ahead = PeekAhead();
@@ -4260,6 +4306,8 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
RuntimeCallTimerScope runtime_timer(
runtime_call_stats_,
counters[Impl::IsPreParser()][parsing_on_main_thread_]);
+ base::ElapsedTimer timer;
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
// ASI inserts `;` after arrow parameters if a line terminator is found.
@@ -4302,7 +4350,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
// For arrow functions, we don't need to retrieve data about function
// parameters.
int dummy_num_parameters = -1;
- DCHECK((kind & FunctionKind::kArrowFunction) != 0);
+ DCHECK_NE(kind & FunctionKind::kArrowFunction, 0);
LazyParsingResult result = impl()->SkipFunction(
nullptr, kind, FunctionLiteral::kAnonymousExpression,
formal_parameters.scope, &dummy_num_parameters,
@@ -4313,6 +4361,13 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
formal_parameters.scope->ResetAfterPreparsing(ast_value_factory_,
false);
+ // Discard any queued destructuring assignments which appeared
+ // in this function's parameter list.
+ FunctionState* parent_state = function_state.outer();
+ DCHECK_NOT_NULL(parent_state);
+ DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(),
+ rewritable_length);
+ parent_state->RewindDestructuringAssignments(rewritable_length);
} else {
Consume(Token::LBRACE);
body = impl()->NewStatementList(8);
@@ -4349,23 +4404,9 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
}
impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
- if (is_lazy_top_level_function) {
- FunctionState* parent_state = function_state.outer();
- DCHECK_NOT_NULL(parent_state);
- DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(),
- rewritable_length);
- parent_state->RewindDestructuringAssignments(rewritable_length);
- }
-
impl()->RewriteDestructuringAssignments();
}
- if (FLAG_trace_preparse) {
- Scope* scope = formal_parameters.scope;
- PrintF(" [%s]: %i-%i (arrow function)\n",
- is_lazy_top_level_function ? "Preparse no-resolution" : "Full parse",
- scope->start_position(), scope->end_position());
- }
FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
impl()->EmptyIdentifierString(), formal_parameters.scope, body,
expected_property_count, formal_parameters.num_parameters(),
@@ -4380,6 +4421,17 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
impl()->AddFunctionForNameInference(function_literal);
+ if (V8_UNLIKELY((FLAG_log_function_events))) {
+ Scope* scope = formal_parameters.scope;
+ double ms = timer.Elapsed().InMillisecondsF();
+ const char* event_name =
+ is_lazy_top_level_function ? "preparse-no-resolution" : "parse";
+ const char* name = "arrow function";
+ logger_->FunctionEvent(event_name, nullptr, script_id(), ms,
+ scope->start_position(), scope->end_position(), name,
+ strlen(name));
+ }
+
return function_literal;
}
@@ -4407,7 +4459,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
Scope* block_scope = NewScope(BLOCK_SCOPE);
BlockState block_state(&scope_, block_scope);
- RaiseLanguageMode(STRICT);
+ RaiseLanguageMode(LanguageMode::kStrict);
ClassInfo class_info(this);
class_info.is_anonymous = is_anonymous;
@@ -4438,19 +4490,23 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
// property.
bool is_constructor = !class_info.has_seen_constructor;
ClassLiteralPropertyT property = ParseClassPropertyDefinition(
- &checker, has_extends, &is_computed_name,
+ &checker, &class_info, 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) {
+ class_info.computed_field_count++;
+ }
is_constructor &= class_info.has_seen_constructor;
impl()->RewriteNonPattern(CHECK_OK);
AccumulateFormalParameterContainmentErrors();
impl()->DeclareClassProperty(name, property, property_kind, is_static,
- is_constructor, &class_info, CHECK_OK);
+ is_constructor, is_computed_name, &class_info,
+ CHECK_OK);
impl()->InferFunctionName();
}
@@ -4550,9 +4606,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
//
// When parsing a TemplateLiteral, we must have scanned either an initial
// TEMPLATE_SPAN, or a TEMPLATE_TAIL.
- CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
+ DCHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL);
- bool forbid_illegal_escapes = !allow_harmony_template_escapes() || !tagged;
+ bool forbid_illegal_escapes = !tagged;
// If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
// In this case we may simply consume the token and build a template with a
@@ -4656,7 +4712,7 @@ ParserBase<Impl>::CheckAndRewriteReferenceExpression(
if (expression->IsValidReferenceExpression()) {
return expression;
}
- if (expression->IsCall()) {
+ if (expression->IsCall() && !expression->AsCall()->is_tagged_template()) {
// If it is a call, make it a runtime error for legacy web compatibility.
// Bug: https://bugs.chromium.org/p/v8/issues/detail?id=4480
// Rewrite `expr' to `expr[throw ReferenceError]'.
@@ -4763,7 +4819,7 @@ ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
if (impl()->IsUseStrictDirective(stat) &&
token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
// Directive "use strict" (ES5 14.1).
- RaiseLanguageMode(STRICT);
+ RaiseLanguageMode(LanguageMode::kStrict);
if (!scope()->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
@@ -4783,14 +4839,14 @@ ParserBase<Impl>::ParseStatementList(StatementListT body, int end_token,
// Possibly an unknown directive.
// Should not change mode, but will increment usage counters
// as appropriate. Ditto usages below.
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
} else {
// End of the directive prologue.
directive_prologue = false;
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
}
} else {
- RaiseLanguageMode(SLOPPY);
+ RaiseLanguageMode(LanguageMode::kSloppy);
}
// If we're allowed to abort, we will do so when we see a "long and
@@ -5121,7 +5177,7 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
ExpectSemicolon(CHECK_OK);
if (labels != nullptr) {
// TODO(adamk): Also measure in the PreParser by passing something
- // non-NULL as |labels|.
+ // non-null as |labels|.
impl()->CountUsage(v8::Isolate::kLabeledExpressionStatement);
}
return factory()->NewExpressionStatement(expr, pos);
@@ -5758,7 +5814,7 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
ForInfo* for_info, ZoneList<const AstRawString*>* labels, bool* ok) {
// Initializer is reference followed by in/of.
if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
- expression = impl()->CheckAndRewriteReferenceExpression(
+ expression = CheckAndRewriteReferenceExpression(
expression, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
kSyntaxError, CHECK_OK);
}
@@ -5959,7 +6015,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
ValidateAssignmentPattern(CHECK_OK);
} else {
impl()->RewriteNonPattern(CHECK_OK);
- each_variable = impl()->CheckAndRewriteReferenceExpression(
+ each_variable = CheckAndRewriteReferenceExpression(
lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
kSyntaxError, CHECK_OK);
}
@@ -6081,6 +6137,22 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
}
}
+template <typename Impl>
+void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static,
+ bool* ok) {
+ if (is_static && IsPrototype()) {
+ this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
+ *ok = false;
+ return;
+ }
+
+ if (IsConstructor()) {
+ this->parser()->ReportMessage(MessageTemplate::kConstructorClassField);
+ *ok = false;
+ return;
+ }
+}
+
#undef CHECK_OK
#undef CHECK_OK_CUSTOM
#undef CHECK_OK_VOID
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index a554d7d242..4d291a741e 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -8,7 +8,6 @@
#include <memory>
#include "src/api.h"
-#include "src/ast/ast-expression-rewriter.h"
#include "src/ast/ast-function-literal-id-reindexer.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/ast.h"
@@ -16,6 +15,7 @@
#include "src/base/platform/platform.h"
#include "src/char-predicates-inl.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
+#include "src/log.h"
#include "src/messages.h"
#include "src/objects-inl.h"
#include "src/parsing/duplicate-finder.h"
@@ -173,11 +173,11 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
FunctionKind kind = call_super ? FunctionKind::kDefaultDerivedConstructor
: FunctionKind::kDefaultBaseConstructor;
DeclarationScope* function_scope = NewFunctionScope(kind);
- SetLanguageMode(function_scope, STRICT);
+ SetLanguageMode(function_scope, LanguageMode::kStrict);
// Set start and end position to the same value
function_scope->set_start_position(pos);
function_scope->set_end_position(pos);
- ZoneList<Statement*>* body = NULL;
+ ZoneList<Statement*>* body = nullptr;
{
FunctionState function_state(&function_state_, &scope_, function_scope);
@@ -212,7 +212,6 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
parameter_count, FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos,
true, GetNextFunctionLiteralId());
-
return function_literal;
}
@@ -245,10 +244,9 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
Expression* y,
Token::Value op, int pos) {
- if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
- y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
- double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
- double y_val = y->AsLiteral()->raw_value()->AsNumber();
+ if ((*x)->IsNumberLiteral() && y->IsNumberLiteral()) {
+ double x_val = (*x)->AsLiteral()->AsNumber();
+ double y_val = y->AsLiteral()->AsNumber();
switch (op) {
case Token::ADD:
*x = factory()->NewNumberLiteral(x_val + y_val, pos);
@@ -308,16 +306,48 @@ bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
return false;
}
+bool Parser::CollapseNaryExpression(Expression** x, Expression* y,
+ Token::Value op, int pos,
+ const SourceRange& range) {
+ // Filter out unsupported ops.
+ if (!Token::IsBinaryOp(op) || op == Token::EXP) return false;
+
+ // Convert *x into an nary operation with the given op, returning false if
+ // this is not possible.
+ NaryOperation* nary = nullptr;
+ if ((*x)->IsBinaryOperation()) {
+ BinaryOperation* binop = (*x)->AsBinaryOperation();
+ if (binop->op() != op) return false;
+
+ nary = factory()->NewNaryOperation(op, binop->left(), 2);
+ nary->AddSubsequent(binop->right(), binop->position());
+ ConvertBinaryToNaryOperationSourceRange(binop, nary);
+ *x = nary;
+ } else if ((*x)->IsNaryOperation()) {
+ nary = (*x)->AsNaryOperation();
+ if (nary->op() != op) return false;
+ } else {
+ return false;
+ }
+
+ // Append our current expression to the nary operation.
+ // TODO(leszeks): Do some literal collapsing here if we're appending Smi or
+ // String literals.
+ nary->AddSubsequent(y, pos);
+ AppendNaryOperationSourceRange(nary, range);
+
+ return true;
+}
+
Expression* Parser::BuildUnaryExpression(Expression* expression,
Token::Value op, int pos) {
- DCHECK(expression != NULL);
- if (expression->IsLiteral()) {
- const AstValue* literal = expression->AsLiteral()->raw_value();
+ DCHECK_NOT_NULL(expression);
+ const Literal* literal = expression->AsLiteral();
+ if (literal != nullptr) {
if (op == Token::NOT) {
// Convert the literal to a boolean condition and negate it.
- bool condition = literal->BooleanValue();
- return factory()->NewBooleanLiteral(!condition, pos);
- } else if (literal->IsNumber()) {
+ return factory()->NewBooleanLiteral(literal->ToBooleanIsFalse(), pos);
+ } else if (literal->IsNumberLiteral()) {
// Compute some expressions involving only number literals.
double value = literal->AsNumber();
switch (op) {
@@ -383,6 +413,12 @@ Expression* Parser::FunctionSentExpression(int pos) {
args, pos);
}
+Expression* Parser::ImportMetaExpression(int pos) {
+ return factory()->NewCallRuntime(
+ Runtime::kInlineGetImportMetaObject,
+ new (zone()) ZoneList<Expression*>(0, zone()), pos);
+}
+
Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
switch (token) {
case Token::NULL_LITERAL:
@@ -399,10 +435,13 @@ Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
double value = scanner()->DoubleValue();
return factory()->NewNumberLiteral(value, pos);
}
+ case Token::BIGINT:
+ return factory()->NewBigIntLiteral(
+ AstBigInt(scanner()->CurrentLiteralAsCString(zone())), pos);
default:
DCHECK(false);
}
- return NULL;
+ return nullptr;
}
Expression* Parser::NewV8Intrinsic(const AstRawString* name,
@@ -463,7 +502,10 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
info->extension(), info->GetOrCreateAstValueFactory(),
- info->runtime_call_stats(), true),
+ info->pending_error_handler(),
+ info->runtime_call_stats(), info->logger(),
+ info->script().is_null() ? -1 : info->script()->id(),
+ info->is_module(), true),
scanner_(info->unicode_cache(), use_counts_),
reusable_preparser_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
@@ -479,7 +521,7 @@ Parser::Parser(ParseInfo* info)
// Even though we were passed ParseInfo, we should not store it in
// Parser - this makes sure that Isolate is not accidentally accessed via
// ParseInfo during background parsing.
- DCHECK(info->character_stream() != nullptr);
+ DCHECK_NOT_NULL(info->character_stream());
// Determine if functions can be lazily compiled. This is necessary to
// allow some of our builtin JS files to be lazily compiled. These
// builtins cannot be handled lazily by the parser, since we have to know
@@ -500,13 +542,11 @@ Parser::Parser(ParseInfo* info)
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_restrictive_generators(FLAG_harmony_restrictive_generators);
- set_allow_harmony_class_fields(FLAG_harmony_class_fields);
- set_allow_harmony_object_rest_spread(FLAG_harmony_object_rest_spread);
+ set_allow_harmony_public_fields(FLAG_harmony_public_fields);
set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import);
set_allow_harmony_import_meta(FLAG_harmony_import_meta);
set_allow_harmony_async_iteration(FLAG_harmony_async_iteration);
- set_allow_harmony_template_escapes(FLAG_harmony_template_escapes);
+ set_allow_harmony_bigint(FLAG_harmony_bigint);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
@@ -527,7 +567,6 @@ void Parser::DeserializeScopeChain(
scope = Scope::DeserializeScopeChain(
zone(), *outer_scope_info, script_scope, ast_value_factory(),
Scope::DeserializationMode::kScopesOnly);
- DCHECK(!info->is_module() || scope->is_module_scope());
}
original_scope_ = scope;
}
@@ -557,9 +596,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
: &RuntimeCallStats::ParseProgram);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram");
base::ElapsedTimer timer;
- if (FLAG_trace_parse) {
- timer.Start();
- }
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
// Initialize parser state.
@@ -583,23 +620,25 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
HandleSourceURLComments(isolate, info->script());
- if (FLAG_trace_parse && result != nullptr) {
- double ms = timer.Elapsed().InMillisecondsF();
- if (info->is_eval()) {
- PrintF("[parsing eval");
- } else if (info->script()->name()->IsString()) {
- String* name = String::cast(info->script()->name());
- std::unique_ptr<char[]> name_chars = name->ToCString();
- PrintF("[parsing script: %s", name_chars.get());
- } else {
- PrintF("[parsing script");
- }
- PrintF(" - took %0.3f ms]\n", ms);
- }
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";
+ Script* script = *info->script();
+ int start = -1;
+ int end = -1;
+ if (!info->is_eval()) {
+ event_name = "parse-script";
+ start = 0;
+ end = String::cast(script->source())->length();
+ }
+ LOG(script->GetIsolate(),
+ FunctionEvent(event_name, script, -1, ms, start, end, "", 0));
+ }
return result;
}
@@ -616,11 +655,10 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
DCHECK(info->function_literal_id() == FunctionLiteral::kIdTypeTopLevel ||
info->function_literal_id() == FunctionLiteral::kIdTypeInvalid);
- FunctionLiteral* result = NULL;
+ FunctionLiteral* result = nullptr;
{
Scope* outer = original_scope_;
DCHECK_NOT_NULL(outer);
- parsing_module_ = info->is_module();
if (info->is_eval()) {
outer = NewEvalScope(outer);
} else if (parsing_module_) {
@@ -638,6 +676,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
bool ok = true;
int beg_pos = scanner()->location().beg_pos;
if (parsing_module_) {
+ DCHECK(info->is_module());
// Declare the special module parameter.
auto name = ast_value_factory()->empty_string();
bool is_duplicate = false;
@@ -658,9 +697,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
zone());
ParseModuleItemList(body, &ok);
- ok = ok &&
- module()->Validate(this->scope()->AsModuleScope(),
- &pending_error_handler_, zone());
+ ok = ok && module()->Validate(this->scope()->AsModuleScope(),
+ pending_error_handler(), zone());
} else {
// Don't count the mode in the use counters--give the program a chance
// to enable script-wide strict mode below.
@@ -708,7 +746,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
info->set_max_function_literal_id(GetLastFunctionLiteralId());
// Make sure the target stack is empty.
- DCHECK(target_stack_ == NULL);
+ DCHECK_NULL(target_stack_);
return result;
}
@@ -722,9 +760,8 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
&RuntimeCallStats::ParseFunction);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction");
base::ElapsedTimer timer;
- if (FLAG_trace_parse) {
- timer.Start();
- }
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
+
DeserializeScopeChain(info, info->maybe_outer_scope_info());
DCHECK_EQ(factory()->zone(), info->zone());
@@ -740,12 +777,18 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
result->set_inferred_name(inferred_name);
}
- if (FLAG_trace_parse && result != NULL) {
+ if (V8_UNLIKELY(FLAG_log_function_events) && result != nullptr) {
double ms = timer.Elapsed().InMillisecondsF();
// We need to make sure that the debug-name is available.
ast_value_factory()->Internalize(isolate);
- std::unique_ptr<char[]> name_chars = result->debug_name()->ToCString();
- PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
+ DeclarationScope* function_scope = result->scope();
+ Script* script = *info->script();
+ std::unique_ptr<char[]> function_name = result->GetDebugName();
+ LOG(script->GetIsolate(),
+ FunctionEvent("parse-function", script, -1, ms,
+ function_scope->start_position(),
+ function_scope->end_position(), function_name.get(),
+ strlen(function_name.get())));
}
return result;
}
@@ -888,6 +931,11 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind,
kNoSourcePosition, function_type, info->language_mode(), &ok);
}
+
+ if (ok) {
+ result->set_requires_instance_fields_initializer(
+ info->requires_instance_fields_initializer());
+ }
// Make sure the results agree.
DCHECK(ok == (result != nullptr));
}
@@ -979,11 +1027,12 @@ void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
// Keep track of the first reserved word encountered in case our
// caller needs to report an error.
if (!reserved_loc->IsValid() &&
- !Token::IsIdentifier(name_tok, STRICT, false, parsing_module_)) {
+ !Token::IsIdentifier(name_tok, LanguageMode::kStrict, false,
+ parsing_module_)) {
*reserved_loc = scanner()->location();
}
const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
- const AstRawString* export_name = NULL;
+ const AstRawString* export_name = nullptr;
Scanner::Location location = scanner()->location();
if (CheckContextualKeyword(Token::AS)) {
export_name = ParseIdentifierName(CHECK_OK_VOID);
@@ -991,7 +1040,7 @@ void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
// both for errors due to "a" and for errors due to "b".
location.end_pos = scanner()->location().end_pos;
}
- if (export_name == NULL) {
+ if (export_name == nullptr) {
export_name = local_name;
}
export_names->Add(export_name, zone());
@@ -1033,8 +1082,8 @@ ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
if (CheckContextualKeyword(Token::AS)) {
local_name = ParseIdentifierName(CHECK_OK);
}
- if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
- parsing_module_)) {
+ if (!Token::IsIdentifier(scanner()->current_token(), LanguageMode::kStrict,
+ false, parsing_module_)) {
*ok = false;
ReportMessage(MessageTemplate::kUnexpectedReserved);
return nullptr;
@@ -1393,8 +1442,8 @@ Variable* Parser::Declare(Declaration* declaration,
}
bool sloppy_mode_block_scope_function_redefinition = false;
Variable* variable = scope->DeclareVariable(
- declaration, mode, init, allow_harmony_restrictive_generators(),
- &sloppy_mode_block_scope_function_redefinition, ok);
+ declaration, mode, init, &sloppy_mode_block_scope_function_redefinition,
+ ok);
if (!*ok) {
// If we only have the start position of a proxy, we can't highlight the
// whole variable name. Pretend its length is 1 so that we highlight at
@@ -1778,25 +1827,13 @@ void Parser::ParseAndRewriteAsyncGeneratorFunctionBody(
zone());
}
-void Parser::CreateFunctionNameAssignment(
- const AstRawString* function_name, int pos,
- FunctionLiteral::FunctionType function_type,
- DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) {
- if (function_type == FunctionLiteral::kNamedExpression) {
- StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition);
- if (function_scope->LookupLocal(function_name) == nullptr) {
- // Now that we know the language mode, we can create the const assignment
- // in the previously reserved spot.
- DCHECK_EQ(function_scope, scope());
- Variable* fvar = function_scope->DeclareFunctionVar(function_name);
- VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
- statement = factory()->NewExpressionStatement(
- factory()->NewAssignment(Token::INIT, fproxy,
- factory()->NewThisFunction(pos),
- kNoSourcePosition),
- kNoSourcePosition);
- }
- result->Set(index, statement);
+void Parser::DeclareFunctionNameVar(const AstRawString* function_name,
+ FunctionLiteral::FunctionType function_type,
+ DeclarationScope* function_scope) {
+ if (function_type == FunctionLiteral::kNamedExpression &&
+ function_scope->LookupLocal(function_name) == nullptr) {
+ DCHECK_EQ(function_scope, scope());
+ function_scope->DeclareFunctionVar(function_name);
}
}
@@ -1851,7 +1888,7 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* subject,
Statement* body) {
ForOfStatement* for_of = stmt->AsForOfStatement();
- if (for_of != NULL) {
+ if (for_of != nullptr) {
const bool finalize = true;
return InitializeForOfStatement(for_of, each, subject, body, finalize,
IteratorType::kNormal, each->position());
@@ -2155,7 +2192,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// }
// }
- DCHECK(for_info.bound_names.length() > 0);
+ DCHECK_GT(for_info.bound_names.length(), 0);
ZoneList<Variable*> temps(for_info.bound_names.length(), zone());
Block* outer_block =
@@ -2180,7 +2217,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
temps.Add(temp, zone());
}
- Variable* first = NULL;
+ Variable* first = nullptr;
// Make statement: first = 1.
if (next) {
first = NewTemporary(temp_name);
@@ -2205,7 +2242,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// need to know about it. This should be safe because we don't run any code
// in this function that looks up break targets.
ForStatement* outer_loop =
- factory()->NewForStatement(NULL, kNoSourcePosition);
+ factory()->NewForStatement(nullptr, kNoSourcePosition);
outer_block->statements()->Add(outer_loop, zone());
outer_block->set_scope(scope());
@@ -2229,7 +2266,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
Statement* assignment_statement =
factory()->NewExpressionStatement(assignment, kNoSourcePosition);
int declaration_pos = for_info.parsing_result.descriptor.declaration_pos;
- DCHECK(declaration_pos != kNoSourcePosition);
+ DCHECK_NE(declaration_pos, kNoSourcePosition);
decl->proxy()->var()->set_initializer_position(declaration_pos);
ignore_completion_block->statements()->Add(assignment_statement, zone());
}
@@ -2237,7 +2274,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// Make statement: if (first == 1) { first = 0; } else { next; }
if (next) {
DCHECK(first);
- Expression* compare = NULL;
+ Expression* compare = nullptr;
// Make compare expression: first == 1.
{
Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
@@ -2245,7 +2282,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
kNoSourcePosition);
}
- Statement* clear_first = NULL;
+ Statement* clear_first = nullptr;
// Make statement: first = 0.
{
VariableProxy* first_proxy = factory()->NewVariableProxy(first);
@@ -2284,7 +2321,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
inner_block->statements()->Add(ignore_completion_block, zone());
// Make cond expression for main loop: flag == 1.
- Expression* flag_cond = NULL;
+ Expression* flag_cond = nullptr;
{
Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
@@ -2293,9 +2330,9 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
}
// Create chain of expressions "flag = 0, temp_x = x, ..."
- Statement* compound_next_statement = NULL;
+ Statement* compound_next_statement = nullptr;
{
- Expression* compound_next = NULL;
+ Expression* compound_next = nullptr;
// Make expression: flag = 0.
{
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
@@ -2324,12 +2361,12 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
// Note that we re-use the original loop node, which retains its labels
// and ensures that any break or continue statements in body point to
// the right place.
- loop->Initialize(NULL, flag_cond, compound_next_statement, body);
+ loop->Initialize(nullptr, flag_cond, compound_next_statement, body);
inner_block->statements()->Add(loop, zone());
// Make statement: {{if (flag == 1) break;}}
{
- Expression* compare = NULL;
+ Expression* compare = nullptr;
// Make compare expresion: flag == 1.
{
Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
@@ -2348,7 +2385,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
inner_block->set_scope(inner_scope);
}
- outer_loop->Initialize(NULL, NULL, NULL, inner_block);
+ outer_loop->Initialize(nullptr, nullptr, nullptr, inner_block);
return outer_block;
}
@@ -2357,6 +2394,7 @@ void Parser::AddArrowFunctionFormalParameters(
ParserFormalParameters* parameters, Expression* expr, int end_pos,
bool* ok) {
// ArrowFunctionFormals ::
+ // Nary(Token::COMMA, VariableProxy*, Tail)
// Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
// Tail
// NonTailArrowFunctionFormals ::
@@ -2366,9 +2404,30 @@ void Parser::AddArrowFunctionFormalParameters(
// VariableProxy
// Spread(VariableProxy)
//
- // As we need to visit the parameters in left-to-right order, we recurse on
- // the left-hand side of comma expressions.
+ // We need to visit the parameters in left-to-right order
//
+
+ // For the Nary case, we simply visit the parameters in a loop.
+ if (expr->IsNaryOperation()) {
+ NaryOperation* nary = expr->AsNaryOperation();
+ // The classifier has already run, so we know that the expression is a valid
+ // arrow function formals production.
+ DCHECK_EQ(nary->op(), Token::COMMA);
+ // Each op position is the end position of the *previous* expr, with the
+ // second (i.e. first "subsequent") op position being the end position of
+ // the first child expression.
+ Expression* next = nary->first();
+ for (size_t i = 0; i < nary->subsequent_length(); ++i) {
+ AddArrowFunctionFormalParameters(
+ parameters, next, nary->subsequent_op_position(i), CHECK_OK_VOID);
+ next = nary->subsequent(i);
+ }
+ AddArrowFunctionFormalParameters(parameters, next, end_pos, CHECK_OK_VOID);
+ return;
+ }
+
+ // For the binary case, we recurse on the left-hand side of binary comma
+ // expressions.
if (expr->IsBinaryOperation()) {
BinaryOperation* binop = expr->AsBinaryOperation();
// The classifier has already run, so we know that the expression is a valid
@@ -2467,7 +2526,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// Anonymous functions were passed either the empty symbol or a null
// handle as the function name. Remember if we were passed a non-empty
// handle to decide whether to invoke function name inference.
- bool should_infer_name = function_name == NULL;
+ bool should_infer_name = function_name == nullptr;
// We want a non-null handle as the function name by default. We will handle
// the "function does not have a shared name" case later.
@@ -2518,8 +2577,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
const bool is_lazy =
eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
- const bool is_top_level =
- impl()->AllowsLazyParsingWithoutUnresolvedVariables();
+ const bool is_top_level = 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_expression =
@@ -2531,6 +2589,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
parsing_on_main_thread_
? &RuntimeCallStats::ParseFunctionLiteral
: &RuntimeCallStats::ParseBackgroundFunctionLiteral);
+ base::ElapsedTimer timer;
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
// Determine whether we can still lazy parse the inner function.
// The preconditions are:
@@ -2631,13 +2691,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
}
DCHECK_EQ(should_preparse, temp_zoned_);
- if (V8_UNLIKELY(FLAG_trace_preparse)) {
- PrintF(" [%s]: %i-%i %.*s\n",
- 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_log_function_events)) {
+ double ms = timer.Elapsed().InMillisecondsF();
+ const char* event_name = should_preparse
+ ? (is_top_level ? "preparse-no-resolution"
+ : "preparse-resolution")
+ : "full-parse";
+ logger_->FunctionEvent(
+ event_name, nullptr, script_id(), ms, scope->start_position(),
+ scope->end_position(),
+ reinterpret_cast<const char*>(function_name->raw_data()),
+ function_name->byte_length());
}
if (V8_UNLIKELY(FLAG_runtime_stats)) {
if (should_preparse) {
@@ -2764,8 +2828,8 @@ Parser::LazyParsingResult Parser::SkipFunction(
DCHECK(!is_inner_function || !may_abort);
PreParser::PreParseResult result = reusable_preparser()->PreParseFunction(
- function_name, kind, function_type, function_scope, parsing_module_,
- is_inner_function, may_abort, use_counts_, produced_preparsed_scope_data);
+ function_name, kind, function_type, function_scope, is_inner_function,
+ may_abort, use_counts_, produced_preparsed_scope_data, this->script_id());
// Return immediately if pre-parser decided to abort parsing.
if (result == PreParser::kPreParseAbort) return kLazyParsingAborted;
@@ -2775,7 +2839,7 @@ Parser::LazyParsingResult Parser::SkipFunction(
*ok = false;
return kLazyParsingComplete;
}
- if (pending_error_handler_.has_pending_error()) {
+ if (pending_error_handler()->has_pending_error()) {
*ok = false;
return kLazyParsingComplete;
}
@@ -3137,6 +3201,20 @@ void Parser::DeclareClassVariable(const AstRawString* name,
}
}
+// TODO(gsathya): Ideally, this should just bypass scope analysis and
+// allocate a slot directly on the context. We should just store this
+// index in the AST, instead of storing the variable.
+Variable* Parser::CreateSyntheticContextVariable(const AstRawString* name,
+ bool* ok) {
+ VariableProxy* proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, kNoSourcePosition);
+ Variable* var = Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
+ Variable::DefaultInitializationFlag(CONST), CHECK_OK);
+ var->ForceContextAllocation();
+ return var;
+}
+
// This method declares a property of the given class. It updates the
// following fields of class_info, as appropriate:
// - constructor
@@ -3145,7 +3223,8 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
ClassLiteralProperty* property,
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
- ClassInfo* class_info, bool* ok) {
+ bool is_computed_name, ClassInfo* class_info,
+ bool* ok) {
if (is_constructor) {
DCHECK(!class_info->constructor);
class_info->constructor = property->value()->AsFunctionLiteral();
@@ -3156,11 +3235,44 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
return;
}
- if (property->kind() == ClassLiteralProperty::FIELD) {
- DCHECK(allow_harmony_class_fields());
- // TODO(littledan): Implement class fields
+ if (kind != ClassLiteralProperty::FIELD) {
+ class_info->properties->Add(property, zone());
+ return;
+ }
+
+ DCHECK(allow_harmony_public_fields());
+
+ if (is_static) {
+ class_info->static_fields->Add(property, zone());
+ } else {
+ class_info->instance_fields->Add(property, zone());
+ }
+
+ if (is_computed_name) {
+ // We create a synthetic variable name here so that scope
+ // analysis doesn't dedupe the vars.
+ Variable* computed_name_var = CreateSyntheticContextVariable(
+ ClassFieldVariableName(ast_value_factory(),
+ class_info->computed_field_count),
+ CHECK_OK_VOID);
+ property->set_computed_name_var(computed_name_var);
+ class_info->properties->Add(property, zone());
}
- class_info->properties->Add(property, zone());
+}
+
+FunctionLiteral* Parser::CreateInitializerFunction(
+ DeclarationScope* scope, ZoneList<ClassLiteral::Property*>* fields) {
+ // function() { .. class fields initializer .. }
+ ZoneList<Statement*>* statements = NewStatementList(1);
+ InitializeClassFieldsStatement* static_fields =
+ factory()->NewInitializeClassFieldsStatement(fields, kNoSourcePosition);
+ statements->Add(static_fields, zone());
+ return factory()->NewFunctionLiteral(
+ ast_value_factory()->empty_string(), scope, statements, 0, 0, 0,
+ FunctionLiteral::kNoDuplicateParameters,
+ FunctionLiteral::kAnonymousExpression,
+ FunctionLiteral::kShouldEagerCompile, scope->start_position(), true,
+ GetNextFunctionLiteralId());
}
// This method generates a ClassLiteral AST node.
@@ -3177,7 +3289,7 @@ Expression* Parser::RewriteClassLiteral(Scope* block_scope,
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);
+ DCHECK_EQ(block_scope->language_mode(), LanguageMode::kStrict);
bool has_extends = class_info->extends != nullptr;
bool has_default_constructor = class_info->constructor == nullptr;
@@ -3191,25 +3303,33 @@ Expression* Parser::RewriteClassLiteral(Scope* block_scope,
class_info->variable->set_initializer_position(end_pos);
}
+ FunctionLiteral* static_fields_initializer = nullptr;
+ if (class_info->has_static_class_fields) {
+ static_fields_initializer = CreateInitializerFunction(
+ class_info->static_fields_scope, class_info->static_fields);
+ }
+
+ FunctionLiteral* instance_fields_initializer_function = nullptr;
+ if (class_info->has_instance_class_fields) {
+ instance_fields_initializer_function = CreateInitializerFunction(
+ class_info->instance_fields_scope, class_info->instance_fields);
+ class_info->constructor->set_requires_instance_fields_initializer(true);
+ }
+
ClassLiteral* class_literal = factory()->NewClassLiteral(
block_scope, class_info->variable, class_info->extends,
- class_info->constructor, class_info->properties, pos, end_pos,
- class_info->has_name_static_property,
+ class_info->constructor, class_info->properties,
+ static_fields_initializer, instance_fields_initializer_function, pos,
+ end_pos, class_info->has_name_static_property,
class_info->has_static_computed_names, class_info->is_anonymous);
AddFunctionForNameInference(class_info->constructor);
-
return class_literal;
}
-Literal* Parser::GetLiteralUndefined(int position) {
- return factory()->NewUndefinedLiteral(position);
-}
-
-
void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
Declaration* decl = scope->CheckConflictingVarDeclarations();
- if (decl != NULL) {
+ if (decl != nullptr) {
// In ES6, conflicting variable bindings are early errors.
const AstRawString* name = decl->proxy()->raw_name();
int position = decl->proxy()->position();
@@ -3263,7 +3383,7 @@ void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
// Parser support
bool Parser::TargetStackContainsLabel(const AstRawString* label) {
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
if (ContainsLabel(t->statement()->labels(), label)) return true;
}
return false;
@@ -3272,31 +3392,31 @@ bool Parser::TargetStackContainsLabel(const AstRawString* label) {
BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
bool* ok) {
- bool anonymous = label == NULL;
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ bool anonymous = label == nullptr;
+ for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
BreakableStatement* stat = t->statement();
if ((anonymous && stat->is_target_for_anonymous()) ||
(!anonymous && ContainsLabel(stat->labels(), label))) {
return stat;
}
}
- return NULL;
+ return nullptr;
}
IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
bool* ok) {
- bool anonymous = label == NULL;
- for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
+ bool anonymous = label == nullptr;
+ for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
IterationStatement* stat = t->statement()->AsIterationStatement();
- if (stat == NULL) continue;
+ if (stat == nullptr) continue;
DCHECK(stat->is_target_for_anonymous());
if (anonymous || ContainsLabel(stat->labels(), label)) {
return stat;
}
}
- return NULL;
+ return nullptr;
}
@@ -3311,17 +3431,6 @@ void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
}
}
-void Parser::ReportErrors(Isolate* isolate, Handle<Script> script) {
- if (stack_overflow()) {
- isolate->StackOverflow();
- } else {
- DCHECK(pending_error_handler_.has_pending_error());
- // Internalize ast values for throwing the pending error.
- ast_value_factory()->Internalize(isolate);
- pending_error_handler_.ThrowPendingError(isolate, script);
- }
-}
-
void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {
// Move statistics to Isolate.
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
@@ -3341,10 +3450,15 @@ void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {
}
void Parser::ParseOnBackground(ParseInfo* info) {
+ RuntimeCallTimerScope runtimeTimer(runtime_call_stats_,
+ &RuntimeCallStats::ParseBackgroundProgram);
parsing_on_main_thread_ = false;
+ if (!info->script().is_null()) {
+ set_script_id(info->script()->id());
+ }
- DCHECK(info->literal() == NULL);
- FunctionLiteral* result = NULL;
+ DCHECK_NULL(info->literal());
+ FunctionLiteral* result = nullptr;
ParserLogger logger;
if (produce_cached_parse_data()) {
@@ -3380,17 +3494,8 @@ void Parser::ParseOnBackground(ParseInfo* info) {
// care of calling AstValueFactory::Internalize just before compilation.
if (produce_cached_parse_data()) {
- if (result != NULL) *info->cached_data() = logger.GetScriptData();
- log_ = NULL;
- }
- if (runtime_call_stats_ &&
- (FLAG_runtime_stats &
- v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
- auto value = v8::tracing::TracedValue::Create();
- runtime_call_stats_->Dump(value.get());
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats"),
- "V8.RuntimeStats", TRACE_EVENT_SCOPE_THREAD,
- "runtime-call-stats", std::move(value));
+ if (result != nullptr) *info->cached_data() = logger.GetScriptData();
+ log_ = nullptr;
}
}
@@ -3400,17 +3505,13 @@ Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
void Parser::AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
bool tail) {
- DCHECK(should_cook || allow_harmony_template_escapes());
- int pos = scanner()->location().beg_pos;
int end = scanner()->location().end_pos - (tail ? 1 : 2);
- const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
- Literal* raw = factory()->NewStringLiteral(trv, pos);
+ const AstRawString* raw = scanner()->CurrentRawSymbol(ast_value_factory());
if (should_cook) {
- const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
- Literal* cooked = factory()->NewStringLiteral(tv, pos);
+ const AstRawString* cooked = scanner()->CurrentSymbol(ast_value_factory());
(*state)->AddTemplateSpan(cooked, raw, end, zone());
} else {
- (*state)->AddTemplateSpan(GetLiteralUndefined(pos), raw, end, zone());
+ (*state)->AddTemplateSpan(nullptr, raw, end, zone());
}
}
@@ -3425,46 +3526,54 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
Expression* tag) {
TemplateLiteral* lit = *state;
int pos = lit->position();
- const ZoneList<Literal*>* cooked_strings = lit->cooked();
- const ZoneList<Literal*>* raw_strings = lit->raw();
+ const ZoneList<const AstRawString*>* cooked_strings = lit->cooked();
+ const ZoneList<const AstRawString*>* raw_strings = lit->raw();
const ZoneList<Expression*>* expressions = lit->expressions();
DCHECK_EQ(cooked_strings->length(), raw_strings->length());
DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
if (!tag) {
- // Build tree of BinaryOps to simplify code-generation
- Expression* expr = cooked_strings->at(0);
+ Expression* first_string =
+ factory()->NewStringLiteral(cooked_strings->at(0), kNoSourcePosition);
+ if (expressions->length() == 0) return first_string;
+
+ // Build N-ary addition op to simplify code-generation.
+ // TODO(leszeks): Could we just store this expression in the
+ // TemplateLiteralState and build it as we go?
+ NaryOperation* expr = factory()->NewNaryOperation(
+ Token::ADD, first_string, 2 * expressions->length());
+
int i = 0;
while (i < expressions->length()) {
Expression* sub = expressions->at(i++);
- Expression* cooked_str = cooked_strings->at(i);
+ const AstRawString* cooked_str = cooked_strings->at(i);
+ DCHECK_NOT_NULL(cooked_str);
// Let middle be ToString(sub).
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(1, zone());
args->Add(sub, zone());
- Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
- args, sub->position());
+ Expression* sub_to_string = factory()->NewCallRuntime(
+ Runtime::kInlineToString, args, sub->position());
- expr = factory()->NewBinaryOperation(
- Token::ADD, factory()->NewBinaryOperation(
- Token::ADD, expr, middle, expr->position()),
- cooked_str, sub->position());
+ expr->AddSubsequent(sub_to_string, sub->position());
+ expr->AddSubsequent(
+ factory()->NewStringLiteral(cooked_str, kNoSourcePosition),
+ sub->position());
}
return expr;
} else {
// GetTemplateObject
const int32_t hash = ComputeTemplateLiteralHash(lit);
- Expression* template_object = factory()->NewGetTemplateObject(
- const_cast<ZoneList<Literal*>*>(cooked_strings),
- const_cast<ZoneList<Literal*>*>(raw_strings), hash, pos);
+ Expression* template_object =
+ factory()->NewGetTemplateObject(cooked_strings, raw_strings, hash, pos);
// Call TagFn
ZoneList<Expression*>* call_args =
new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
call_args->Add(template_object, zone());
call_args->AddAll(*expressions, zone());
- return factory()->NewCall(tag, call_args, pos);
+ return factory()->NewTaggedTemplate(tag, call_args, pos);
}
}
@@ -3483,7 +3592,7 @@ uint32_t HalfAvalance(uint32_t a) {
} // namespace
int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
- const ZoneList<Literal*>* raw_strings = lit->raw();
+ const ZoneList<const AstRawString*>* raw_strings = lit->raw();
int total = raw_strings->length();
DCHECK_GT(total, 0);
@@ -3495,8 +3604,7 @@ int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
running_hash, "${}", 3);
}
- const AstRawString* raw_string =
- raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
+ 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(
@@ -3700,53 +3808,18 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
body->Add(block, zone());
}
-class NonPatternRewriter : public AstExpressionRewriter {
- public:
- NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
- : AstExpressionRewriter(stack_limit), parser_(parser) {}
- ~NonPatternRewriter() override {}
-
- private:
- bool RewriteExpression(Expression* expr) override {
- if (expr->IsRewritableExpression()) return true;
- // Rewrite only what could have been a pattern but is not.
- if (expr->IsArrayLiteral()) {
- // Spread rewriting in array literals.
- ArrayLiteral* lit = expr->AsArrayLiteral();
- VisitExpressions(lit->values());
- replacement_ = parser_->RewriteSpreads(lit);
- return false;
- }
- if (expr->IsObjectLiteral()) {
- return true;
- }
- if (expr->IsBinaryOperation() &&
- expr->AsBinaryOperation()->op() == Token::COMMA) {
- return true;
- }
- // Everything else does not need rewriting.
- return false;
- }
-
- void VisitLiteralProperty(LiteralProperty* property) override {
- if (property == nullptr) return;
- // Do not rewrite (computed) key expressions
- AST_REWRITE_PROPERTY(Expression, property, value);
- }
-
- Parser* parser_;
-};
-
void Parser::RewriteNonPattern(bool* ok) {
ValidateExpression(CHECK_OK_VOID);
auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
int begin = classifier()->GetNonPatternBegin();
int end = non_patterns_to_rewrite->length();
if (begin < end) {
- NonPatternRewriter rewriter(stack_limit_, this);
for (int i = begin; i < end; i++) {
- DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
- rewriter.Rewrite(non_patterns_to_rewrite->at(i));
+ RewritableExpression* expr = non_patterns_to_rewrite->at(i);
+ // TODO(adamk): Make this more typesafe.
+ DCHECK(expr->expression()->IsArrayLiteral());
+ ArrayLiteral* lit = expr->expression()->AsArrayLiteral();
+ expr->Rewrite(RewriteSpreads(lit));
}
non_patterns_to_rewrite->Rewind(begin);
}
@@ -3759,73 +3832,19 @@ void Parser::RewriteDestructuringAssignments() {
for (int i = assignments.length() - 1; i >= 0; --i) {
// Rewrite list in reverse, so that nested assignment patterns are rewritten
// correctly.
- const DestructuringAssignment& pair = assignments.at(i);
- RewritableExpression* to_rewrite =
- pair.assignment->AsRewritableExpression();
+ RewritableExpression* to_rewrite = assignments[i];
DCHECK_NOT_NULL(to_rewrite);
if (!to_rewrite->is_rewritten()) {
// Since this function is called at the end of parsing the program,
// pair.scope may already have been removed by FinalizeBlockScope in the
// meantime.
- Scope* scope = pair.scope->GetUnremovedScope();
+ Scope* scope = to_rewrite->scope()->GetUnremovedScope();
BlockState block_state(&scope_, scope);
RewriteDestructuringAssignment(to_rewrite);
}
}
}
-Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
- int pos) {
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
- args->Add(left, zone());
- args->Add(right, zone());
- return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
-}
-
-Expression* Parser::RewriteAssignExponentiation(Expression* left,
- Expression* right, int pos) {
- ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
- if (left->IsVariableProxy()) {
- VariableProxy* lhs = left->AsVariableProxy();
-
- Expression* result;
- DCHECK_NOT_NULL(lhs->raw_name());
- result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position());
- args->Add(left, zone());
- args->Add(right, zone());
- Expression* call =
- factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
- return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
- } else if (left->IsProperty()) {
- Property* prop = left->AsProperty();
- auto temp_obj = NewTemporary(ast_value_factory()->empty_string());
- auto temp_key = NewTemporary(ast_value_factory()->empty_string());
- Expression* assign_obj = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
- kNoSourcePosition);
- Expression* assign_key = factory()->NewAssignment(
- Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
- kNoSourcePosition);
- args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
- factory()->NewVariableProxy(temp_key),
- left->position()),
- zone());
- args->Add(right, zone());
- Expression* call =
- factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
- Expression* target = factory()->NewProperty(
- factory()->NewVariableProxy(temp_obj),
- factory()->NewVariableProxy(temp_key), kNoSourcePosition);
- Expression* assign =
- factory()->NewAssignment(Token::ASSIGN, target, call, pos);
- return factory()->NewBinaryOperation(
- Token::COMMA, assign_obj,
- factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
- pos);
- }
- UNREACHABLE();
-}
-
Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
// Array literals containing spreads are rewritten using do expressions, e.g.
// [1, 2, 3, ...x, 4, ...y, 5]
@@ -3860,8 +3879,7 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
// %AppendElement($R, value)
// or, in case of a hole,
// ++($R.length)
- if (!value->IsLiteral() ||
- !value->AsLiteral()->raw_value()->IsTheHole()) {
+ if (!value->IsTheHoleLiteral()) {
ZoneList<Expression*>* append_element_args = NewExpressionList(2);
append_element_args->Add(factory()->NewVariableProxy(result), zone());
append_element_args->Add(value, zone());
@@ -3914,14 +3932,12 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
return factory()->NewDoExpression(do_block, result, lit->position());
}
-void Parser::QueueDestructuringAssignmentForRewriting(Expression* expr) {
- DCHECK(expr->IsRewritableExpression());
- function_state_->AddDestructuringAssignment(
- DestructuringAssignment(expr, scope()));
+void Parser::QueueDestructuringAssignmentForRewriting(
+ RewritableExpression* expr) {
+ function_state_->AddDestructuringAssignment(expr);
}
-void Parser::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
- DCHECK(expr->IsRewritableExpression());
+void Parser::QueueNonPatternForRewriting(RewritableExpression* expr, bool* ok) {
function_state_->AddNonPatternForRewriting(expr, ok);
}
@@ -4171,7 +4187,7 @@ void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition,
Block* block = factory()->NewBlock(2, true);
Expression* proxy = factory()->NewVariableProxy(completion);
BuildIteratorCloseForCompletion(block->statements(), iter, proxy, type);
- DCHECK(block->statements()->length() == 2);
+ DCHECK_EQ(block->statements()->length(), 2);
maybe_close = IgnoreCompletion(factory()->NewIfStatement(
condition, block, factory()->NewEmptyStatement(nopos), nopos));
diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h
index 296762c14d..aa800dafc5 100644
--- a/deps/v8/src/parsing/parser.h
+++ b/deps/v8/src/parsing/parser.h
@@ -17,7 +17,6 @@
#include "src/parsing/preparse-data-format.h"
#include "src/parsing/preparse-data.h"
#include "src/parsing/preparser.h"
-#include "src/pending-compilation-error-handler.h"
#include "src/utils.h"
namespace v8 {
@@ -31,6 +30,7 @@ class ParseInfo;
class ScriptData;
class ParserTarget;
class ParserTargetScope;
+class PendingCompilationErrorHandler;
class PreParsedScopeData;
class FunctionEntry BASE_EMBEDDED {
@@ -85,7 +85,7 @@ class ParseData {
if (pd->IsSane()) return pd;
cached_data->Reject();
delete pd;
- return NULL;
+ return nullptr;
}
void Initialize();
@@ -167,6 +167,7 @@ struct ParserTypes<Parser> {
typedef ObjectLiteral::Property* ObjectLiteralProperty;
typedef ClassLiteral::Property* ClassLiteralProperty;
typedef v8::internal::Suspend* Suspend;
+ typedef v8::internal::RewritableExpression* RewritableExpression;
typedef ZoneList<v8::internal::Expression*>* ExpressionList;
typedef ZoneList<ObjectLiteral::Property*>* ObjectPropertyList;
typedef ZoneList<ClassLiteral::Property*>* ClassPropertyList;
@@ -190,9 +191,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
explicit Parser(ParseInfo* info);
~Parser() {
delete reusable_preparser_;
- reusable_preparser_ = NULL;
+ reusable_preparser_ = nullptr;
delete cached_parse_data_;
- cached_parse_data_ = NULL;
+ cached_parse_data_ = nullptr;
}
static bool IsPreParser() { return false; }
@@ -210,8 +211,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void DeserializeScopeChain(ParseInfo* info,
MaybeHandle<ScopeInfo> maybe_outer_scope_info);
- // Handle errors detected during parsing
- void ReportErrors(Isolate* isolate, Handle<Script> script);
// Move statistics to Isolate
void UpdateStatistics(Isolate* isolate, Handle<Script> script);
void HandleSourceURLComments(Isolate* isolate, Handle<Script> script);
@@ -257,7 +256,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void PrepareGeneratorVariables();
- // Returns NULL if parsing failed.
+ // Returns nullptr if parsing failed.
FunctionLiteral* ParseProgram(Isolate* isolate, ParseInfo* info);
FunctionLiteral* ParseFunction(Isolate* isolate, ParseInfo* info,
@@ -283,22 +282,20 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
PreParser* reusable_preparser() {
- if (reusable_preparser_ == NULL) {
+ if (reusable_preparser_ == nullptr) {
reusable_preparser_ =
new PreParser(zone(), &scanner_, stack_limit_, ast_value_factory(),
- &pending_error_handler_, runtime_call_stats_,
- parsing_on_main_thread_);
+ pending_error_handler(), runtime_call_stats_, logger_,
+ -1, parsing_module_, parsing_on_main_thread_);
#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_class_fields);
- SET_ALLOW(harmony_object_rest_spread);
+ SET_ALLOW(harmony_public_fields);
SET_ALLOW(harmony_dynamic_import);
SET_ALLOW(harmony_import_meta);
SET_ALLOW(harmony_async_iteration);
- SET_ALLOW(harmony_template_escapes);
- SET_ALLOW(harmony_restrictive_generators);
+ SET_ALLOW(harmony_bigint);
#undef SET_ALLOW
}
return reusable_preparser_;
@@ -348,15 +345,18 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void ParseAndRewriteAsyncGeneratorFunctionBody(int pos, FunctionKind kind,
ZoneList<Statement*>* body,
bool* ok);
- void CreateFunctionNameAssignment(const AstRawString* function_name, int pos,
- FunctionLiteral::FunctionType function_type,
- DeclarationScope* function_scope,
- ZoneList<Statement*>* result, int index);
+ void DeclareFunctionNameVar(const AstRawString* function_name,
+ FunctionLiteral::FunctionType function_type,
+ DeclarationScope* function_scope);
Statement* DeclareFunction(const AstRawString* variable_name,
FunctionLiteral* function, VariableMode mode,
int pos, bool is_sloppy_block_function,
ZoneList<const AstRawString*>* names, bool* ok);
+ Variable* CreateSyntheticContextVariable(const AstRawString* synthetic_name,
+ bool* ok);
+ FunctionLiteral* CreateInitializerFunction(
+ DeclarationScope* scope, ZoneList<ClassLiteral::Property*>* fields);
V8_INLINE Statement* DeclareClass(const AstRawString* variable_name,
Expression* value,
ZoneList<const AstRawString*>* names,
@@ -368,6 +368,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ClassLiteralProperty* property,
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
+ bool is_computed_name,
ClassInfo* class_info, bool* ok);
V8_INLINE Expression* RewriteClassLiteral(Scope* block_scope,
const AstRawString* name,
@@ -426,9 +427,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
int function_token_position, FunctionLiteral::FunctionType type,
LanguageMode language_mode, bool* ok);
- // Get odd-ball literals.
- Literal* GetLiteralUndefined(int position);
-
// Check if the scope has conflicting var/let declarations from different
// scopes. This covers for example
//
@@ -499,13 +497,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
TemplateLiteral(Zone* zone, int pos)
: cooked_(8, zone), raw_(8, zone), expressions_(8, zone), pos_(pos) {}
- const ZoneList<Literal*>* cooked() const { return &cooked_; }
- const ZoneList<Literal*>* raw() const { return &raw_; }
+ const ZoneList<const AstRawString*>* cooked() const { return &cooked_; }
+ const ZoneList<const AstRawString*>* raw() const { return &raw_; }
const ZoneList<Expression*>* expressions() const { return &expressions_; }
int position() const { return pos_; }
- void AddTemplateSpan(Literal* cooked, Literal* raw, int end, Zone* zone) {
- DCHECK_NOT_NULL(cooked);
+ void AddTemplateSpan(const AstRawString* cooked, const AstRawString* raw,
+ int end, Zone* zone) {
DCHECK_NOT_NULL(raw);
cooked_.Add(cooked, zone);
raw_.Add(raw, zone);
@@ -517,8 +515,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
private:
- ZoneList<Literal*> cooked_;
- ZoneList<Literal*> raw_;
+ ZoneList<const AstRawString*> cooked_;
+ ZoneList<const AstRawString*> raw_;
ZoneList<Expression*> expressions_;
int pos_;
};
@@ -529,9 +527,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// "should_cook" means that the span can be "cooked": in tagged template
// literals, both the raw and "cooked" representations are available to user
// code ("cooked" meaning that escape sequences are converted to their
- // interpreted values). With the --harmony-template-escapes flag, invalid
- // escape sequences cause the cooked span to be represented by undefined,
- // instead of being a syntax error.
+ // interpreted values). Invalid escape sequences cause the cooked span
+ // to be represented by undefined, instead of being a syntax error.
// "tail" indicates that this span is the last in the literal.
void AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
bool tail);
@@ -554,20 +551,15 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Rewrite all DestructuringAssignments in the current FunctionState.
V8_INLINE void RewriteDestructuringAssignments();
- V8_INLINE Expression* RewriteExponentiation(Expression* left,
- Expression* right, int pos);
- V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
- Expression* right, int pos);
-
- friend class NonPatternRewriter;
- V8_INLINE Expression* RewriteSpreads(ArrayLiteral* lit);
+ Expression* RewriteSpreads(ArrayLiteral* lit);
// Rewrite expressions that are not used as patterns
V8_INLINE void RewriteNonPattern(bool* ok);
V8_INLINE void QueueDestructuringAssignmentForRewriting(
- Expression* assignment);
- V8_INLINE void QueueNonPatternForRewriting(Expression* expr, bool* ok);
+ RewritableExpression* assignment);
+ V8_INLINE void QueueNonPatternForRewriting(RewritableExpression* expr,
+ bool* ok);
friend class InitializerRewriter;
void RewriteParameterInitializer(Expression* expr);
@@ -623,9 +615,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Returns true if the expression is of type "this.foo".
V8_INLINE static bool IsThisProperty(Expression* expression) {
- DCHECK(expression != NULL);
+ DCHECK_NOT_NULL(expression);
Property* property = expression->AsProperty();
- return property != NULL && property->obj()->IsVariableProxy() &&
+ return property != nullptr && property->obj()->IsVariableProxy() &&
property->obj()->AsVariableProxy()->is_this();
}
@@ -689,8 +681,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ExpressionStatement* e_stat = statement->AsExpressionStatement();
if (e_stat == nullptr) return false;
Literal* literal = e_stat->expression()->AsLiteral();
- if (literal == nullptr || !literal->raw_value()->IsString()) return false;
- return arg == nullptr || literal->raw_value()->AsString() == arg;
+ if (literal == nullptr || !literal->IsString()) return false;
+ return arg == nullptr || literal->AsRawString() == arg;
}
V8_INLINE void GetDefaultStrings(
@@ -740,7 +732,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// literal so it can be added as a constant function property.
V8_INLINE static void CheckAssigningFunctionLiteralToProperty(
Expression* left, Expression* right) {
- DCHECK(left != NULL);
+ DCHECK_NOT_NULL(left);
if (left->IsProperty() && right->IsFunctionLiteral()) {
right->AsFunctionLiteral()->set_pretenure();
}
@@ -761,6 +753,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
bool ShortcutNumericLiteralBinaryExpression(Expression** x, Expression* y,
Token::Value op, int pos);
+ // Returns true if we have a binary operation between a binary/n-ary
+ // expression (with the same operation) and a value, which can be collapsed
+ // into a single n-ary expression. In that case, *x will be changed to an
+ // n-ary expression.
+ bool CollapseNaryExpression(Expression** x, Expression* y, Token::Value op,
+ int pos, const SourceRange& range);
+
// Rewrites the following types of unary expressions:
// not <literal> -> true / false
// + <numeric literal> -> <numeric literal>
@@ -798,10 +797,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
// Reporting errors.
- V8_INLINE void ReportMessageAt(Scanner::Location source_location,
- MessageTemplate::Template message,
- const char* arg = NULL,
- ParseErrorType error_type = kSyntaxError) {
+ void ReportMessageAt(Scanner::Location source_location,
+ MessageTemplate::Template message,
+ const char* arg = nullptr,
+ ParseErrorType error_type = kSyntaxError) {
if (stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at
@@ -809,15 +808,15 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// and we want to report the stack overflow later.
return;
}
- pending_error_handler_.ReportMessageAt(source_location.beg_pos,
- source_location.end_pos, message,
- arg, error_type);
+ pending_error_handler()->ReportMessageAt(source_location.beg_pos,
+ source_location.end_pos, message,
+ arg, error_type);
}
- V8_INLINE void ReportMessageAt(Scanner::Location source_location,
- MessageTemplate::Template message,
- const AstRawString* arg,
- ParseErrorType error_type = kSyntaxError) {
+ void ReportMessageAt(Scanner::Location source_location,
+ MessageTemplate::Template message,
+ const AstRawString* arg,
+ ParseErrorType error_type = kSyntaxError) {
if (stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at
@@ -825,9 +824,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// and we want to report the stack overflow later.
return;
}
- pending_error_handler_.ReportMessageAt(source_location.beg_pos,
- source_location.end_pos, message,
- arg, error_type);
+ pending_error_handler()->ReportMessageAt(source_location.beg_pos,
+ source_location.end_pos, message,
+ arg, error_type);
}
// "null" return type creators.
@@ -845,20 +844,15 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return subject == nullptr;
}
- // Non-NULL empty string.
+ // Non-null empty string.
V8_INLINE const AstRawString* EmptyIdentifierString() const {
return ast_value_factory()->empty_string();
}
- // Odd-ball literal creators.
- V8_INLINE Literal* GetLiteralTheHole(int position) {
- return factory()->NewTheHoleLiteral(kNoSourcePosition);
- }
-
// Producing data during the recursive descent.
V8_INLINE const AstRawString* GetSymbol() const {
const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
- DCHECK(result != NULL);
+ DCHECK_NOT_NULL(result);
return result;
}
@@ -882,6 +876,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Expression* NewSuperCallReference(int pos);
Expression* NewTargetExpression(int pos);
Expression* FunctionSentExpression(int pos);
+ Expression* ImportMetaExpression(int pos);
Literal* ExpressionFromLiteral(Token::Value token, int pos);
@@ -995,7 +990,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return function_state_->GetReportedErrorList();
}
- V8_INLINE ZoneList<Expression*>* GetNonPatternList() const {
+ V8_INLINE ZoneList<RewritableExpression*>* GetNonPatternList() const {
return function_state_->non_patterns_to_rewrite();
}
@@ -1009,6 +1004,32 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return parameters_end_pos_ != kNoSourcePosition;
}
+ V8_INLINE void ConvertBinaryToNaryOperationSourceRange(
+ BinaryOperation* binary_op, NaryOperation* nary_op) {
+ if (source_range_map_ == nullptr) return;
+ DCHECK_NULL(source_range_map_->Find(nary_op));
+
+ BinaryOperationSourceRanges* ranges =
+ static_cast<BinaryOperationSourceRanges*>(
+ source_range_map_->Find(binary_op));
+ if (ranges == nullptr) return;
+
+ SourceRange range = ranges->GetRange(SourceRangeKind::kRight);
+ source_range_map_->Insert(
+ nary_op, new (zone()) NaryOperationSourceRanges(zone(), range));
+ }
+
+ V8_INLINE void AppendNaryOperationSourceRange(NaryOperation* node,
+ const SourceRange& range) {
+ if (source_range_map_ == nullptr) return;
+ NaryOperationSourceRanges* ranges =
+ static_cast<NaryOperationSourceRanges*>(source_range_map_->Find(node));
+ if (ranges == nullptr) return;
+
+ ranges->AddRange(range);
+ DCHECK_EQ(node->subsequent_length(), ranges->RangeCount());
+ }
+
V8_INLINE void RecordBlockSourceRange(Block* node,
int32_t continuation_position) {
if (source_range_map_ == nullptr) return;
@@ -1032,6 +1053,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
new (zone()) ConditionalSourceRanges(then_range, else_range));
}
+ V8_INLINE void RecordBinaryOperationSourceRange(
+ Expression* node, const SourceRange& right_range) {
+ if (source_range_map_ == nullptr) return;
+ source_range_map_->Insert(node->AsBinaryOperation(),
+ new (zone())
+ BinaryOperationSourceRanges(right_range));
+ }
+
V8_INLINE void RecordJumpStatementSourceRange(Statement* node,
int32_t continuation_position) {
if (source_range_map_ == nullptr) return;
@@ -1113,8 +1142,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
ScriptCompiler::CompileOptions compile_options_;
ParseData* cached_parse_data_;
- PendingCompilationErrorHandler pending_error_handler_;
-
// Other information which will be stored in Parser and moved to Isolate after
// parsing.
int use_counts_[v8::Isolate::kUseCounterFeatureCount];
diff --git a/deps/v8/src/parsing/parsing.cc b/deps/v8/src/parsing/parsing.cc
index 7a280b00b8..bc3c6dec7b 100644
--- a/deps/v8/src/parsing/parsing.cc
+++ b/deps/v8/src/parsing/parsing.cc
@@ -40,7 +40,8 @@ bool ParseProgram(ParseInfo* info, Isolate* isolate) {
result = parser.ParseProgram(isolate, info);
info->set_literal(result);
if (result == nullptr) {
- parser.ReportErrors(isolate, info->script());
+ info->pending_error_handler()->ReportErrors(isolate, info->script(),
+ info->ast_value_factory());
} else {
result->scope()->AttachOuterScopeInfo(info, isolate);
info->set_language_mode(info->literal()->language_mode());
@@ -74,7 +75,8 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
result = parser.ParseFunction(isolate, info, shared_info);
info->set_literal(result);
if (result == nullptr) {
- parser.ReportErrors(isolate, info->script());
+ info->pending_error_handler()->ReportErrors(isolate, info->script(),
+ info->ast_value_factory());
} else {
result->scope()->AttachOuterScopeInfo(info, isolate);
}
diff --git a/deps/v8/src/parsing/pattern-rewriter.cc b/deps/v8/src/parsing/pattern-rewriter.cc
index 2f5d248aed..faecb5bb0c 100644
--- a/deps/v8/src/parsing/pattern-rewriter.cc
+++ b/deps/v8/src/parsing/pattern-rewriter.cc
@@ -131,7 +131,7 @@ void Parser::RewriteDestructuringAssignment(RewritableExpression* to_rewrite) {
Expression* Parser::RewriteDestructuringAssignment(Assignment* assignment) {
DCHECK_NOT_NULL(assignment);
DCHECK_EQ(Token::ASSIGN, assignment->op());
- auto to_rewrite = factory()->NewRewritableExpression(assignment);
+ auto to_rewrite = factory()->NewRewritableExpression(assignment, scope());
RewriteDestructuringAssignment(to_rewrite);
return to_rewrite->expression();
}
@@ -220,7 +220,7 @@ void PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
if (!*ok_) return;
DCHECK_NOT_NULL(var);
DCHECK(proxy->is_resolved());
- DCHECK(initializer_position_ != kNoSourcePosition);
+ DCHECK_NE(initializer_position_, kNoSourcePosition);
var->set_initializer_position(initializer_position_);
Scope* declaration_scope =
@@ -419,7 +419,7 @@ void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
}
- DCHECK(rest_runtime_callargs != nullptr);
+ DCHECK_NOT_NULL(rest_runtime_callargs);
rest_runtime_callargs->Add(excluded_property, zone());
}
@@ -539,7 +539,7 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
}
block_->statements()->Add(if_not_done, zone());
- if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+ if (!value->IsTheHoleLiteral()) {
{
// completion = kAbruptCompletion;
Expression* proxy = factory()->NewVariableProxy(completion);
@@ -726,6 +726,7 @@ void PatternRewriter::VisitProperty(v8::internal::Property* node) {
void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); }
NOT_A_PATTERN(BinaryOperation)
+NOT_A_PATTERN(NaryOperation)
NOT_A_PATTERN(Block)
NOT_A_PATTERN(BreakStatement)
NOT_A_PATTERN(Call)
@@ -772,6 +773,7 @@ NOT_A_PATTERN(WithStatement)
NOT_A_PATTERN(Yield)
NOT_A_PATTERN(YieldStar)
NOT_A_PATTERN(Await)
+NOT_A_PATTERN(InitializeClassFieldsStatement)
#undef NOT_A_PATTERN
} // namespace internal
diff --git a/deps/v8/src/parsing/preparsed-scope-data.cc b/deps/v8/src/parsing/preparsed-scope-data.cc
index 8d2ce2d1a5..7191639cf8 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.cc
+++ b/deps/v8/src/parsing/preparsed-scope-data.cc
@@ -20,27 +20,27 @@ class ScopeCallsSloppyEvalField : public BitField<bool, 0, 1> {};
class InnerScopeCallsEvalField
: public BitField<bool, ScopeCallsSloppyEvalField::kNext, 1> {};
-class VariableIsUsedField : public BitField16<bool, 0, 1> {};
-class VariableMaybeAssignedField
- : public BitField16<bool, VariableIsUsedField::kNext, 1> {};
+class VariableMaybeAssignedField : public BitField8<bool, 0, 1> {};
class VariableContextAllocatedField
- : public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {};
+ : public BitField8<bool, VariableMaybeAssignedField::kNext, 1> {};
const int kMagicValue = 0xc0de0de;
#ifdef DEBUG
const size_t kUint32Size = 5;
const size_t kUint8Size = 2;
+const size_t kQuarterMarker = 0;
#else
const size_t kUint32Size = 4;
const size_t kUint8Size = 1;
#endif
+const int kPlaceholderSize = kUint32Size;
const int kSkippableFunctionDataSize = 4 * kUint32Size + 1 * kUint8Size;
-STATIC_ASSERT(LANGUAGE_END == 2);
-class LanguageField : public BitField<int, 0, 1> {};
-class UsesSuperField : public BitField<bool, LanguageField::kNext, 1> {};
+class LanguageField : public BitField8<LanguageMode, 0, 1> {};
+class UsesSuperField : public BitField8<bool, LanguageField::kNext, 1> {};
+STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
} // namespace
@@ -98,6 +98,7 @@ void ProducedPreParsedScopeData::ByteData::WriteUint32(uint32_t data) {
for (int i = 0; i < 4; ++i) {
backing_store_.push_back(*d++);
}
+ free_quarters_in_last_byte_ = 0;
}
void ProducedPreParsedScopeData::ByteData::OverwriteFirstUint32(uint32_t data) {
@@ -120,6 +121,25 @@ void ProducedPreParsedScopeData::ByteData::WriteUint8(uint8_t data) {
backing_store_.push_back(kUint8Size);
#endif
backing_store_.push_back(data);
+ free_quarters_in_last_byte_ = 0;
+}
+
+void ProducedPreParsedScopeData::ByteData::WriteQuarter(uint8_t data) {
+ DCHECK_LE(data, 3);
+ if (free_quarters_in_last_byte_ == 0) {
+#ifdef DEBUG
+ // Save a marker in debug mode.
+ backing_store_.push_back(kQuarterMarker);
+#endif
+ backing_store_.push_back(0);
+ free_quarters_in_last_byte_ = 3;
+ } else {
+ --free_quarters_in_last_byte_;
+ }
+
+ uint8_t shift_amount = free_quarters_in_last_byte_ * 2;
+ DCHECK_EQ(backing_store_.back() & (3 << shift_amount), 0);
+ backing_store_.back() |= (data << shift_amount);
}
Handle<PodArray<uint8_t>> ProducedPreParsedScopeData::ByteData::Serialize(
@@ -215,7 +235,7 @@ void ProducedPreParsedScopeData::AddSkippableFunction(
uint8_t language_and_super = LanguageField::encode(language_mode) |
UsesSuperField::encode(uses_super_property);
- byte_data_->WriteUint8(language_and_super);
+ byte_data_->WriteQuarter(language_and_super);
}
void ProducedPreParsedScopeData::SaveScopeAllocationData(
@@ -224,9 +244,9 @@ void ProducedPreParsedScopeData::SaveScopeAllocationData(
DCHECK(previously_produced_preparsed_scope_data_.is_null());
// The data contains a uint32 (reserved space for scope_data_start) and
// function data items, kSkippableFunctionDataSize each.
- DCHECK_GE(byte_data_->size(), kUint32Size);
+ DCHECK_GE(byte_data_->size(), kPlaceholderSize);
DCHECK_LE(byte_data_->size(), std::numeric_limits<uint32_t>::max());
- DCHECK_EQ(byte_data_->size() % kSkippableFunctionDataSize, kUint32Size);
+ DCHECK_EQ(byte_data_->size() % kSkippableFunctionDataSize, kPlaceholderSize);
if (bailed_out_) {
return;
@@ -235,7 +255,7 @@ void ProducedPreParsedScopeData::SaveScopeAllocationData(
uint32_t scope_data_start = static_cast<uint32_t>(byte_data_->size());
// If there are no skippable inner functions, we don't need to save anything.
- if (scope_data_start == kUint32Size) {
+ if (scope_data_start == kPlaceholderSize) {
return;
}
@@ -250,6 +270,10 @@ void ProducedPreParsedScopeData::SaveScopeAllocationData(
SaveDataForScope(scope);
}
+bool ProducedPreParsedScopeData::ContainsInnerFunctions() const {
+ return byte_data_->size() > kPlaceholderSize;
+}
+
MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
Isolate* isolate) {
if (!previously_produced_preparsed_scope_data_.is_null()) {
@@ -263,7 +287,7 @@ MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
DCHECK(!ThisOrParentBailedOut());
- if (byte_data_->size() <= kUint32Size) {
+ if (byte_data_->size() <= kPlaceholderSize) {
// The data contains only the placeholder.
return MaybeHandle<PreParsedScopeData>();
}
@@ -377,14 +401,11 @@ void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) {
byte_data_->WriteUint8(name->raw_data()[i]);
}
#endif
- // FIXME(marja): Only 3 bits needed, not a full byte.
- byte variable_data = VariableIsUsedField::encode(var->is_used()) |
- VariableMaybeAssignedField::encode(
+ byte variable_data = VariableMaybeAssignedField::encode(
var->maybe_assigned() == kMaybeAssigned) |
VariableContextAllocatedField::encode(
var->has_forced_context_allocation());
-
- byte_data_->WriteUint8(variable_data);
+ byte_data_->WriteQuarter(variable_data);
}
void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
@@ -397,8 +418,8 @@ void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
if (ScopeIsSkippableFunctionScope(inner)) {
// Don't save data about function scopes, since they'll have their own
// ProducedPreParsedScopeData where their data is saved.
- DCHECK(inner->AsDeclarationScope()->produced_preparsed_scope_data() !=
- nullptr);
+ DCHECK_NOT_NULL(
+ inner->AsDeclarationScope()->produced_preparsed_scope_data());
continue;
}
scopes.push_back(inner);
@@ -424,6 +445,7 @@ int32_t ConsumedPreParsedScopeData::ByteData::ReadUint32() {
for (int i = 0; i < 4; ++i) {
*p++ = data_->get(index_++);
}
+ stored_quarters_ = 0;
return result;
}
@@ -434,9 +456,29 @@ uint8_t ConsumedPreParsedScopeData::ByteData::ReadUint8() {
// Check that there indeed is a byte following.
DCHECK_EQ(data_->get(index_++), kUint8Size);
#endif
+ stored_quarters_ = 0;
return data_->get(index_++);
}
+uint8_t ConsumedPreParsedScopeData::ByteData::ReadQuarter() {
+ DCHECK_NOT_NULL(data_);
+ if (stored_quarters_ == 0) {
+ DCHECK_GE(RemainingBytes(), kUint8Size);
+#ifdef DEBUG
+ // Check that there indeed are quarters following.
+ DCHECK_EQ(data_->get(index_++), kQuarterMarker);
+#endif
+ stored_byte_ = data_->get(index_++);
+ stored_quarters_ = 4;
+ }
+ // Read the first 2 bits from stored_byte_.
+ uint8_t result = (stored_byte_ >> 6) & 3;
+ DCHECK_LE(result, 3);
+ --stored_quarters_;
+ stored_byte_ <<= 2;
+ return result;
+}
+
ConsumedPreParsedScopeData::ConsumedPreParsedScopeData()
: scope_data_(new ByteData()), child_index_(0) {}
@@ -452,7 +494,7 @@ void ConsumedPreParsedScopeData::SetData(Handle<PreParsedScopeData> data) {
DCHECK_EQ(scope_data_->ReadUint32(), kMagicValue);
#endif
// The first data item is scope_data_start. Skip over it.
- scope_data_->SetPosition(kUint32Size);
+ scope_data_->SetPosition(kPlaceholderSize);
}
ProducedPreParsedScopeData*
@@ -472,7 +514,7 @@ ConsumedPreParsedScopeData::GetDataForSkippableFunction(
*num_parameters = scope_data_->ReadUint32();
*num_inner_functions = scope_data_->ReadUint32();
- uint8_t language_and_super = scope_data_->ReadUint8();
+ uint8_t language_and_super = scope_data_->ReadQuarter();
*language_mode = LanguageMode(LanguageField::decode(language_and_super));
*uses_super_property = UsesSuperField::decode(language_and_super);
@@ -513,13 +555,6 @@ void ConsumedPreParsedScopeData::RestoreScopeAllocationData(
DCHECK_EQ(scope_data_->RemainingBytes(), 0);
}
-void ConsumedPreParsedScopeData::SkipFunctionDataForTesting() {
- ByteData::ReadingScope reading_scope(this);
- scope_data_->SetPosition(0);
- uint32_t scope_data_start = scope_data_->ReadUint32();
- scope_data_->SetPosition(scope_data_start);
-}
-
void ConsumedPreParsedScopeData::RestoreData(Scope* scope) {
if (scope->is_declaration_scope() &&
scope->AsDeclarationScope()->is_skipped_function()) {
@@ -576,15 +611,12 @@ void ConsumedPreParsedScopeData::RestoreDataForVariable(Variable* var) {
DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
}
#endif
- CHECK_GE(scope_data_->RemainingBytes(), kUint8Size);
- uint8_t variable_data = scope_data_->ReadUint8();
- if (VariableIsUsedField::decode(variable_data)) {
- var->set_is_used();
- }
+ uint8_t variable_data = scope_data_->ReadQuarter();
if (VariableMaybeAssignedField::decode(variable_data)) {
var->set_maybe_assigned();
}
if (VariableContextAllocatedField::decode(variable_data)) {
+ var->set_is_used();
var->ForceContextAllocation();
}
}
diff --git a/deps/v8/src/parsing/preparsed-scope-data.h b/deps/v8/src/parsing/preparsed-scope-data.h
index 290bfba2fd..b621f069d2 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.h
+++ b/deps/v8/src/parsing/preparsed-scope-data.h
@@ -69,10 +69,12 @@ class ProducedPreParsedScopeData : public ZoneObject {
public:
class ByteData : public ZoneObject {
public:
- explicit ByteData(Zone* zone) : backing_store_(zone) {}
+ explicit ByteData(Zone* zone)
+ : backing_store_(zone), free_quarters_in_last_byte_(0) {}
void WriteUint32(uint32_t data);
void WriteUint8(uint8_t data);
+ void WriteQuarter(uint8_t data);
// For overwriting previously written data at position 0.
void OverwriteFirstUint32(uint32_t data);
@@ -83,6 +85,7 @@ class ProducedPreParsedScopeData : public ZoneObject {
private:
ZoneChunkList<uint8_t> backing_store_;
+ uint8_t free_quarters_in_last_byte_;
};
// Create a ProducedPreParsedScopeData object which will collect data as we
@@ -142,6 +145,8 @@ class ProducedPreParsedScopeData : public ZoneObject {
}
#endif // DEBUG
+ bool ContainsInnerFunctions() const;
+
// If there is data (if the Scope contains skippable inner functions), move
// the data into the heap and return a Handle to it; otherwise return a null
// MaybeHandle.
@@ -179,7 +184,8 @@ class ConsumedPreParsedScopeData {
public:
class ByteData {
public:
- ByteData() : data_(nullptr), index_(0) {}
+ ByteData()
+ : data_(nullptr), index_(0), stored_quarters_(0), stored_byte_(0) {}
// Reading from the ByteData is only allowed when a ReadingScope is on the
// stack. This ensures that we have a DisallowHeapAllocation in place
@@ -202,6 +208,7 @@ class ConsumedPreParsedScopeData {
int32_t ReadUint32();
uint8_t ReadUint8();
+ uint8_t ReadQuarter();
size_t RemainingBytes() const {
DCHECK_NOT_NULL(data_);
@@ -211,6 +218,8 @@ class ConsumedPreParsedScopeData {
// private:
PodArray<uint8_t>* data_;
int index_;
+ uint8_t stored_quarters_;
+ uint8_t stored_byte_;
};
ConsumedPreParsedScopeData();
@@ -229,11 +238,6 @@ class ConsumedPreParsedScopeData {
// subscopes') variables.
void RestoreScopeAllocationData(DeclarationScope* scope);
- // Skips the data about skippable functions, moves straight to the scope
- // allocation data. Useful for tests which don't want to verify only the scope
- // allocation data.
- void SkipFunctionDataForTesting();
-
private:
void RestoreData(Scope* scope);
void RestoreDataForVariable(Variable* var);
diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc
index c31fd4af8e..16879e518c 100644
--- a/deps/v8/src/parsing/preparser.cc
+++ b/deps/v8/src/parsing/preparser.cc
@@ -87,7 +87,7 @@ PreParserIdentifier PreParser::GetSymbol() const {
return symbol;
}
-PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
+PreParser::PreParseResult PreParser::PreParseProgram() {
DCHECK_NULL(scope_);
DeclarationScope* scope = NewScriptScope();
#ifdef DEBUG
@@ -97,13 +97,12 @@ PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
// ModuleDeclarationInstantiation for Source Text Module Records creates a
// new Module Environment Record whose outer lexical environment record is
// the global scope.
- if (is_module) scope = NewModuleScope(scope);
+ if (parsing_module_) scope = NewModuleScope(scope);
FunctionState top_scope(&function_state_, &scope_, scope);
original_scope_ = scope_;
bool ok = true;
int start_position = scanner()->peek_location().beg_pos;
- parsing_module_ = is_module;
PreParserStatementList body;
ParseStatementList(body, Token::EOS, &ok);
original_scope_ = nullptr;
@@ -119,14 +118,14 @@ PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
PreParser::PreParseResult PreParser::PreParseFunction(
const AstRawString* function_name, FunctionKind kind,
FunctionLiteral::FunctionType function_type,
- DeclarationScope* function_scope, bool parsing_module,
- bool is_inner_function, bool may_abort, int* use_counts,
- ProducedPreParsedScopeData** produced_preparsed_scope_data) {
+ DeclarationScope* function_scope, bool is_inner_function, bool may_abort,
+ int* use_counts, ProducedPreParsedScopeData** produced_preparsed_scope_data,
+ int script_id) {
DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
- parsing_module_ = parsing_module;
use_counts_ = use_counts;
DCHECK(!track_unresolved_variables_);
track_unresolved_variables_ = is_inner_function;
+ set_script_id(script_id);
#ifdef DEBUG
function_scope->set_is_being_lazily_parsed(true);
#endif
@@ -208,7 +207,7 @@ PreParser::PreParseResult PreParser::PreParseFunction(
if (!IsArrowFunction(kind) && track_unresolved_variables_ &&
result == kLazyParsingComplete) {
- CreateFunctionNameAssignment(function_name, function_type, function_scope);
+ DeclareFunctionNameVar(function_name, function_type, function_scope);
// Declare arguments after parsing the function since lexical 'arguments'
// masks the arguments object. Declare arguments before declaring the
@@ -224,7 +223,7 @@ PreParser::PreParseResult PreParser::PreParseFunction(
} else if (stack_overflow()) {
return kPreParseStackOverflow;
} else if (!*ok) {
- DCHECK(pending_error_handler_->has_pending_error());
+ DCHECK(pending_error_handler()->has_pending_error());
} else {
DCHECK_EQ(Token::RBRACE, scanner()->peek());
@@ -279,6 +278,9 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
runtime_call_stats_,
counters[track_unresolved_variables_][parsing_on_main_thread_]);
+ base::ElapsedTimer timer;
+ if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
+
DeclarationScope* function_scope = NewFunctionScope(kind);
function_scope->SetLanguageMode(language_mode);
@@ -344,11 +346,23 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
produced_preparsed_scope_data_scope->MarkFunctionAsSkippable(
end_position, GetLastFunctionLiteralId() - func_id);
}
- if (FLAG_trace_preparse) {
- PrintF(" [%s]: %i-%i\n",
- track_unresolved_variables_ ? "Preparse resolution"
- : "Preparse no-resolution",
- function_scope->start_position(), function_scope->end_position());
+ if (V8_UNLIKELY(FLAG_log_function_events)) {
+ double ms = timer.Elapsed().InMillisecondsF();
+ const char* event_name = track_unresolved_variables_
+ ? "preparse-resolution"
+ : "preparse-no-resolution";
+ // We might not always get a function name here. However, it can be easily
+ // reconstructed from the script id and the byte range in the log processor.
+ const char* name = "";
+ size_t name_byte_length = 0;
+ const AstRawString* string = function_name.string_;
+ if (string != nullptr) {
+ name = reinterpret_cast<const char*>(string->raw_data());
+ name_byte_length = string->byte_length();
+ }
+ logger_->FunctionEvent(
+ event_name, nullptr, script_id(), ms, function_scope->start_position(),
+ function_scope->end_position(), name, name_byte_length);
}
return Expression::Default();
diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h
index 275c5e9e0b..8c1d183fd6 100644
--- a/deps/v8/src/parsing/preparser.h
+++ b/deps/v8/src/parsing/preparser.h
@@ -192,6 +192,17 @@ class PreParserExpression {
ExpressionTypeField::encode(kCallEvalExpression));
}
+ static PreParserExpression CallTaggedTemplate() {
+ return PreParserExpression(
+ TypeField::encode(kExpression) |
+ ExpressionTypeField::encode(kCallTaggedTemplateExpression));
+ }
+
+ bool is_tagged_template() const {
+ DCHECK(IsCall());
+ return ExpressionTypeField::decode(code_) == kCallTaggedTemplateExpression;
+ }
+
static PreParserExpression SuperCallReference() {
return PreParserExpression(
TypeField::encode(kExpression) |
@@ -255,7 +266,13 @@ class PreParserExpression {
bool IsCall() const {
return TypeField::decode(code_) == kExpression &&
(ExpressionTypeField::decode(code_) == kCallExpression ||
- ExpressionTypeField::decode(code_) == kCallEvalExpression);
+ ExpressionTypeField::decode(code_) == kCallEvalExpression ||
+ ExpressionTypeField::decode(code_) ==
+ kCallTaggedTemplateExpression);
+ }
+ PreParserExpression* AsCall() {
+ if (IsCall()) return this;
+ return nullptr;
}
bool IsSuperCallReference() const {
@@ -286,6 +303,7 @@ class PreParserExpression {
int position() const { return kNoSourcePosition; }
void set_function_token_position(int position) {}
+ void set_scope(Scope* scope) {}
private:
enum Type {
@@ -304,6 +322,7 @@ class PreParserExpression {
kPropertyExpression,
kCallExpression,
kCallEvalExpression,
+ kCallTaggedTemplateExpression,
kSuperCallReference,
kAssignment
};
@@ -382,7 +401,7 @@ inline void PreParserList<PreParserExpression>::Add(
const PreParserExpression& expression, Zone* zone) {
if (expression.variables_ != nullptr) {
DCHECK(FLAG_lazy_inner_functions);
- DCHECK(zone != nullptr);
+ DCHECK_NOT_NULL(zone);
if (variables_ == nullptr) {
variables_ = new (zone) ZoneList<VariableProxy*>(1, zone);
}
@@ -524,6 +543,9 @@ class PreParserFactory {
PreParserExpression NewUndefinedLiteral(int pos) {
return PreParserExpression::Default();
}
+ PreParserExpression NewTheHoleLiteral() {
+ return PreParserExpression::Default();
+ }
PreParserExpression NewRegExpLiteral(const PreParserIdentifier& js_pattern,
int js_flags, int pos) {
return PreParserExpression::Default();
@@ -583,7 +605,7 @@ class PreParserFactory {
return PreParserExpression::Default();
}
PreParserExpression NewRewritableExpression(
- const PreParserExpression& expression) {
+ const PreParserExpression& expression, Scope* scope) {
return expression;
}
PreParserExpression NewAssignment(Token::Value op,
@@ -624,6 +646,11 @@ class PreParserFactory {
}
return PreParserExpression::Call();
}
+ PreParserExpression NewTaggedTemplate(
+ PreParserExpression expression, const PreParserExpressionList& arguments,
+ int pos) {
+ return PreParserExpression::CallTaggedTemplate();
+ }
PreParserExpression NewCallNew(const PreParserExpression& expression,
const PreParserExpressionList& arguments,
int pos) {
@@ -805,6 +832,7 @@ struct ParserTypes<PreParser> {
typedef PreParserExpression ObjectLiteralProperty;
typedef PreParserExpression ClassLiteralProperty;
typedef PreParserExpression Suspend;
+ typedef PreParserExpression RewritableExpression;
typedef PreParserExpressionList ExpressionList;
typedef PreParserExpressionList ObjectPropertyList;
typedef PreParserExpressionList ClassPropertyList;
@@ -854,14 +882,15 @@ class PreParser : public ParserBase<PreParser> {
PreParser(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
AstValueFactory* ast_value_factory,
PendingCompilationErrorHandler* pending_error_handler,
- RuntimeCallStats* runtime_call_stats,
+ RuntimeCallStats* runtime_call_stats, Logger* logger,
+ int script_id = -1, bool parsing_module = false,
bool parsing_on_main_thread = true)
: ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
- ast_value_factory, runtime_call_stats,
- parsing_on_main_thread),
+ ast_value_factory, pending_error_handler,
+ runtime_call_stats, logger, script_id,
+ parsing_module, parsing_on_main_thread),
use_counts_(nullptr),
track_unresolved_variables_(false),
- pending_error_handler_(pending_error_handler),
produced_preparsed_scope_data_(nullptr) {}
static bool IsPreParser() { return true; }
@@ -872,7 +901,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);
+ PreParseResult PreParseProgram();
// Parses a single function literal, from the opening parentheses before
// parameters to the closing brace after the body.
@@ -885,9 +914,10 @@ class PreParser : public ParserBase<PreParser> {
PreParseResult PreParseFunction(
const AstRawString* function_name, FunctionKind kind,
FunctionLiteral::FunctionType function_type,
- DeclarationScope* function_scope, bool parsing_module,
- bool track_unresolved_variables, bool may_abort, int* use_counts,
- ProducedPreParsedScopeData** produced_preparser_scope_data);
+ DeclarationScope* function_scope, bool track_unresolved_variables,
+ bool may_abort, int* use_counts,
+ ProducedPreParsedScopeData** produced_preparser_scope_data,
+ int script_id);
ProducedPreParsedScopeData* produced_preparsed_scope_data() const {
return produced_preparsed_scope_data_;
@@ -914,6 +944,10 @@ class PreParser : public ParserBase<PreParser> {
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
bool parse_lazily() const { return false; }
+ PendingCompilationErrorHandler* pending_error_handler() {
+ return pending_error_handler_;
+ }
+
V8_INLINE LazyParsingResult
SkipFunction(const AstRawString* name, FunctionKind kind,
FunctionLiteral::FunctionType function_type,
@@ -922,11 +956,12 @@ class PreParser : public ParserBase<PreParser> {
bool is_inner_function, bool may_abort, bool* ok) {
UNREACHABLE();
}
- Expression ParseFunctionLiteral(
- Identifier name, Scanner::Location function_name_location,
- FunctionNameValidity function_name_validity, FunctionKind kind,
- int function_token_pos, FunctionLiteral::FunctionType function_type,
- LanguageMode language_mode, bool* ok);
+ Expression ParseFunctionLiteral(Identifier name,
+ Scanner::Location function_name_location,
+ FunctionNameValidity function_name_validity,
+ FunctionKind kind, int function_token_pos,
+ FunctionLiteral::FunctionType function_type,
+ LanguageMode language_mode, bool* ok);
LazyParsingResult ParseStatementListAndLogFunction(
PreParserFormalParameters* formals, bool maybe_abort, bool* ok);
@@ -960,17 +995,6 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void RewriteDestructuringAssignments() {}
- V8_INLINE PreParserExpression
- RewriteExponentiation(const PreParserExpression& left,
- const PreParserExpression& right, int pos) {
- return left;
- }
- V8_INLINE PreParserExpression
- RewriteAssignExponentiation(const PreParserExpression& left,
- const PreParserExpression& right, int pos) {
- return left;
- }
-
V8_INLINE void PrepareGeneratorVariables() {}
V8_INLINE void RewriteAsyncFunctionBody(
PreParserStatementList body, PreParserStatement block,
@@ -1038,27 +1062,24 @@ class PreParser : public ParserBase<PreParser> {
int pos, FunctionKind kind, PreParserStatementList body, bool* ok) {
ParseStatementList(body, Token::RBRACE, ok);
}
- V8_INLINE void CreateFunctionNameAssignment(
+ V8_INLINE void DeclareFunctionNameVar(
const AstRawString* function_name,
FunctionLiteral::FunctionType function_type,
DeclarationScope* function_scope) {
if (track_unresolved_variables_ &&
- function_type == FunctionLiteral::kNamedExpression) {
- if (function_scope->LookupLocal(function_name) == nullptr) {
- DCHECK_EQ(function_scope, scope());
- Variable* fvar = function_scope->DeclareFunctionVar(function_name);
- fvar->set_is_used();
- }
+ function_type == FunctionLiteral::kNamedExpression &&
+ function_scope->LookupLocal(function_name) == nullptr) {
+ DCHECK_EQ(function_scope, scope());
+ function_scope->DeclareFunctionVar(function_name);
}
}
- V8_INLINE void CreateFunctionNameAssignment(
- const PreParserIdentifier& function_name, int pos,
+ V8_INLINE void DeclareFunctionNameVar(
+ const PreParserIdentifier& function_name,
FunctionLiteral::FunctionType function_type,
- DeclarationScope* function_scope, PreParserStatementList result,
- int index) {
- CreateFunctionNameAssignment(function_name.string_, function_type,
- function_scope);
+ DeclarationScope* function_scope) {
+ DeclareFunctionNameVar(function_name.string_, function_type,
+ function_scope);
}
V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
@@ -1118,7 +1139,16 @@ class PreParser : public ParserBase<PreParser> {
const PreParserExpression& property,
ClassLiteralProperty::Kind kind,
bool is_static, bool is_constructor,
- ClassInfo* class_info, bool* ok) {}
+ bool is_computed_name,
+ ClassInfo* class_info, bool* ok) {
+ if (kind == ClassLiteralProperty::FIELD && is_computed_name) {
+ scope()->DeclareVariableName(
+ ClassFieldVariableName(ast_value_factory(),
+ class_info->computed_field_count),
+ CONST);
+ }
+ }
+
V8_INLINE PreParserExpression
RewriteClassLiteral(Scope* scope, const PreParserIdentifier& name,
ClassInfo* class_info, int pos, int end_pos, bool* ok) {
@@ -1134,12 +1164,18 @@ class PreParser : public ParserBase<PreParser> {
FunctionKind kind = has_extends ? FunctionKind::kDefaultDerivedConstructor
: FunctionKind::kDefaultBaseConstructor;
DeclarationScope* function_scope = NewFunctionScope(kind);
- SetLanguageMode(function_scope, STRICT);
+ SetLanguageMode(function_scope, LanguageMode::kStrict);
function_scope->set_start_position(pos);
function_scope->set_end_position(pos);
FunctionState function_state(&function_state_, &scope_, function_scope);
GetNextFunctionLiteralId();
}
+ if (class_info->has_static_class_fields) {
+ GetNextFunctionLiteralId();
+ }
+ if (class_info->has_instance_class_fields) {
+ GetNextFunctionLiteralId();
+ }
return PreParserExpression::Default();
}
@@ -1265,6 +1301,13 @@ class PreParser : public ParserBase<PreParser> {
return false;
}
+ V8_INLINE NaryOperation* CollapseNaryExpression(PreParserExpression* x,
+ PreParserExpression y,
+ Token::Value op, int pos,
+ const SourceRange& range) {
+ return nullptr;
+ }
+
V8_INLINE PreParserExpression BuildUnaryExpression(
const PreParserExpression& expression, Token::Value op, int pos) {
return PreParserExpression::Default();
@@ -1381,13 +1424,13 @@ class PreParser : public ParserBase<PreParser> {
}
// Reporting errors.
- V8_INLINE void ReportMessageAt(Scanner::Location source_location,
- MessageTemplate::Template message,
- const char* arg = NULL,
- ParseErrorType error_type = kSyntaxError) {
- pending_error_handler_->ReportMessageAt(source_location.beg_pos,
- source_location.end_pos, message,
- arg, error_type);
+ void ReportMessageAt(Scanner::Location source_location,
+ MessageTemplate::Template message,
+ const char* arg = nullptr,
+ ParseErrorType error_type = kSyntaxError) {
+ pending_error_handler()->ReportMessageAt(source_location.beg_pos,
+ source_location.end_pos, message,
+ arg, error_type);
}
V8_INLINE void ReportMessageAt(Scanner::Location source_location,
@@ -1427,15 +1470,6 @@ class PreParser : public ParserBase<PreParser> {
return PreParserIdentifier::Default();
}
- // Odd-ball literal creators.
- V8_INLINE PreParserExpression GetLiteralTheHole(int position) {
- return PreParserExpression::Default();
- }
-
- V8_INLINE PreParserExpression GetLiteralUndefined(int position) {
- return PreParserExpression::Default();
- }
-
// Producing data during the recursive descent.
PreParserIdentifier GetSymbol() const;
@@ -1495,6 +1529,10 @@ class PreParser : public ParserBase<PreParser> {
return PreParserExpression::Default();
}
+ V8_INLINE PreParserExpression ImportMetaExpression(int pos) {
+ return PreParserExpression::Default();
+ }
+
V8_INLINE PreParserExpression ExpressionFromLiteral(Token::Value token,
int pos) {
return PreParserExpression::Default();
@@ -1650,7 +1688,6 @@ class PreParser : public ParserBase<PreParser> {
int* use_counts_;
bool track_unresolved_variables_;
PreParserLogger log_;
- PendingCompilationErrorHandler* pending_error_handler_;
ProducedPreParsedScopeData* produced_preparsed_scope_data_;
};
diff --git a/deps/v8/src/parsing/rewriter.cc b/deps/v8/src/parsing/rewriter.cc
index ddf60a5004..c31d0ea21d 100644
--- a/deps/v8/src/parsing/rewriter.cc
+++ b/deps/v8/src/parsing/rewriter.cc
@@ -263,6 +263,9 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
0, factory()->NewExpressionStatement(save, kNoSourcePosition), zone());
node->finally_block()->statements()->Add(
factory()->NewExpressionStatement(restore, kNoSourcePosition), zone());
+ // We can't tell whether the finally-block is guaranteed to set .result, so
+ // reset is_set_ before visiting the try-block.
+ is_set_ = false;
}
Visit(node->try_block());
node->set_try_block(replacement_->AsBlock());
@@ -335,6 +338,10 @@ void Processor::VisitDebuggerStatement(DebuggerStatement* node) {
replacement_ = node;
}
+void Processor::VisitInitializeClassFieldsStatement(
+ InitializeClassFieldsStatement* node) {
+ replacement_ = node;
+}
// Expressions are never visited.
#define DEF_VISIT(type) \
@@ -359,7 +366,9 @@ bool Rewriter::Rewrite(ParseInfo* info) {
RuntimeCallTimerScope runtimeTimer(
info->runtime_call_stats(),
- &RuntimeCallStats::CompileRewriteReturnResult);
+ info->on_background_thread()
+ ? &RuntimeCallStats::CompileBackgroundRewriteReturnResult
+ : &RuntimeCallStats::CompileRewriteReturnResult);
FunctionLiteral* function = info->literal();
DCHECK_NOT_NULL(function);
diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc
index 5229aed780..c5175c4de7 100644
--- a/deps/v8/src/parsing/scanner-character-streams.cc
+++ b/deps/v8/src/parsing/scanner-character-streams.cc
@@ -310,7 +310,7 @@ void Utf8ExternalStreamingStream::FillBufferFromCurrentChunk() {
unibrow::uchar t =
unibrow::Utf8::ValueOfIncrementalFinish(&current_.pos.incomplete_char);
if (t != unibrow::Utf8::kBufferEmpty) {
- DCHECK(t < unibrow::Utf16::kMaxNonSurrogateCharCode);
+ DCHECK_LT(t, unibrow::Utf16::kMaxNonSurrogateCharCode);
*cursor = static_cast<uc16>(t);
buffer_end_++;
current_.pos.chars++;
@@ -835,9 +835,9 @@ 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());
+ DCHECK_GE(start_pos, 0);
+ DCHECK_LE(start_pos, end_pos);
+ DCHECK_LE(end_pos, data->length());
if (data->IsExternalOneByteString()) {
return new ExternalOneByteStringUtf16CharacterStream(
Handle<ExternalOneByteString>::cast(data),
diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc
index f0ce0012ae..8030b93889 100644
--- a/deps/v8/src/parsing/scanner.cc
+++ b/deps/v8/src/parsing/scanner.cc
@@ -13,6 +13,7 @@
#include "src/ast/ast-value-factory.h"
#include "src/char-predicates-inl.h"
#include "src/conversions-inl.h"
+#include "src/objects/bigint.h"
#include "src/parsing/duplicate-finder.h" // For Scanner::FindSymbol
#include "src/unicode-cache-inl.h"
@@ -196,6 +197,7 @@ Scanner::Scanner(UnicodeCache* unicode_cache, int* use_counts)
octal_pos_(Location::invalid()),
octal_message_(MessageTemplate::kNone),
found_html_comment_(false),
+ allow_harmony_bigint_(false),
use_counts_(use_counts) {}
void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
@@ -211,7 +213,7 @@ void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
template <bool capture_raw, bool unicode>
uc32 Scanner::ScanHexNumber(int expected_length) {
- DCHECK(expected_length <= 4); // prevent overflow
+ DCHECK_LE(expected_length, 4); // prevent overflow
int begin = source_pos() - 2;
uc32 x = 0;
@@ -582,7 +584,7 @@ void Scanner::TryToParseSourceURLComment() {
Token::Value Scanner::SkipMultiLineComment() {
- DCHECK(c0_ == '*');
+ DCHECK_EQ(c0_, '*');
Advance();
while (c0_ != kEndOfInput) {
@@ -608,7 +610,7 @@ Token::Value Scanner::SkipMultiLineComment() {
Token::Value Scanner::ScanHtmlComment() {
// Check for <!-- comments.
- DCHECK(c0_ == '!');
+ DCHECK_EQ(c0_, '!');
Advance();
if (c0_ != '-') {
PushBack('!'); // undo Advance()
@@ -626,8 +628,8 @@ Token::Value Scanner::ScanHtmlComment() {
}
void Scanner::Scan() {
- next_.literal_chars = NULL;
- next_.raw_literal_chars = NULL;
+ next_.literal_chars = nullptr;
+ next_.raw_literal_chars = nullptr;
next_.invalid_template_escape_message = MessageTemplate::kNone;
Token::Value token;
do {
@@ -934,6 +936,7 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::IDENTIFIER:
case Token::NUMBER:
+ case Token::BIGINT:
case Token::REGEXP_LITERAL:
case Token::SMI:
case Token::STRING:
@@ -1185,8 +1188,8 @@ Token::Value Scanner::ScanTemplateSpan() {
Token::Value Scanner::ScanTemplateStart() {
- DCHECK(next_next_.token == Token::UNINITIALIZED);
- DCHECK(c0_ == '`');
+ DCHECK_EQ(next_next_.token, Token::UNINITIALIZED);
+ DCHECK_EQ(c0_, '`');
next_.location.beg_pos = source_pos();
Advance(); // Consume `
return ScanTemplateSpan();
@@ -1321,14 +1324,31 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
ScanDecimalDigits(); // optional
if (c0_ == '.') {
+ seen_period = true;
AddLiteralCharAdvance();
ScanDecimalDigits(); // optional
}
}
}
- // scan exponent, if any
- if (c0_ == 'e' || c0_ == 'E') {
+ bool is_bigint = false;
+ if (allow_harmony_bigint() && c0_ == 'n' && !seen_period &&
+ (kind == DECIMAL || kind == HEX || kind == OCTAL || kind == BINARY)) {
+ // Check that the literal is within our limits for BigInt length.
+ // For simplicity, use 4 bits per character to calculate the maximum
+ // allowed literal length.
+ static const int kMaxBigIntCharacters = BigInt::kMaxLengthBits / 4;
+ int length = source_pos() - start_pos - (kind != DECIMAL ? 2 : 0);
+ if (length > kMaxBigIntCharacters) {
+ ReportScannerError(Location(start_pos, source_pos()),
+ MessageTemplate::kBigIntTooBig);
+ return Token::ILLEGAL;
+ }
+
+ is_bigint = true;
+ Advance();
+ } 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;
@@ -1357,7 +1377,8 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
octal_pos_ = Location(start_pos, source_pos());
octal_message_ = MessageTemplate::kStrictDecimalWithLeadingZero;
}
- return Token::NUMBER;
+
+ return is_bigint ? Token::BIGINT : Token::NUMBER;
}
@@ -1481,7 +1502,7 @@ uc32 Scanner::ScanUnicodeEscape() {
static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
int input_length) {
- DCHECK(input_length >= 1);
+ DCHECK_GE(input_length, 1);
const int kMinLength = 2;
const int kMaxLength = 11;
if (input_length < kMinLength || input_length > kMaxLength) {
@@ -1728,11 +1749,7 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
flag = RegExp::kMultiline;
break;
case 's':
- if (FLAG_harmony_regexp_dotall) {
- flag = RegExp::kDotAll;
- } else {
- return Nothing<RegExp::Flags>();
- }
+ flag = RegExp::kDotAll;
break;
case 'u':
flag = RegExp::kUnicode;
@@ -1787,6 +1804,16 @@ double Scanner::DoubleValue() {
ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
}
+const char* Scanner::CurrentLiteralAsCString(Zone* zone) const {
+ DCHECK(is_literal_one_byte());
+ Vector<const uint8_t> vector = literal_one_byte_string();
+ int length = vector.length();
+ char* buffer = zone->NewArray<char>(length + 1);
+ memcpy(buffer, vector.start(), length);
+ buffer[length] = '\0';
+ return buffer;
+}
+
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 200054d893..08d77c686b 100644
--- a/deps/v8/src/parsing/scanner.h
+++ b/deps/v8/src/parsing/scanner.h
@@ -260,6 +260,8 @@ class Scanner {
double DoubleValue();
+ const char* CurrentLiteralAsCString(Zone* zone) const;
+
inline bool CurrentMatches(Token::Value token) const {
DCHECK(Token::IsKeyword(token));
return current_.token == token;
@@ -356,6 +358,9 @@ class Scanner {
bool FoundHtmlComment() const { return found_html_comment_; }
+ bool allow_harmony_bigint() const { return allow_harmony_bigint_; }
+ void set_allow_harmony_bigint(bool allow) { allow_harmony_bigint_ = allow; }
+
private:
// Scoped helper for saving & restoring scanner error state.
// This is used for tagged template literals, in which normally forbidden
@@ -409,7 +414,7 @@ class Scanner {
Vector<const uint16_t> two_byte_literal() const {
DCHECK(!is_one_byte_);
- DCHECK((position_ & 0x1) == 0);
+ DCHECK_EQ(position_ & 0x1, 0);
return Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(backing_store_.start()),
position_ >> 1);
@@ -494,18 +499,18 @@ class Scanner {
// Initialize current_ to not refer to a literal.
current_.token = Token::UNINITIALIZED;
current_.contextual_token = Token::UNINITIALIZED;
- current_.literal_chars = NULL;
- current_.raw_literal_chars = NULL;
+ current_.literal_chars = nullptr;
+ current_.raw_literal_chars = nullptr;
current_.invalid_template_escape_message = MessageTemplate::kNone;
next_.token = Token::UNINITIALIZED;
next_.contextual_token = Token::UNINITIALIZED;
- next_.literal_chars = NULL;
- next_.raw_literal_chars = NULL;
+ next_.literal_chars = nullptr;
+ next_.raw_literal_chars = nullptr;
next_.invalid_template_escape_message = MessageTemplate::kNone;
next_next_.token = Token::UNINITIALIZED;
next_next_.contextual_token = Token::UNINITIALIZED;
- next_next_.literal_chars = NULL;
- next_next_.raw_literal_chars = NULL;
+ next_next_.literal_chars = nullptr;
+ next_next_.raw_literal_chars = nullptr;
next_next_.invalid_template_escape_message = MessageTemplate::kNone;
found_html_comment_ = false;
scanner_error_ = MessageTemplate::kNone;
@@ -572,8 +577,8 @@ class Scanner {
// Stops scanning of a literal and drop the collected characters,
// e.g., due to an encountered error.
inline void DropLiteral() {
- next_.literal_chars = NULL;
- next_.raw_literal_chars = NULL;
+ next_.literal_chars = nullptr;
+ next_.raw_literal_chars = nullptr;
}
inline void AddLiteralCharAdvance() {
@@ -662,10 +667,6 @@ class Scanner {
bool is_literal_one_byte() const {
return !current_.literal_chars || current_.literal_chars->is_one_byte();
}
- int literal_length() const {
- if (current_.literal_chars) return current_.literal_chars->length();
- return Token::StringLength(current_.token);
- }
// Returns the literal string for the next token (the token that
// would be returned if Next() were called).
Vector<const uint8_t> next_literal_one_byte_string() const {
@@ -801,6 +802,9 @@ class Scanner {
// Whether this scanner encountered an HTML comment.
bool found_html_comment_;
+ // Whether to recognize BIGINT tokens.
+ bool allow_harmony_bigint_;
+
int* use_counts_;
MessageTemplate::Template scanner_error_;
diff --git a/deps/v8/src/parsing/token.h b/deps/v8/src/parsing/token.h
index 4cc4db288a..e4a4a5e587 100644
--- a/deps/v8/src/parsing/token.h
+++ b/deps/v8/src/parsing/token.h
@@ -14,7 +14,7 @@ namespace internal {
// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
// same signature M(name, string, precedence), where name is the
// symbolic token name, string is the corresponding syntactic symbol
-// (or NULL, for literals), and precedence is the precedence (or 0).
+// (or nullptr, for literals), and precedence is the precedence (or 0).
// The parameters are invoked for token categories as follows:
//
// T: Non-keyword tokens
@@ -32,171 +32,172 @@ namespace internal {
#define IGNORE_TOKEN(name, string, precedence)
-#define TOKEN_LIST(T, K, C) \
- /* End of source indicator. */ \
- T(EOS, "EOS", 0) \
- \
- /* Punctuators (ECMA-262, section 7.7, page 15). */ \
- T(LPAREN, "(", 0) \
- T(RPAREN, ")", 0) \
- T(LBRACK, "[", 0) \
- T(RBRACK, "]", 0) \
- T(LBRACE, "{", 0) \
- T(RBRACE, "}", 0) \
- T(COLON, ":", 0) \
- T(SEMICOLON, ";", 0) \
- T(PERIOD, ".", 0) \
- T(ELLIPSIS, "...", 0) \
- T(CONDITIONAL, "?", 3) \
- T(INC, "++", 0) \
- T(DEC, "--", 0) \
- T(ARROW, "=>", 0) \
- \
- /* Assignment operators. */ \
- /* IsAssignmentOp() relies on this block of enum values being */ \
- /* contiguous and sorted in the same order! */ \
- T(INIT, "=init", 2) /* AST-use only. */ \
- T(ASSIGN, "=", 2) \
- T(ASSIGN_BIT_OR, "|=", 2) \
- T(ASSIGN_BIT_XOR, "^=", 2) \
- T(ASSIGN_BIT_AND, "&=", 2) \
- T(ASSIGN_SHL, "<<=", 2) \
- T(ASSIGN_SAR, ">>=", 2) \
- T(ASSIGN_SHR, ">>>=", 2) \
- T(ASSIGN_ADD, "+=", 2) \
- T(ASSIGN_SUB, "-=", 2) \
- T(ASSIGN_MUL, "*=", 2) \
- T(ASSIGN_DIV, "/=", 2) \
- T(ASSIGN_MOD, "%=", 2) \
- T(ASSIGN_EXP, "**=", 2) \
- \
- /* Binary operators sorted by precedence. */ \
- /* IsBinaryOp() relies on this block of enum values */ \
- /* being contiguous and sorted in the same order! */ \
- T(COMMA, ",", 1) \
- T(OR, "||", 4) \
- T(AND, "&&", 5) \
- T(BIT_OR, "|", 6) \
- T(BIT_XOR, "^", 7) \
- T(BIT_AND, "&", 8) \
- T(SHL, "<<", 11) \
- T(SAR, ">>", 11) \
- T(SHR, ">>>", 11) \
- T(ADD, "+", 12) \
- T(SUB, "-", 12) \
- T(MUL, "*", 13) \
- T(DIV, "/", 13) \
- T(MOD, "%", 13) \
- T(EXP, "**", 14) \
- \
- /* Compare operators sorted by precedence. */ \
- /* IsCompareOp() relies on this block of enum values */ \
- /* being contiguous and sorted in the same order! */ \
- T(EQ, "==", 9) \
- T(NE, "!=", 9) \
- T(EQ_STRICT, "===", 9) \
- T(NE_STRICT, "!==", 9) \
- T(LT, "<", 10) \
- T(GT, ">", 10) \
- T(LTE, "<=", 10) \
- T(GTE, ">=", 10) \
- K(INSTANCEOF, "instanceof", 10) \
- K(IN, "in", 10) \
- \
- /* Unary operators. */ \
- /* IsUnaryOp() relies on this block of enum values */ \
- /* being contiguous and sorted in the same order! */ \
- T(NOT, "!", 0) \
- T(BIT_NOT, "~", 0) \
- K(DELETE, "delete", 0) \
- K(TYPEOF, "typeof", 0) \
- K(VOID, "void", 0) \
- \
- /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
- K(BREAK, "break", 0) \
- K(CASE, "case", 0) \
- K(CATCH, "catch", 0) \
- K(CONTINUE, "continue", 0) \
- K(DEBUGGER, "debugger", 0) \
- K(DEFAULT, "default", 0) \
- /* DELETE */ \
- K(DO, "do", 0) \
- K(ELSE, "else", 0) \
- K(FINALLY, "finally", 0) \
- K(FOR, "for", 0) \
- K(FUNCTION, "function", 0) \
- K(IF, "if", 0) \
- /* IN */ \
- /* INSTANCEOF */ \
- K(NEW, "new", 0) \
- K(RETURN, "return", 0) \
- K(SWITCH, "switch", 0) \
- K(THIS, "this", 0) \
- K(THROW, "throw", 0) \
- K(TRY, "try", 0) \
- /* TYPEOF */ \
- K(VAR, "var", 0) \
- /* VOID */ \
- K(WHILE, "while", 0) \
- K(WITH, "with", 0) \
- \
- /* Literals (ECMA-262, section 7.8, page 16). */ \
- K(NULL_LITERAL, "null", 0) \
- K(TRUE_LITERAL, "true", 0) \
- K(FALSE_LITERAL, "false", 0) \
- T(NUMBER, NULL, 0) \
- T(SMI, NULL, 0) \
- T(STRING, NULL, 0) \
- \
- /* Identifiers (not keywords or future reserved words). */ \
- T(IDENTIFIER, NULL, 0) \
- \
- /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
- T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
- K(ASYNC, "async", 0) \
- /* `await` is a reserved word in module code only */ \
- K(AWAIT, "await", 0) \
- K(CLASS, "class", 0) \
- K(CONST, "const", 0) \
- K(ENUM, "enum", 0) \
- K(EXPORT, "export", 0) \
- K(EXTENDS, "extends", 0) \
- K(IMPORT, "import", 0) \
- K(LET, "let", 0) \
- K(STATIC, "static", 0) \
- K(YIELD, "yield", 0) \
- K(SUPER, "super", 0) \
- \
- /* Illegal token - not able to scan. */ \
- T(ILLEGAL, "ILLEGAL", 0) \
- T(ESCAPED_KEYWORD, NULL, 0) \
- T(ESCAPED_STRICT_RESERVED_WORD, NULL, 0) \
- \
- /* Scanner-internal use only. */ \
- T(WHITESPACE, NULL, 0) \
- T(UNINITIALIZED, NULL, 0) \
- T(REGEXP_LITERAL, NULL, 0) \
- \
- /* ES6 Template Literals */ \
- T(TEMPLATE_SPAN, NULL, 0) \
- T(TEMPLATE_TAIL, NULL, 0) \
- \
- /* Contextual keyword tokens */ \
- C(GET, "get", 0) \
- 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(PROTOTYPE, "prototype", 0) \
- C(EVAL, "eval", 0) \
- C(ARGUMENTS, "arguments", 0) \
- C(UNDEFINED, "undefined", 0) \
+#define TOKEN_LIST(T, K, C) \
+ /* End of source indicator. */ \
+ T(EOS, "EOS", 0) \
+ \
+ /* Punctuators (ECMA-262, section 7.7, page 15). */ \
+ T(LPAREN, "(", 0) \
+ T(RPAREN, ")", 0) \
+ T(LBRACK, "[", 0) \
+ T(RBRACK, "]", 0) \
+ T(LBRACE, "{", 0) \
+ T(RBRACE, "}", 0) \
+ T(COLON, ":", 0) \
+ T(SEMICOLON, ";", 0) \
+ T(PERIOD, ".", 0) \
+ T(ELLIPSIS, "...", 0) \
+ T(CONDITIONAL, "?", 3) \
+ T(INC, "++", 0) \
+ T(DEC, "--", 0) \
+ T(ARROW, "=>", 0) \
+ \
+ /* Assignment operators. */ \
+ /* IsAssignmentOp() relies on this block of enum values being */ \
+ /* contiguous and sorted in the same order! */ \
+ T(INIT, "=init", 2) /* AST-use only. */ \
+ T(ASSIGN, "=", 2) \
+ T(ASSIGN_BIT_OR, "|=", 2) \
+ T(ASSIGN_BIT_XOR, "^=", 2) \
+ T(ASSIGN_BIT_AND, "&=", 2) \
+ T(ASSIGN_SHL, "<<=", 2) \
+ T(ASSIGN_SAR, ">>=", 2) \
+ T(ASSIGN_SHR, ">>>=", 2) \
+ T(ASSIGN_ADD, "+=", 2) \
+ T(ASSIGN_SUB, "-=", 2) \
+ T(ASSIGN_MUL, "*=", 2) \
+ T(ASSIGN_DIV, "/=", 2) \
+ T(ASSIGN_MOD, "%=", 2) \
+ T(ASSIGN_EXP, "**=", 2) \
+ \
+ /* Binary operators sorted by precedence. */ \
+ /* IsBinaryOp() relies on this block of enum values */ \
+ /* being contiguous and sorted in the same order! */ \
+ T(COMMA, ",", 1) \
+ T(OR, "||", 4) \
+ T(AND, "&&", 5) \
+ T(BIT_OR, "|", 6) \
+ T(BIT_XOR, "^", 7) \
+ T(BIT_AND, "&", 8) \
+ T(SHL, "<<", 11) \
+ T(SAR, ">>", 11) \
+ T(SHR, ">>>", 11) \
+ T(ADD, "+", 12) \
+ T(SUB, "-", 12) \
+ T(MUL, "*", 13) \
+ T(DIV, "/", 13) \
+ T(MOD, "%", 13) \
+ T(EXP, "**", 14) \
+ \
+ /* Compare operators sorted by precedence. */ \
+ /* IsCompareOp() relies on this block of enum values */ \
+ /* being contiguous and sorted in the same order! */ \
+ T(EQ, "==", 9) \
+ T(NE, "!=", 9) \
+ T(EQ_STRICT, "===", 9) \
+ T(NE_STRICT, "!==", 9) \
+ T(LT, "<", 10) \
+ T(GT, ">", 10) \
+ T(LTE, "<=", 10) \
+ T(GTE, ">=", 10) \
+ K(INSTANCEOF, "instanceof", 10) \
+ K(IN, "in", 10) \
+ \
+ /* Unary operators. */ \
+ /* IsUnaryOp() relies on this block of enum values */ \
+ /* being contiguous and sorted in the same order! */ \
+ T(NOT, "!", 0) \
+ T(BIT_NOT, "~", 0) \
+ K(DELETE, "delete", 0) \
+ K(TYPEOF, "typeof", 0) \
+ K(VOID, "void", 0) \
+ \
+ /* Keywords (ECMA-262, section 7.5.2, page 13). */ \
+ K(BREAK, "break", 0) \
+ K(CASE, "case", 0) \
+ K(CATCH, "catch", 0) \
+ K(CONTINUE, "continue", 0) \
+ K(DEBUGGER, "debugger", 0) \
+ K(DEFAULT, "default", 0) \
+ /* DELETE */ \
+ K(DO, "do", 0) \
+ K(ELSE, "else", 0) \
+ K(FINALLY, "finally", 0) \
+ K(FOR, "for", 0) \
+ K(FUNCTION, "function", 0) \
+ K(IF, "if", 0) \
+ /* IN */ \
+ /* INSTANCEOF */ \
+ K(NEW, "new", 0) \
+ K(RETURN, "return", 0) \
+ K(SWITCH, "switch", 0) \
+ K(THIS, "this", 0) \
+ K(THROW, "throw", 0) \
+ K(TRY, "try", 0) \
+ /* TYPEOF */ \
+ K(VAR, "var", 0) \
+ /* VOID */ \
+ K(WHILE, "while", 0) \
+ K(WITH, "with", 0) \
+ \
+ /* Literals (ECMA-262, section 7.8, page 16). */ \
+ K(NULL_LITERAL, "null", 0) \
+ K(TRUE_LITERAL, "true", 0) \
+ K(FALSE_LITERAL, "false", 0) \
+ T(NUMBER, nullptr, 0) \
+ T(SMI, nullptr, 0) \
+ T(STRING, nullptr, 0) \
+ T(BIGINT, nullptr, 0) \
+ \
+ /* Identifiers (not keywords or future reserved words). */ \
+ T(IDENTIFIER, nullptr, 0) \
+ \
+ /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
+ T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \
+ K(ASYNC, "async", 0) \
+ /* `await` is a reserved word in module code only */ \
+ K(AWAIT, "await", 0) \
+ K(CLASS, "class", 0) \
+ K(CONST, "const", 0) \
+ K(ENUM, "enum", 0) \
+ K(EXPORT, "export", 0) \
+ K(EXTENDS, "extends", 0) \
+ K(IMPORT, "import", 0) \
+ K(LET, "let", 0) \
+ K(STATIC, "static", 0) \
+ K(YIELD, "yield", 0) \
+ K(SUPER, "super", 0) \
+ \
+ /* Illegal token - not able to scan. */ \
+ T(ILLEGAL, "ILLEGAL", 0) \
+ T(ESCAPED_KEYWORD, nullptr, 0) \
+ T(ESCAPED_STRICT_RESERVED_WORD, nullptr, 0) \
+ \
+ /* Scanner-internal use only. */ \
+ T(WHITESPACE, nullptr, 0) \
+ T(UNINITIALIZED, nullptr, 0) \
+ T(REGEXP_LITERAL, nullptr, 0) \
+ \
+ /* ES6 Template Literals */ \
+ T(TEMPLATE_SPAN, nullptr, 0) \
+ T(TEMPLATE_TAIL, nullptr, 0) \
+ \
+ /* Contextual keyword tokens */ \
+ C(GET, "get", 0) \
+ 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(PROTOTYPE, "prototype", 0) \
+ C(EVAL, "eval", 0) \
+ C(ARGUMENTS, "arguments", 0) \
+ C(UNDEFINED, "undefined", 0) \
C(ANONYMOUS, "anonymous", 0)
class Token {
@@ -246,10 +247,6 @@ class Token {
static bool IsBinaryOp(Value op) { return COMMA <= op && op <= EXP; }
- static bool IsTruncatingBinaryOp(Value op) {
- return BIT_OR <= op && op <= SHR;
- }
-
static bool IsCompareOp(Value op) {
return EQ <= op && op <= IN;
}
@@ -262,62 +259,6 @@ class Token {
return op == EQ || op == EQ_STRICT;
}
- static bool IsInequalityOp(Value op) {
- return op == NE || op == NE_STRICT;
- }
-
- static bool IsArithmeticCompareOp(Value op) {
- return IsOrderedRelationalCompareOp(op) ||
- IsEqualityOp(op) || IsInequalityOp(op);
- }
-
- static Value NegateCompareOp(Value op) {
- DCHECK(IsArithmeticCompareOp(op));
- switch (op) {
- case EQ: return NE;
- case NE: return EQ;
- case EQ_STRICT: return NE_STRICT;
- case NE_STRICT: return EQ_STRICT;
- case LT: return GTE;
- case GT: return LTE;
- case LTE: return GT;
- case GTE: return LT;
- default:
- UNREACHABLE();
- }
- }
-
- static Value ReverseCompareOp(Value op) {
- DCHECK(IsArithmeticCompareOp(op));
- switch (op) {
- case EQ: return EQ;
- case NE: return NE;
- case EQ_STRICT: return EQ_STRICT;
- case NE_STRICT: return NE_STRICT;
- case LT: return GT;
- case GT: return LT;
- case LTE: return GTE;
- case GTE: return LTE;
- default:
- UNREACHABLE();
- }
- }
-
- static bool EvalComparison(Value op, double op1, double op2) {
- DCHECK(IsArithmeticCompareOp(op));
- switch (op) {
- case Token::EQ:
- case Token::EQ_STRICT: return (op1 == op2);
- case Token::NE: return (op1 != op2);
- case Token::LT: return (op1 < op2);
- case Token::GT: return (op1 > op2);
- case Token::LTE: return (op1 <= op2);
- case Token::GTE: return (op1 >= op2);
- default:
- UNREACHABLE();
- }
- }
-
static Value BinaryOpForAssignment(Value op) {
DCHECK(IsAssignmentOp(op));
switch (op) {
@@ -343,6 +284,8 @@ class Token {
return Token::DIV;
case Token::ASSIGN_MOD:
return Token::MOD;
+ case Token::ASSIGN_EXP:
+ return Token::EXP;
default:
UNREACHABLE();
}
@@ -365,7 +308,7 @@ class Token {
}
// Returns a string corresponding to the JS token string
- // (.e., "<" for the token LT) or NULL if the token doesn't
+ // (.e., "<" for the token LT) or nullptr if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
static const char* String(Value tok) {
DCHECK(tok < NUM_TOKENS); // tok is unsigned.