summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing')
-rw-r--r--deps/v8/src/parsing/expression-classifier.h56
-rw-r--r--deps/v8/src/parsing/func-name-inferrer.cc44
-rw-r--r--deps/v8/src/parsing/func-name-inferrer.h13
-rw-r--r--deps/v8/src/parsing/parse-info.cc34
-rw-r--r--deps/v8/src/parsing/parse-info.h36
-rw-r--r--deps/v8/src/parsing/parser-base.h259
-rw-r--r--deps/v8/src/parsing/parser.cc103
-rw-r--r--deps/v8/src/parsing/parser.h20
-rw-r--r--deps/v8/src/parsing/pattern-rewriter.cc3
-rw-r--r--deps/v8/src/parsing/preparse-data.cc44
-rw-r--r--deps/v8/src/parsing/preparse-data.h84
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.cc7
-rw-r--r--deps/v8/src/parsing/preparsed-scope-data.h6
-rw-r--r--deps/v8/src/parsing/preparser-logger.h35
-rw-r--r--deps/v8/src/parsing/preparser.cc1
-rw-r--r--deps/v8/src/parsing/preparser.h49
-rw-r--r--deps/v8/src/parsing/scanner-character-streams.cc201
-rw-r--r--deps/v8/src/parsing/scanner-character-streams.h1
-rw-r--r--deps/v8/src/parsing/scanner-inl.h43
-rw-r--r--deps/v8/src/parsing/scanner.cc402
-rw-r--r--deps/v8/src/parsing/scanner.h343
21 files changed, 885 insertions, 899 deletions
diff --git a/deps/v8/src/parsing/expression-classifier.h b/deps/v8/src/parsing/expression-classifier.h
index 522b650be7..7833dbc8d3 100644
--- a/deps/v8/src/parsing/expression-classifier.h
+++ b/deps/v8/src/parsing/expression-classifier.h
@@ -7,6 +7,7 @@
#include "src/messages.h"
#include "src/parsing/scanner.h"
+#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
@@ -61,18 +62,15 @@ class ExpressionClassifier {
: location(Scanner::Location::invalid()),
message(MessageTemplate::kNone),
kind(kUnusedError),
- type(kSyntaxError),
arg(nullptr) {}
V8_INLINE explicit Error(Scanner::Location loc,
MessageTemplate::Template msg, ErrorKind k,
- const char* a = nullptr,
- ParseErrorType t = kSyntaxError)
- : location(loc), message(msg), kind(k), type(t), arg(a) {}
+ const char* a = nullptr)
+ : location(loc), message(msg), kind(k), arg(a) {}
Scanner::Location location;
- MessageTemplate::Template message : 26;
+ MessageTemplate::Template message : 28;
unsigned kind : 4;
- ParseErrorType type : 2;
const char* arg;
};
@@ -88,10 +86,6 @@ class ExpressionClassifier {
};
// clang-format on
- enum FunctionProperties : unsigned {
- NonSimpleParameter = 1 << 0
- };
-
explicit ExpressionClassifier(typename Types::Base* base,
DuplicateFinder* duplicate_finder = nullptr)
: base_(base),
@@ -100,9 +94,9 @@ class ExpressionClassifier {
reported_errors_(base->impl()->GetReportedErrorList()),
duplicate_finder_(duplicate_finder),
invalid_productions_(0),
- function_properties_(0) {
+ is_non_simple_parameter_list_(0) {
base->classifier_ = this;
- reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
+ reported_errors_begin_ = reported_errors_end_ = reported_errors_->size();
}
V8_INLINE ~ExpressionClassifier() {
@@ -193,11 +187,11 @@ class ExpressionClassifier {
}
V8_INLINE bool is_simple_parameter_list() const {
- return !(function_properties_ & NonSimpleParameter);
+ return !is_non_simple_parameter_list_;
}
V8_INLINE void RecordNonSimpleParameter() {
- function_properties_ |= NonSimpleParameter;
+ is_non_simple_parameter_list_ = 1;
}
void RecordExpressionError(const Scanner::Location& loc,
@@ -208,14 +202,6 @@ class ExpressionClassifier {
Add(Error(loc, message, kExpressionProduction, arg));
}
- void RecordExpressionError(const Scanner::Location& loc,
- MessageTemplate::Template message,
- ParseErrorType type, const char* arg = nullptr) {
- if (!is_valid_expression()) return;
- invalid_productions_ |= ExpressionProduction;
- Add(Error(loc, message, kExpressionProduction, arg, type));
- }
-
void RecordFormalParameterInitializerError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
@@ -292,7 +278,7 @@ class ExpressionClassifier {
void Accumulate(ExpressionClassifier* inner, unsigned productions) {
DCHECK_EQ(inner->reported_errors_, reported_errors_);
DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_);
- DCHECK_EQ(inner->reported_errors_end_, reported_errors_->length());
+ DCHECK_EQ(inner->reported_errors_end_, reported_errors_->size());
// Propagate errors from inner, but don't overwrite already recorded
// errors.
unsigned non_arrow_inner_invalid_productions =
@@ -305,9 +291,9 @@ class ExpressionClassifier {
bool copy_BP_to_AFP = false;
if (productions & ArrowFormalParametersProduction &&
is_valid_arrow_formal_parameters()) {
- // Also copy function properties if expecting an arrow function
- // parameter.
- function_properties_ |= inner->function_properties_;
+ // Also whether we've seen any non-simple parameters
+ // if expecting an arrow function parameter.
+ is_non_simple_parameter_list_ |= inner->is_non_simple_parameter_list_;
if (!inner->is_valid_binding_pattern()) {
copy_BP_to_AFP = true;
invalid_productions_ |= ArrowFormalParametersProduction;
@@ -352,14 +338,14 @@ class ExpressionClassifier {
}
}
}
- reported_errors_->Rewind(reported_errors_end_);
+ reported_errors_->resize(reported_errors_end_);
inner->reported_errors_begin_ = inner->reported_errors_end_ =
reported_errors_end_;
}
V8_INLINE void Discard() {
- if (reported_errors_end_ == reported_errors_->length()) {
- reported_errors_->Rewind(reported_errors_begin_);
+ if (reported_errors_end_ == reported_errors_->size()) {
+ reported_errors_->resize(reported_errors_begin_);
reported_errors_end_ = reported_errors_begin_;
}
DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
@@ -389,8 +375,8 @@ class ExpressionClassifier {
// Adds e to the end of the list of reported errors for this classifier.
// It is expected that this classifier is the last one in the stack.
V8_INLINE void Add(const Error& e) {
- DCHECK_EQ(reported_errors_end_, reported_errors_->length());
- reported_errors_->Add(e, zone_);
+ DCHECK_EQ(reported_errors_end_, reported_errors_->size());
+ reported_errors_->push_back(e);
reported_errors_end_++;
}
@@ -400,7 +386,7 @@ class ExpressionClassifier {
// in an inner classifier) or it could be an existing error (in case a
// copy is needed).
V8_INLINE void Copy(int i) {
- DCHECK_LT(i, reported_errors_->length());
+ DCHECK_LT(i, reported_errors_->size());
if (reported_errors_end_ != i)
reported_errors_->at(reported_errors_end_) = reported_errors_->at(i);
reported_errors_end_++;
@@ -409,10 +395,10 @@ class ExpressionClassifier {
typename Types::Base* base_;
ExpressionClassifier* previous_;
Zone* zone_;
- ZoneList<Error>* reported_errors_;
+ ZoneVector<Error>* reported_errors_;
DuplicateFinder* duplicate_finder_;
- unsigned invalid_productions_ : 14;
- unsigned function_properties_ : 2;
+ unsigned invalid_productions_ : 15;
+ unsigned is_non_simple_parameter_list_ : 1;
// The uint16_t for reported_errors_begin_ and reported_errors_end_ will
// not be enough in the case of a long series of expressions using nested
// classifiers, e.g., a long sequence of assignments, as in:
diff --git a/deps/v8/src/parsing/func-name-inferrer.cc b/deps/v8/src/parsing/func-name-inferrer.cc
index 4920877610..7d476f1e64 100644
--- a/deps/v8/src/parsing/func-name-inferrer.cc
+++ b/deps/v8/src/parsing/func-name-inferrer.cc
@@ -14,72 +14,74 @@ namespace internal {
FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
Zone* zone)
: ast_value_factory_(ast_value_factory),
- entries_stack_(10, zone),
- names_stack_(5, zone),
- funcs_to_infer_(4, zone),
- zone_(zone) {
-}
-
+ entries_stack_(zone),
+ names_stack_(zone),
+ funcs_to_infer_(zone),
+ zone_(zone) {}
void FuncNameInferrer::PushEnclosingName(const AstRawString* name) {
// Enclosing name is a name of a constructor function. To check
// that it is really a constructor, we check that it is not empty
// and starts with a capital letter.
if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
- names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
+ names_stack_.push_back(Name(name, kEnclosingConstructorName));
}
}
void FuncNameInferrer::PushLiteralName(const AstRawString* name) {
if (IsOpen() && name != ast_value_factory_->prototype_string()) {
- names_stack_.Add(Name(name, kLiteralName), zone());
+ names_stack_.push_back(Name(name, kLiteralName));
}
}
void FuncNameInferrer::PushVariableName(const AstRawString* name) {
if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
- names_stack_.Add(Name(name, kVariableName), zone());
+ names_stack_.push_back(Name(name, kVariableName));
}
}
void FuncNameInferrer::RemoveAsyncKeywordFromEnd() {
if (IsOpen()) {
- CHECK_GT(names_stack_.length(), 0);
- CHECK(names_stack_.last().name->IsOneByteEqualTo("async"));
- names_stack_.RemoveLast();
+ CHECK_GT(names_stack_.size(), 0);
+ CHECK(names_stack_.back().name->IsOneByteEqualTo("async"));
+ names_stack_.pop_back();
}
}
void FuncNameInferrer::Leave() {
DCHECK(IsOpen());
- names_stack_.Rewind(entries_stack_.RemoveLast());
- if (entries_stack_.is_empty()) funcs_to_infer_.Clear();
+ size_t last_entry = entries_stack_.back();
+ entries_stack_.pop_back();
+ names_stack_.Rewind(last_entry);
+ if (entries_stack_.is_empty()) funcs_to_infer_.Rewind();
}
const AstConsString* FuncNameInferrer::MakeNameFromStack() {
AstConsString* result = ast_value_factory_->NewConsString();
- for (int pos = 0; pos < names_stack_.length(); pos++) {
+ auto it = names_stack_.begin();
+ while (it != names_stack_.end()) {
+ // Advance the iterator to be able to peek the next value.
+ auto current = it++;
// Skip consecutive variable declarations.
- if (pos + 1 < names_stack_.length() &&
- names_stack_.at(pos).type == kVariableName &&
- names_stack_.at(pos + 1).type == kVariableName) {
+ if (it != names_stack_.end() && current->type == kVariableName &&
+ it->type == kVariableName) {
continue;
}
// Add name. Separate names with ".".
if (!result->IsEmpty()) {
result->AddString(zone(), ast_value_factory_->dot_string());
}
- result->AddString(zone(), names_stack_.at(pos).name);
+ result->AddString(zone(), current->name);
}
return result;
}
void FuncNameInferrer::InferFunctionsNames() {
const AstConsString* func_name = MakeNameFromStack();
- for (int i = 0; i < funcs_to_infer_.length(); ++i) {
- funcs_to_infer_[i]->set_raw_inferred_name(func_name);
+ for (FunctionLiteral* func : funcs_to_infer_) {
+ func->set_raw_inferred_name(func_name);
}
funcs_to_infer_.Rewind(0);
}
diff --git a/deps/v8/src/parsing/func-name-inferrer.h b/deps/v8/src/parsing/func-name-inferrer.h
index 21c4da3be9..8f0f428a05 100644
--- a/deps/v8/src/parsing/func-name-inferrer.h
+++ b/deps/v8/src/parsing/func-name-inferrer.h
@@ -5,6 +5,7 @@
#ifndef V8_PARSING_FUNC_NAME_INFERRER_H_
#define V8_PARSING_FUNC_NAME_INFERRER_H_
+#include "src/zone/zone-chunk-list.h"
#include "src/zone/zone.h"
namespace v8 {
@@ -62,13 +63,13 @@ class FuncNameInferrer : public ZoneObject {
// Adds a function to infer name for.
void AddFunction(FunctionLiteral* func_to_infer) {
if (IsOpen()) {
- funcs_to_infer_.Add(func_to_infer, zone());
+ funcs_to_infer_.push_back(func_to_infer);
}
}
void RemoveLastFunction() {
if (IsOpen() && !funcs_to_infer_.is_empty()) {
- funcs_to_infer_.RemoveLast();
+ funcs_to_infer_.pop_back();
}
}
@@ -94,7 +95,7 @@ class FuncNameInferrer : public ZoneObject {
NameType type;
};
- void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }
+ void Enter() { entries_stack_.push_back(names_stack_.size()); }
void Leave();
@@ -107,9 +108,9 @@ class FuncNameInferrer : public ZoneObject {
void InferFunctionsNames();
AstValueFactory* ast_value_factory_;
- ZoneList<int> entries_stack_;
- ZoneList<Name> names_stack_;
- ZoneList<FunctionLiteral*> funcs_to_infer_;
+ ZoneChunkList<size_t> entries_stack_;
+ ZoneChunkList<Name> names_stack_;
+ ZoneChunkList<FunctionLiteral*> funcs_to_infer_;
Zone* zone_;
DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
diff --git a/deps/v8/src/parsing/parse-info.cc b/deps/v8/src/parsing/parse-info.cc
index ee7e4b1569..0a58c4f0bd 100644
--- a/deps/v8/src/parsing/parse-info.cc
+++ b/deps/v8/src/parsing/parse-info.cc
@@ -4,10 +4,10 @@
#include "src/parsing/parse-info.h"
-#include "src/api.h"
#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
+#include "src/base/template-utils.h"
#include "src/heap/heap-inl.h"
#include "src/objects-inl.h"
#include "src/objects/scope-info.h"
@@ -17,14 +17,14 @@ namespace v8 {
namespace internal {
ParseInfo::ParseInfo(Isolate* isolate, AccountingAllocator* zone_allocator)
- : zone_(std::make_shared<Zone>(zone_allocator, ZONE_NAME)),
+ : zone_(base::make_unique<Zone>(zone_allocator, ZONE_NAME)),
flags_(0),
extension_(nullptr),
script_scope_(nullptr),
unicode_cache_(nullptr),
stack_limit_(0),
hash_seed_(0),
- function_flags_(0),
+ function_kind_(FunctionKind::kNormalFunction),
script_id_(-1),
start_position_(0),
end_position_(0),
@@ -65,11 +65,14 @@ ParseInfo::ParseInfo(Isolate* isolate, Handle<SharedFunctionInfo> shared)
set_wrapped_as_function(shared->is_wrapped());
set_allow_lazy_parsing(FLAG_lazy_inner_functions);
set_is_named_expression(shared->is_named_expression());
- set_function_flags(shared->flags());
set_start_position(shared->StartPosition());
set_end_position(shared->EndPosition());
function_literal_id_ = shared->FunctionLiteralId(isolate);
set_language_mode(shared->language_mode());
+ set_function_kind(shared->kind());
+ set_declaration(shared->is_declaration());
+ set_requires_instance_fields_initializer(
+ shared->requires_instance_fields_initializer());
set_asm_wasm_broken(shared->is_asm_wasm_broken());
Handle<Script> script(Script::cast(shared->script()), isolate);
@@ -100,19 +103,6 @@ ParseInfo::~ParseInfo() {}
DeclarationScope* ParseInfo::scope() const { return literal()->scope(); }
-bool ParseInfo::is_declaration() const {
- return SharedFunctionInfo::IsDeclarationBit::decode(function_flags_);
-}
-
-FunctionKind ParseInfo::function_kind() const {
- return SharedFunctionInfo::FunctionKindBits::decode(function_flags_);
-}
-
-bool ParseInfo::requires_instance_fields_initializer() const {
- return SharedFunctionInfo::RequiresInstanceFieldsInitializer::decode(
- function_flags_);
-}
-
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.
@@ -141,11 +131,6 @@ void ParseInfo::UpdateBackgroundParseStatisticsOnMainThread(Isolate* isolate) {
set_runtime_call_stats(main_call_stats);
}
-void ParseInfo::ShareZone(ParseInfo* other) {
- DCHECK_EQ(0, zone_->allocation_size());
- zone_ = other->zone_;
-}
-
Handle<Script> ParseInfo::CreateScript(Isolate* isolate, Handle<String> source,
ScriptOriginOptions origin_options,
NativesFlag natives) {
@@ -186,11 +171,6 @@ AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
return ast_value_factory();
}
-void ParseInfo::ShareAstValueFactory(ParseInfo* other) {
- DCHECK(!ast_value_factory_.get());
- ast_value_factory_ = other->ast_value_factory_;
-}
-
void ParseInfo::AllocateSourceRangeMap() {
DCHECK(block_coverage_enabled());
set_source_range_map(new (zone()) SourceRangeMap(zone()));
diff --git a/deps/v8/src/parsing/parse-info.h b/deps/v8/src/parsing/parse-info.h
index 4abf3a1fb0..64a50806f5 100644
--- a/deps/v8/src/parsing/parse-info.h
+++ b/deps/v8/src/parsing/parse-info.h
@@ -54,12 +54,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
Zone* zone() const { return zone_.get(); }
- // Sets this parse info to share the same zone as |other|
- void ShareZone(ParseInfo* other);
-
- // Sets this parse info to share the same ast value factory as |other|
- void ShareAstValueFactory(ParseInfo* other);
-
// Convenience accessor methods for flags.
#define FLAG_ACCESSOR(flag, getter, setter) \
bool getter() const { return GetFlag(flag); } \
@@ -86,6 +80,10 @@ class V8_EXPORT_PRIVATE ParseInfo {
FLAG_ACCESSOR(kWrappedAsFunction, is_wrapped_as_function,
set_wrapped_as_function)
FLAG_ACCESSOR(kAllowEvalCache, allow_eval_cache, set_allow_eval_cache)
+ FLAG_ACCESSOR(kIsDeclaration, is_declaration, set_declaration)
+ FLAG_ACCESSOR(kRequiresInstanceFieldsInitializer,
+ requires_instance_fields_initializer,
+ set_requires_instance_fields_initializer);
#undef FLAG_ACCESSOR
void set_parse_restriction(ParseRestriction restriction) {
@@ -143,11 +141,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
uint64_t hash_seed() const { return hash_seed_; }
void set_hash_seed(uint64_t hash_seed) { hash_seed_ = hash_seed; }
- int function_flags() const { return function_flags_; }
- void set_function_flags(int function_flags) {
- function_flags_ = function_flags;
- }
-
int start_position() const { return start_position_; }
void set_start_position(int start_position) {
start_position_ = start_position;
@@ -166,6 +159,11 @@ class V8_EXPORT_PRIVATE ParseInfo {
function_literal_id_ = function_literal_id;
}
+ FunctionKind function_kind() const { return function_kind_; }
+ void set_function_kind(FunctionKind function_kind) {
+ function_kind_ = function_kind;
+ }
+
int max_function_literal_id() const { return max_function_literal_id_; }
void set_max_function_literal_id(int max_function_literal_id) {
max_function_literal_id_ = max_function_literal_id;
@@ -196,11 +194,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
return &pending_error_handler_;
}
- // Getters for individual function flags.
- bool is_declaration() const;
- FunctionKind function_kind() const;
- bool requires_instance_fields_initializer() const;
-
//--------------------------------------------------------------------------
// TODO(titzer): these should not be part of ParseInfo.
//--------------------------------------------------------------------------
@@ -249,19 +242,19 @@ class V8_EXPORT_PRIVATE ParseInfo {
kOnBackgroundThread = 1 << 13,
kWrappedAsFunction = 1 << 14, // Implicitly wrapped as function.
kAllowEvalCache = 1 << 15,
+ kIsDeclaration = 1 << 16,
+ kRequiresInstanceFieldsInitializer = 1 << 17,
};
//------------- Inputs to parsing and scope analysis -----------------------
- std::shared_ptr<Zone> zone_;
+ std::unique_ptr<Zone> zone_;
unsigned flags_;
v8::Extension* extension_;
DeclarationScope* script_scope_;
UnicodeCache* unicode_cache_;
uintptr_t stack_limit_;
uint64_t hash_seed_;
- // TODO(leszeks): Move any remaining flags used here either to the flags_
- // field or to other fields.
- int function_flags_;
+ FunctionKind function_kind_;
int script_id_;
int start_position_;
int end_position_;
@@ -276,7 +269,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
//----------- Inputs+Outputs of parsing and scope analysis -----------------
std::unique_ptr<Utf16CharacterStream> character_stream_;
ConsumedPreParsedScopeData consumed_preparsed_scope_data_;
- std::shared_ptr<AstValueFactory> ast_value_factory_;
+ std::unique_ptr<AstValueFactory> ast_value_factory_;
const class AstStringConstants* ast_string_constants_;
const AstRawString* function_name_;
RuntimeCallStats* runtime_call_stats_;
@@ -285,7 +278,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
//----------- Output of parsing and scope analysis ------------------------
FunctionLiteral* literal_;
- std::shared_ptr<DeferredHandles> deferred_handles_;
PendingCompilationErrorHandler pending_error_handler_;
void SetFlag(Flag f) { flags_ |= f; }
diff --git a/deps/v8/src/parsing/parser-base.h b/deps/v8/src/parsing/parser-base.h
index 6f6cff8e20..9d13724f06 100644
--- a/deps/v8/src/parsing/parser-base.h
+++ b/deps/v8/src/parsing/parser-base.h
@@ -21,6 +21,7 @@
#include "src/parsing/func-name-inferrer.h"
#include "src/parsing/scanner.h"
#include "src/parsing/token.h"
+#include "src/zone/zone-chunk-list.h"
namespace v8 {
namespace internal {
@@ -416,21 +417,23 @@ class ParserBase {
void AdoptDestructuringAssignmentsFromParentState(int pos) {
const auto& outer_assignments =
outer_function_state_->destructuring_assignments_to_rewrite_;
- DCHECK_GE(outer_assignments.length(), pos);
- for (int i = pos; i < outer_assignments.length(); ++i) {
- auto expr = outer_assignments[i];
+ DCHECK_GE(outer_assignments.size(), pos);
+ auto it = outer_assignments.begin();
+ it.Advance(pos);
+ for (; it != outer_assignments.end(); ++it) {
+ auto expr = *it;
expr->set_scope(scope_);
- destructuring_assignments_to_rewrite_.Add(expr, scope_->zone());
+ destructuring_assignments_to_rewrite_.push_back(expr);
}
outer_function_state_->RewindDestructuringAssignments(pos);
}
- const ZoneList<RewritableExpressionT>&
+ const ZoneChunkList<RewritableExpressionT>&
destructuring_assignments_to_rewrite() const {
return destructuring_assignments_to_rewrite_;
}
- ZoneList<typename ExpressionClassifier::Error>* GetReportedErrorList() {
+ ZoneVector<typename ExpressionClassifier::Error>* GetReportedErrorList() {
return &reported_errors_;
}
@@ -472,26 +475,27 @@ class ParserBase {
private:
void AddDestructuringAssignment(RewritableExpressionT expr) {
- destructuring_assignments_to_rewrite_.Add(expr, scope_->zone());
+ destructuring_assignments_to_rewrite_.push_back(expr);
}
// Properties count estimation.
int expected_property_count_;
+ // How many suspends are needed for this function.
+ int suspend_count_;
+
FunctionState** function_state_stack_;
FunctionState* outer_function_state_;
DeclarationScope* scope_;
- ZoneList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
+ ZoneChunkList<RewritableExpressionT> destructuring_assignments_to_rewrite_;
- ZoneList<typename ExpressionClassifier::Error> reported_errors_;
+ // We use a ZoneVector here because we need to do a lot of random access.
+ ZoneVector<typename ExpressionClassifier::Error> reported_errors_;
// A reason, if any, why this function should not be optimized.
BailoutReason dont_optimize_reason_;
- // How many suspends are needed for this function.
- int suspend_count_;
-
// Record whether the next (=== immediately following) function literal is
// preceded by a parenthesis / exclamation mark. Also record the previous
// state.
@@ -594,7 +598,6 @@ class ParserBase {
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;
@@ -745,8 +748,7 @@ class ParserBase {
Next();
return;
}
- if (scanner()->HasAnyLineTerminatorBeforeNext() ||
- tok == Token::RBRACE ||
+ if (scanner()->HasLineTerminatorBeforeNext() || tok == Token::RBRACE ||
tok == Token::EOS) {
return;
}
@@ -959,8 +961,7 @@ class ParserBase {
void ReportClassifierError(
const typename ExpressionClassifier::Error& error) {
- impl()->ReportMessageAt(error.location, error.message, error.arg,
- error.type);
+ impl()->ReportMessageAt(error.location, error.message, error.arg);
}
void ValidateExpression(bool* ok) {
@@ -1089,7 +1090,7 @@ class ParserBase {
function_state_->kind(), is_strict_reserved, is_await, ok);
}
- IdentifierT ParseIdentifierName(bool* ok);
+ V8_INLINE IdentifierT ParseIdentifierName(bool* ok);
ExpressionT ParseIdentifierNameOrPrivateName(bool* ok);
@@ -1135,8 +1136,7 @@ class ParserBase {
ClassLiteralPropertyT ParseClassPropertyDefinition(
ClassLiteralChecker* checker, ClassInfo* class_info,
IdentifierT* property_name, bool has_extends, bool* is_computed_name,
- bool* has_seen_constructor, ClassLiteralProperty::Kind* property_kind,
- bool* is_static, bool* has_name_static_property, bool* ok);
+ ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* ok);
ExpressionT ParseClassFieldInitializer(ClassInfo* class_info, bool is_static,
bool* ok);
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
@@ -1152,15 +1152,15 @@ class ParserBase {
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool accept_IN, bool* ok);
- ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
+ V8_INLINE ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
ExpressionT ParseUnaryExpression(bool* ok);
- ExpressionT ParsePostfixExpression(bool* ok);
- ExpressionT ParseLeftHandSideExpression(bool* ok);
+ V8_INLINE ExpressionT ParsePostfixExpression(bool* ok);
+ V8_INLINE ExpressionT ParseLeftHandSideExpression(bool* ok);
ExpressionT ParseMemberWithNewPrefixesExpression(bool* is_async, bool* ok);
- ExpressionT ParseMemberExpression(bool* is_async, bool* ok);
- ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
- bool* is_async, bool* ok);
+ V8_INLINE ExpressionT ParseMemberExpression(bool* is_async, bool* ok);
+ V8_INLINE ExpressionT ParseMemberExpressionContinuation(
+ ExpressionT expression, bool* is_async, bool* ok);
// `rewritable_length`: length of the destructuring_assignments_to_rewrite()
// queue in the parent function state, prior to parsing of formal parameters.
@@ -1183,7 +1183,7 @@ class ParserBase {
ExpressionT ParseImportExpressions(bool* ok);
ExpressionT ParseNewTargetExpression(bool* ok);
- void ParseFormalParameter(FormalParametersT* parameters, bool* ok);
+ V8_INLINE void ParseFormalParameter(FormalParametersT* parameters, bool* ok);
void ParseFormalParameterList(FormalParametersT* parameters, bool* ok);
void CheckArityRestrictions(int param_count, FunctionKind function_type,
bool has_rest, int formals_start_pos,
@@ -1228,14 +1228,19 @@ class ParserBase {
USE(result);
DCHECK_EQ(result, kLazyParsingComplete);
}
- LazyParsingResult ParseStatementList(StatementListT body,
- Token::Value end_token, bool may_abort,
- bool* ok);
+ V8_INLINE LazyParsingResult ParseStatementList(StatementListT body,
+ Token::Value end_token,
+ bool may_abort, bool* ok);
StatementT ParseStatementListItem(bool* ok);
- StatementT ParseStatement(ZonePtrList<const AstRawString>* labels, bool* ok) {
- return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
+
+ StatementT ParseStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
+ bool* ok) {
+ return ParseStatement(labels, own_labels,
+ kDisallowLabelledFunctionStatement, ok);
}
StatementT ParseStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
AllowLabelledFunctionStatement allow_function,
bool* ok);
BlockT ParseBlock(ZonePtrList<const AstRawString>* labels, bool* ok);
@@ -1259,6 +1264,7 @@ class ParserBase {
StatementT ParseExpressionOrLabelledStatement(
ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
AllowLabelledFunctionStatement allow_function, bool* ok);
StatementT ParseIfStatement(ZonePtrList<const AstRawString>* labels,
bool* ok);
@@ -1269,34 +1275,41 @@ class ParserBase {
StatementT ParseWithStatement(ZonePtrList<const AstRawString>* labels,
bool* ok);
StatementT ParseDoWhileStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
bool* ok);
StatementT ParseWhileStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
bool* ok);
StatementT ParseThrowStatement(bool* ok);
StatementT ParseSwitchStatement(ZonePtrList<const AstRawString>* labels,
bool* ok);
- StatementT ParseTryStatement(bool* ok);
+ V8_INLINE StatementT ParseTryStatement(bool* ok);
StatementT ParseForStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
bool* ok);
StatementT ParseForEachStatementWithDeclarations(
int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- Scope* inner_block_scope, bool* ok);
+ ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope,
+ bool* ok);
StatementT ParseForEachStatementWithoutDeclarations(
int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
- ForInfo* for_info, ZonePtrList<const AstRawString>* labels, bool* ok);
+ ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok);
// Parse a C-style for loop: 'for (<init>; <cond>; <next>) { ... }'
// "for (<init>;" is assumed to have been parser already.
- ForStatementT ParseStandardForLoop(int stmt_pos,
- ZonePtrList<const AstRawString>* labels,
- ExpressionT* cond, StatementT* next,
- StatementT* body, bool* ok);
+ ForStatementT ParseStandardForLoop(
+ int stmt_pos, ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, ExpressionT* cond,
+ StatementT* next, StatementT* body, bool* ok);
// Same as the above, but handles those cases where <init> is a
// lexical variable declaration.
StatementT ParseStandardForLoopWithLexicalDeclarations(
int stmt_pos, StatementT init, ForInfo* for_info,
- ZonePtrList<const AstRawString>* labels, bool* ok);
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok);
StatementT ParseForAwaitStatement(ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
bool* ok);
bool IsNextLetKeyword();
@@ -1574,17 +1587,18 @@ ParserBase<Impl>::FunctionState::FunctionState(
DeclarationScope* scope)
: BlockState(scope_stack, scope),
expected_property_count_(0),
+ suspend_count_(0),
function_state_stack_(function_state_stack),
outer_function_state_(*function_state_stack),
scope_(scope),
- destructuring_assignments_to_rewrite_(16, scope->zone()),
- reported_errors_(16, scope->zone()),
+ destructuring_assignments_to_rewrite_(scope->zone()),
+ reported_errors_(scope_->zone()),
dont_optimize_reason_(BailoutReason::kNoReason),
- suspend_count_(0),
next_function_is_likely_called_(false),
previous_function_was_likely_called_(false),
contains_function_or_eval_(false) {
*function_state_stack = this;
+ reported_errors_.reserve(16);
if (outer_function_state_) {
outer_function_state_->previous_function_was_likely_called_ =
outer_function_state_->next_function_is_likely_called_;
@@ -1875,7 +1889,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
return impl()->ExpressionFromLiteral(Next(), beg_pos);
case Token::ASYNC:
- if (!scanner()->HasAnyLineTerminatorAfterNext() &&
+ if (!scanner()->HasLineTerminatorAfterNext() &&
PeekAhead() == Token::FUNCTION) {
BindingPatternUnexpectedToken();
Consume(Token::ASYNC);
@@ -2179,10 +2193,10 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
int pos = peek_position();
if (!*is_generator && token == Token::ASYNC &&
- !scanner()->HasAnyLineTerminatorAfterNext()) {
+ !scanner()->HasLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
token = peek();
- if (token == Token::MUL && !scanner()->HasAnyLineTerminatorBeforeNext()) {
+ if (token == Token::MUL && !scanner()->HasLineTerminatorBeforeNext()) {
Consume(Token::MUL);
token = peek();
*is_generator = true;
@@ -2300,11 +2314,9 @@ template <typename Impl>
typename ParserBase<Impl>::ClassLiteralPropertyT
ParserBase<Impl>::ParseClassPropertyDefinition(
ClassLiteralChecker* checker, ClassInfo* class_info, IdentifierT* name,
- bool has_extends, bool* is_computed_name, bool* has_seen_constructor,
- ClassLiteralProperty::Kind* property_kind, bool* is_static,
- bool* has_name_static_property, bool* ok) {
- DCHECK_NOT_NULL(has_seen_constructor);
- DCHECK_NOT_NULL(has_name_static_property);
+ bool has_extends, bool* is_computed_name,
+ ClassLiteralProperty::Kind* property_kind, bool* is_static, bool* ok) {
+ DCHECK_NOT_NULL(class_info);
bool is_get = false;
bool is_set = false;
bool is_generator = false;
@@ -2353,8 +2365,9 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
CHECK_OK_CUSTOM(NullLiteralProperty));
}
- if (!*has_name_static_property && *is_static && impl()->IsName(*name)) {
- *has_name_static_property = true;
+ if (!class_info->has_name_static_property && *is_static &&
+ impl()->IsName(*name)) {
+ class_info->has_name_static_property = true;
}
switch (kind) {
@@ -2416,7 +2429,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
FunctionKind kind = MethodKindFor(is_generator, is_async);
if (!*is_static && impl()->IsConstructor(*name)) {
- *has_seen_constructor = true;
+ class_info->has_seen_constructor = true;
kind = has_extends ? FunctionKind::kDerivedConstructor
: FunctionKind::kBaseConstructor;
}
@@ -2875,11 +2888,11 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
this, classifier()->duplicate_finder());
Scope::Snapshot scope_snapshot(scope());
- int rewritable_length =
- function_state_->destructuring_assignments_to_rewrite().length();
+ int rewritable_length = static_cast<int>(
+ function_state_->destructuring_assignments_to_rewrite().size());
bool is_async = peek() == Token::ASYNC &&
- !scanner()->HasAnyLineTerminatorAfterNext() &&
+ !scanner()->HasLineTerminatorAfterNext() &&
IsValidArrowFormalParametersStart(PeekAhead());
bool parenthesized_formals = peek() == Token::LPAREN;
@@ -3056,7 +3069,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
// The following initialization is necessary.
ExpressionT expression = impl()->NullExpression();
bool delegating = false; // yield*
- if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
+ if (!scanner()->HasLineTerminatorBeforeNext()) {
if (Check(Token::MUL)) delegating = true;
switch (peek()) {
case Token::EOS:
@@ -3307,8 +3320,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePostfixExpression(
int lhs_beg_pos = peek_position();
ExpressionT expression = ParseLeftHandSideExpression(CHECK_OK);
- if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
- Token::IsCountOp(peek())) {
+ if (!scanner()->HasLineTerminatorBeforeNext() && Token::IsCountOp(peek())) {
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
@@ -3375,6 +3387,7 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
// function literal eagerly, we can also compile it eagerly.
if (result->IsFunctionLiteral()) {
result->AsFunctionLiteral()->SetShouldEagerCompile();
+ result->AsFunctionLiteral()->mark_as_iife();
}
}
Scanner::Location spread_pos;
@@ -4168,7 +4181,7 @@ ParserBase<Impl>::ParseAsyncFunctionDeclaration(
// ( FormalParameters[Await] ) { AsyncFunctionBody }
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
int pos = position();
- if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+ if (scanner()->HasLineTerminatorBeforeNext()) {
*ok = false;
impl()->ReportUnexpectedToken(scanner()->current_token());
return impl()->NullStatement();
@@ -4360,7 +4373,7 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
base::ElapsedTimer timer;
if (V8_UNLIKELY(FLAG_log_function_events)) timer.Start();
- if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
+ if (peek() == Token::ARROW && scanner_->HasLineTerminatorBeforeNext()) {
// ASI inserts `;` after arrow parameters if a line terminator is found.
// `=> ...` is never a valid expression, so report as syntax error.
// If next token is not `=>`, it's a syntax error anyways.
@@ -4547,8 +4560,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
bool is_constructor = !class_info.has_seen_constructor;
ClassLiteralPropertyT property = ParseClassPropertyDefinition(
&checker, &class_info, &property_name, has_extends, &is_computed_name,
- &class_info.has_seen_constructor, &property_kind, &is_static,
- &class_info.has_name_static_property, CHECK_OK);
+ &property_kind, &is_static, CHECK_OK);
if (!class_info.has_static_computed_names && is_static &&
is_computed_name) {
class_info.has_static_computed_names = true;
@@ -4971,7 +4983,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
break;
case Token::ASYNC:
if (PeekAhead() == Token::FUNCTION &&
- !scanner()->HasAnyLineTerminatorAfterNext()) {
+ !scanner()->HasLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
return ParseAsyncFunctionDeclaration(nullptr, false, ok);
}
@@ -4979,12 +4991,13 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem(
default:
break;
}
- return ParseStatement(nullptr, kAllowLabelledFunctionStatement, ok);
+ return ParseStatement(nullptr, nullptr, kAllowLabelledFunctionStatement, ok);
}
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
AllowLabelledFunctionStatement allow_function, bool* ok) {
// Statement ::
// Block
@@ -5003,6 +5016,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
// TryStatement
// DebuggerStatement
+ // {own_labels} is always a subset of {labels}.
+ DCHECK_IMPLIES(labels == nullptr, own_labels == nullptr);
+
// Note: Since labels can only be used by 'break' and 'continue'
// statements, which themselves are only valid within blocks,
// iterations or 'switch' statements (i.e., BreakableStatements),
@@ -5018,14 +5034,14 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
case Token::IF:
return ParseIfStatement(labels, ok);
case Token::DO:
- return ParseDoWhileStatement(labels, ok);
+ return ParseDoWhileStatement(labels, own_labels, ok);
case Token::WHILE:
- return ParseWhileStatement(labels, ok);
+ return ParseWhileStatement(labels, own_labels, ok);
case Token::FOR:
if (V8_UNLIKELY(is_async_function() && PeekAhead() == Token::AWAIT)) {
- return ParseForAwaitStatement(labels, ok);
+ return ParseForAwaitStatement(labels, own_labels, ok);
}
- return ParseForStatement(labels, ok);
+ return ParseForStatement(labels, own_labels, ok);
case Token::CONTINUE:
return ParseContinueStatement(ok);
case Token::BREAK:
@@ -5068,7 +5084,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
case Token::VAR:
return ParseVariableStatement(kStatement, nullptr, ok);
case Token::ASYNC:
- if (!scanner()->HasAnyLineTerminatorAfterNext() &&
+ if (!scanner()->HasLineTerminatorAfterNext() &&
PeekAhead() == Token::FUNCTION) {
impl()->ReportMessageAt(
scanner()->peek_location(),
@@ -5078,7 +5094,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement(
}
V8_FALLTHROUGH;
default:
- return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
+ return ParseExpressionOrLabelledStatement(labels, own_labels,
+ allow_function, ok);
}
}
@@ -5118,7 +5135,7 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement(
ZonePtrList<const AstRawString>* labels, bool* ok) {
if (is_strict(language_mode()) || peek() != Token::FUNCTION) {
- return ParseStatement(labels, ok);
+ return ParseStatement(labels, nullptr, ok);
} else {
// Make a block around the statement for a lexical binding
// is introduced by a FunctionDeclaration.
@@ -5178,6 +5195,7 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseExpressionOrLabelledStatement(
ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels,
AllowLabelledFunctionStatement allow_function, bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
@@ -5203,7 +5221,7 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
// However, ASI may insert a line break before an identifier or a brace.
if (next_next != Token::LBRACK &&
((next_next != Token::LBRACE && next_next != Token::IDENTIFIER) ||
- scanner_->HasAnyLineTerminatorAfterNext())) {
+ scanner_->HasLineTerminatorAfterNext())) {
break;
}
impl()->ReportMessageAt(scanner()->peek_location(),
@@ -5221,22 +5239,22 @@ ParserBase<Impl>::ParseExpressionOrLabelledStatement(
impl()->IsIdentifier(expr)) {
// The whole expression was a single identifier, and not, e.g.,
// something starting with an identifier or a parenthesized identifier.
- labels = impl()->DeclareLabel(labels, impl()->AsIdentifierExpression(expr),
- CHECK_OK);
+ impl()->DeclareLabel(&labels, &own_labels,
+ impl()->AsIdentifierExpression(expr), CHECK_OK);
Consume(Token::COLON);
// ES#sec-labelled-function-declarations Labelled Function Declarations
if (peek() == Token::FUNCTION && is_sloppy(language_mode()) &&
allow_function == kAllowLabelledFunctionStatement) {
return ParseFunctionDeclaration(ok);
}
- return ParseStatement(labels, allow_function, ok);
+ return ParseStatement(labels, own_labels, allow_function, ok);
}
// If we have an extension, we allow a native function declaration.
// A native function declaration starts with "native function" with
// no line-terminator between the two words.
if (extension_ != nullptr && peek() == Token::FUNCTION &&
- !scanner()->HasAnyLineTerminatorBeforeNext() && impl()->IsNative(expr) &&
+ !scanner()->HasLineTerminatorBeforeNext() && impl()->IsNative(expr) &&
!scanner()->literal_contains_escapes()) {
return ParseNativeDeclaration(ok);
}
@@ -5289,7 +5307,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseContinueStatement(
Expect(Token::CONTINUE, CHECK_OK);
IdentifierT label = impl()->NullIdentifier();
Token::Value tok = peek();
- if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
+ if (!scanner()->HasLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
tok != Token::RBRACE && tok != Token::EOS) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
@@ -5326,7 +5344,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseBreakStatement(
Expect(Token::BREAK, CHECK_OK);
IdentifierT label = impl()->NullIdentifier();
Token::Value tok = peek();
- if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
+ if (!scanner()->HasLineTerminatorBeforeNext() && tok != Token::SEMICOLON &&
tok != Token::RBRACE && tok != Token::EOS) {
// ECMA allows "eval" or "arguments" as labels even in strict mode.
label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
@@ -5380,7 +5398,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
Token::Value tok = peek();
ExpressionT return_value = impl()->NullExpression();
- if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON ||
+ if (scanner()->HasLineTerminatorBeforeNext() || tok == Token::SEMICOLON ||
tok == Token::RBRACE || tok == Token::EOS) {
if (IsDerivedConstructor(function_state_->kind())) {
return_value = impl()->ThisExpression(loc.beg_pos);
@@ -5421,7 +5439,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
{
BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos);
- body = ParseStatement(labels, CHECK_OK);
+ body = ParseStatement(labels, nullptr, CHECK_OK);
with_scope->set_end_position(scanner()->location().end_pos);
}
return factory()->NewWithStatement(with_scope, expr, body, pos);
@@ -5429,11 +5447,13 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWithStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
- auto loop = factory()->NewDoWhileStatement(labels, peek_position());
+ auto loop =
+ factory()->NewDoWhileStatement(labels, own_labels, peek_position());
typename Types::Target target(this, loop);
SourceRange body_range;
@@ -5442,7 +5462,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
Expect(Token::DO, CHECK_OK);
{
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr, CHECK_OK);
}
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
@@ -5464,11 +5484,12 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDoWhileStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
- auto loop = factory()->NewWhileStatement(labels, peek_position());
+ auto loop = factory()->NewWhileStatement(labels, own_labels, peek_position());
typename Types::Target target(this, loop);
SourceRange body_range;
@@ -5480,7 +5501,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseWhileStatement(
Expect(Token::RPAREN, CHECK_OK);
{
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr, CHECK_OK);
}
loop->Initialize(cond, body);
@@ -5497,7 +5518,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseThrowStatement(
Expect(Token::THROW, CHECK_OK);
int pos = position();
- if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+ if (scanner()->HasLineTerminatorBeforeNext()) {
ReportMessage(MessageTemplate::kNewlineAfterThrow);
*ok = false;
return impl()->NullStatement();
@@ -5679,7 +5700,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// Either a standard for loop
// for (<init>; <cond>; <next>) { ... }
// or a for-each loop
@@ -5719,8 +5741,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
if (CheckInOrOf(&for_info.mode)) {
scope()->set_is_hidden();
- return ParseForEachStatementWithDeclarations(stmt_pos, &for_info, labels,
- inner_block_scope, ok);
+ return ParseForEachStatementWithDeclarations(
+ stmt_pos, &for_info, labels, own_labels, inner_block_scope, ok);
}
Expect(Token::SEMICOLON, CHECK_OK);
@@ -5732,8 +5754,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
// No variable declarations will have been created in inner_block_scope.
DCHECK_NULL(finalized);
USE(finalized);
- return ParseStandardForLoopWithLexicalDeclarations(stmt_pos, init,
- &for_info, labels, ok);
+ return ParseStandardForLoopWithLexicalDeclarations(
+ stmt_pos, init, &for_info, labels, own_labels, ok);
}
StatementT init = impl()->NullStatement();
@@ -5745,7 +5767,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
if (CheckInOrOf(&for_info.mode)) {
return ParseForEachStatementWithDeclarations(stmt_pos, &for_info, labels,
- nullptr, ok);
+ own_labels, nullptr, ok);
}
init = impl()->BuildInitializationBlock(&for_info.parsing_result, nullptr,
@@ -5768,9 +5790,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
}
if (is_for_each) {
- return ParseForEachStatementWithoutDeclarations(stmt_pos, expression,
- lhs_beg_pos, lhs_end_pos,
- &for_info, labels, ok);
+ return ParseForEachStatementWithoutDeclarations(
+ stmt_pos, expression, lhs_beg_pos, lhs_end_pos, &for_info, labels,
+ own_labels, ok);
}
// Initializer is just an expression.
init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
@@ -5782,8 +5804,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
ExpressionT cond = impl()->NullExpression();
StatementT next = impl()->NullStatement();
StatementT body = impl()->NullStatement();
- ForStatementT loop =
- ParseStandardForLoop(stmt_pos, labels, &cond, &next, &body, CHECK_OK);
+ ForStatementT loop = ParseStandardForLoop(stmt_pos, labels, own_labels, &cond,
+ &next, &body, CHECK_OK);
loop->Initialize(init, cond, next, body);
return loop;
}
@@ -5792,7 +5814,8 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithDeclarations(
int stmt_pos, ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
- Scope* inner_block_scope, bool* ok) {
+ ZonePtrList<const AstRawString>* own_labels, Scope* inner_block_scope,
+ bool* ok) {
// Just one declaration followed by in/of.
if (for_info->parsing_result.declarations.size() != 1) {
impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
@@ -5820,7 +5843,8 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
BlockT init_block = impl()->RewriteForVarInLegacy(*for_info);
- auto loop = factory()->NewForEachStatement(for_info->mode, labels, stmt_pos);
+ auto loop = factory()->NewForEachStatement(for_info->mode, labels, own_labels,
+ stmt_pos);
typename Types::Target target(this, loop);
ExpressionT enumerable = impl()->NullExpression();
@@ -5850,7 +5874,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
- StatementT body = ParseStatement(nullptr, CHECK_OK);
+ StatementT body = ParseStatement(nullptr, nullptr, CHECK_OK);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
impl()->DesugarBindingInForEachStatement(for_info, &body_block,
@@ -5888,7 +5912,8 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
- ForInfo* for_info, ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ForInfo* for_info, ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// Initializer is reference followed by in/of.
if (!expression->IsArrayLiteral() && !expression->IsObjectLiteral()) {
expression = CheckAndRewriteReferenceExpression(
@@ -5896,7 +5921,8 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
kSyntaxError, CHECK_OK);
}
- auto loop = factory()->NewForEachStatement(for_info->mode, labels, stmt_pos);
+ auto loop = factory()->NewForEachStatement(for_info->mode, labels, own_labels,
+ stmt_pos);
typename Types::Target target(this, loop);
ExpressionT enumerable = impl()->NullExpression();
@@ -5915,7 +5941,7 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr, CHECK_OK);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
}
return impl()->InitializeForEachStatement(loop, expression, enumerable, body);
@@ -5925,7 +5951,8 @@ template <typename Impl>
typename ParserBase<Impl>::StatementT
ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
int stmt_pos, StatementT init, ForInfo* for_info,
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// The condition and the next statement of the for loop must be parsed
// in a new scope.
Scope* inner_scope = NewScope(BLOCK_SCOPE);
@@ -5936,8 +5963,8 @@ ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
{
BlockState block_state(&scope_, inner_scope);
scope()->set_start_position(scanner()->location().beg_pos);
- loop =
- ParseStandardForLoop(stmt_pos, labels, &cond, &next, &body, CHECK_OK);
+ loop = ParseStandardForLoop(stmt_pos, labels, own_labels, &cond, &next,
+ &body, CHECK_OK);
scope()->set_end_position(scanner()->location().end_pos);
}
@@ -5980,9 +6007,10 @@ ParserBase<Impl>::ParseStandardForLoopWithLexicalDeclarations(
template <typename Impl>
typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
- int stmt_pos, ZonePtrList<const AstRawString>* labels, ExpressionT* cond,
+ int stmt_pos, ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, ExpressionT* cond,
StatementT* next, StatementT* body, bool* ok) {
- ForStatementT loop = factory()->NewForStatement(labels, stmt_pos);
+ ForStatementT loop = factory()->NewForStatement(labels, own_labels, stmt_pos);
typename Types::Target target(this, loop);
if (peek() != Token::SEMICOLON) {
@@ -5999,7 +6027,7 @@ typename ParserBase<Impl>::ForStatementT ParserBase<Impl>::ParseStandardForLoop(
SourceRange body_range;
{
SourceRangeScope range_scope(scanner(), &body_range);
- *body = ParseStatement(nullptr, CHECK_OK);
+ *body = ParseStatement(nullptr, nullptr, CHECK_OK);
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
@@ -6019,7 +6047,8 @@ void ParserBase<Impl>::MarkLoopVariableAsAssigned(
template <typename Impl>
typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
- ZonePtrList<const AstRawString>* labels, bool* ok) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, bool* ok) {
// for await '(' ForDeclaration of AssignmentExpression ')'
DCHECK(is_async_function());
@@ -6036,7 +6065,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
scope()->set_start_position(scanner()->location().beg_pos);
scope()->set_is_hidden();
- auto loop = factory()->NewForOfStatement(labels, stmt_pos);
+ auto loop = factory()->NewForOfStatement(labels, own_labels, stmt_pos);
typename Types::Target target(this, loop);
ExpressionT each_variable = impl()->NullExpression();
@@ -6119,7 +6148,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
- body = ParseStatement(nullptr, CHECK_OK);
+ body = ParseStatement(nullptr, nullptr, CHECK_OK);
scope()->set_end_position(scanner()->location().end_pos);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index dacce7d38f..41ff551091 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -412,7 +412,8 @@ Parser::Parser(ParseInfo* info)
info->runtime_call_stats(), info->logger(),
info->script().is_null() ? -1 : info->script()->id(),
info->is_module(), true),
- scanner_(info->unicode_cache()),
+ scanner_(info->unicode_cache(), info->character_stream(),
+ info->is_module()),
reusable_preparser_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
source_range_map_(info->source_range_map()),
@@ -507,7 +508,7 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
// Initialize parser state.
DeserializeScopeChain(isolate, info, info->maybe_outer_scope_info());
- scanner_.Initialize(info->character_stream(), info->is_module());
+ scanner_.Initialize();
FunctionLiteral* result = DoParseProgram(isolate, info);
MaybeResetCharacterStream(info, result);
@@ -701,7 +702,7 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
// Initialize parser state.
Handle<String> name(shared_info->Name(), isolate);
info->set_function_name(ast_value_factory()->GetString(name));
- scanner_.Initialize(info->character_stream(), info->is_module());
+ scanner_.Initialize();
FunctionLiteral* result =
DoParseFunction(isolate, info, info->function_name());
@@ -775,7 +776,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
if (IsArrowFunction(kind)) {
if (IsAsyncFunction(kind)) {
- DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
+ DCHECK(!scanner()->HasLineTerminatorAfterNext());
if (!Check(Token::ASYNC)) {
CHECK(stack_overflow());
return nullptr;
@@ -798,7 +799,7 @@ FunctionLiteral* Parser::DoParseFunction(Isolate* isolate, ParseInfo* info,
ParserFormalParameters formals(scope);
// The outer FunctionState should not contain destructuring assignments.
DCHECK_EQ(0,
- function_state.destructuring_assignments_to_rewrite().length());
+ function_state.destructuring_assignments_to_rewrite().size());
{
// Parsing patterns as variable reference expression creates
// NewUnresolved references in current scope. Enter arrow function
@@ -943,10 +944,8 @@ const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
return GetSymbol();
}
-void Parser::ParseExportClause(ZonePtrList<const AstRawString>* export_names,
- ZoneList<Scanner::Location>* export_locations,
- ZonePtrList<const AstRawString>* local_names,
- Scanner::Location* reserved_loc, bool* ok) {
+ZoneChunkList<Parser::ExportClauseData>* Parser::ParseExportClause(
+ Scanner::Location* reserved_loc, bool* ok) {
// ExportClause :
// '{' '}'
// '{' ExportsList '}'
@@ -959,8 +958,10 @@ void Parser::ParseExportClause(ZonePtrList<const AstRawString>* export_names,
// ExportSpecifier :
// IdentifierName
// IdentifierName 'as' IdentifierName
+ ZoneChunkList<ExportClauseData>* export_data =
+ new (zone()) ZoneChunkList<ExportClauseData>(zone());
- Expect(Token::LBRACE, CHECK_OK_VOID);
+ Expect(Token::LBRACE, CHECK_OK);
Token::Value name_tok;
while ((name_tok = peek()) != Token::RBRACE) {
@@ -971,11 +972,11 @@ void Parser::ParseExportClause(ZonePtrList<const AstRawString>* export_names,
parsing_module_)) {
*reserved_loc = scanner()->location();
}
- const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
+ const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
const AstRawString* export_name = nullptr;
Scanner::Location location = scanner()->location();
if (CheckContextualKeyword(Token::AS)) {
- export_name = ParseIdentifierName(CHECK_OK_VOID);
+ export_name = ParseIdentifierName(CHECK_OK);
// Set the location to the whole "a as b" string, so that it makes sense
// both for errors due to "a" and for errors due to "b".
location.end_pos = scanner()->location().end_pos;
@@ -983,14 +984,13 @@ void Parser::ParseExportClause(ZonePtrList<const AstRawString>* export_names,
if (export_name == nullptr) {
export_name = local_name;
}
- export_names->Add(export_name, zone());
- local_names->Add(local_name, zone());
- export_locations->Add(location, zone());
+ export_data->push_back({export_name, local_name, location});
if (peek() == Token::RBRACE) break;
- Expect(Token::COMMA, CHECK_OK_VOID);
+ Expect(Token::COMMA, CHECK_OK);
}
- Expect(Token::RBRACE, CHECK_OK_VOID);
+ Expect(Token::RBRACE, CHECK_OK);
+ return export_data;
}
ZonePtrList<const Parser::NamedImport>* Parser::ParseNamedImports(int pos,
@@ -1179,7 +1179,7 @@ Statement* Parser::ParseExportDefault(bool* ok) {
case Token::ASYNC:
if (PeekAhead() == Token::FUNCTION &&
- !scanner()->HasAnyLineTerminatorAfterNext()) {
+ !scanner()->HasLineTerminatorAfterNext()) {
Consume(Token::ASYNC);
result = ParseAsyncFunctionDeclaration(&local_names, true, CHECK_OK);
break;
@@ -1264,11 +1264,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
// encountered, and then throw a SyntaxError if we are in the
// non-FromClause case.
Scanner::Location reserved_loc = Scanner::Location::invalid();
- ZonePtrList<const AstRawString> export_names(1, zone());
- ZoneList<Scanner::Location> export_locations(1, zone());
- ZonePtrList<const AstRawString> original_names(1, zone());
- ParseExportClause(&export_names, &export_locations, &original_names,
- &reserved_loc, CHECK_OK);
+ ZoneChunkList<ExportClauseData>* export_data =
+ ParseExportClause(&reserved_loc, CHECK_OK);
const AstRawString* module_specifier = nullptr;
Scanner::Location specifier_loc;
if (CheckContextualKeyword(Token::FROM)) {
@@ -1281,21 +1278,18 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
return nullptr;
}
ExpectSemicolon(CHECK_OK);
- const int length = export_names.length();
- DCHECK_EQ(length, original_names.length());
- DCHECK_EQ(length, export_locations.length());
if (module_specifier == nullptr) {
- for (int i = 0; i < length; ++i) {
- module()->AddExport(original_names[i], export_names[i],
- export_locations[i], zone());
+ for (const ExportClauseData& data : *export_data) {
+ module()->AddExport(data.local_name, data.export_name, data.location,
+ zone());
}
- } else if (length == 0) {
+ } else if (export_data->is_empty()) {
module()->AddEmptyImport(module_specifier, specifier_loc);
} else {
- for (int i = 0; i < length; ++i) {
- module()->AddExport(original_names[i], export_names[i],
- module_specifier, export_locations[i],
- specifier_loc, zone());
+ for (const ExportClauseData& data : *export_data) {
+ module()->AddExport(data.local_name, data.export_name,
+ module_specifier, data.location, specifier_loc,
+ zone());
}
}
return factory()->NewEmptyStatement(pos);
@@ -1410,7 +1404,7 @@ Block* Parser::BuildInitializationBlock(
DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names, bool* ok) {
Block* result = factory()->NewBlock(1, true);
- for (auto declaration : parsing_result->declarations) {
+ for (const auto& declaration : parsing_result->declarations) {
DeclareAndInitializeVariables(result, &(parsing_result->descriptor),
&declaration, names, CHECK_OK);
}
@@ -1473,29 +1467,40 @@ Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
pos);
}
-ZonePtrList<const AstRawString>* Parser::DeclareLabel(
- ZonePtrList<const AstRawString>* labels, VariableProxy* var, bool* ok) {
+void Parser::DeclareLabel(ZonePtrList<const AstRawString>** labels,
+ ZonePtrList<const AstRawString>** own_labels,
+ VariableProxy* var, bool* ok) {
DCHECK(IsIdentifier(var));
const AstRawString* label = var->raw_name();
+
// TODO(1240780): We don't check for redeclaration of labels
// during preparsing since keeping track of the set of active
// labels requires nontrivial changes to the way scopes are
// structured. However, these are probably changes we want to
// make later anyway so we should go back and fix this then.
- if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
+ if (ContainsLabel(*labels, label) || TargetStackContainsLabel(label)) {
ReportMessage(MessageTemplate::kLabelRedeclaration, label);
*ok = false;
- return nullptr;
+ return;
}
- if (labels == nullptr) {
- labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
+
+ // Add {label} to both {labels} and {own_labels}.
+ if (*labels == nullptr) {
+ DCHECK_NULL(*own_labels);
+ *labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
+ *own_labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
+ } else {
+ if (*own_labels == nullptr) {
+ *own_labels = new (zone()) ZonePtrList<const AstRawString>(1, zone());
+ }
}
- labels->Add(label, zone());
+ (*labels)->Add(label, zone());
+ (*own_labels)->Add(label, zone());
+
// Remove the "ghost" variable that turned out to be a label
// from the top scope. This way, we don't try to resolve it
// during the scope processing.
scope()->RemoveUnresolved(var);
- return labels;
}
bool Parser::ContainsLabel(ZonePtrList<const AstRawString>* labels,
@@ -2194,7 +2199,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(nullptr, kNoSourcePosition);
+ factory()->NewForStatement(nullptr, nullptr, kNoSourcePosition);
outer_block->statements()->Add(outer_loop, zone());
outer_block->set_scope(scope());
@@ -3396,9 +3401,10 @@ IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
if (stat == nullptr) continue;
DCHECK(stat->is_target_for_anonymous());
- if (anonymous || ContainsLabel(stat->labels(), label)) {
+ if (anonymous || ContainsLabel(stat->own_labels(), label)) {
return stat;
}
+ if (ContainsLabel(stat->labels(), label)) break;
}
return nullptr;
}
@@ -3442,7 +3448,7 @@ void Parser::ParseOnBackground(ParseInfo* info) {
DCHECK_NULL(info->literal());
FunctionLiteral* result = nullptr;
- scanner_.Initialize(info->character_stream(), info->is_module());
+ scanner_.Initialize();
DCHECK(info->maybe_outer_scope_info().is_null());
DCHECK(original_scope_);
@@ -3652,10 +3658,11 @@ void Parser::RewriteAsyncFunctionBody(ZonePtrList<Statement>* body,
void Parser::RewriteDestructuringAssignments() {
const auto& assignments =
function_state_->destructuring_assignments_to_rewrite();
- for (int i = assignments.length() - 1; i >= 0; --i) {
+ auto it = assignments.rbegin();
+ for (; it != assignments.rend(); ++it) {
// Rewrite list in reverse, so that nested assignment patterns are rewritten
// correctly.
- RewritableExpression* to_rewrite = assignments[i];
+ RewritableExpression* to_rewrite = *it;
DCHECK_NOT_NULL(to_rewrite);
if (!to_rewrite->is_rewritten()) {
// Since this function is called at the end of parsing the program,
diff --git a/deps/v8/src/parsing/parser.h b/deps/v8/src/parsing/parser.h
index 2dec83b274..00e73f37a2 100644
--- a/deps/v8/src/parsing/parser.h
+++ b/deps/v8/src/parsing/parser.h
@@ -14,9 +14,9 @@
#include "src/globals.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/parsing.h"
-#include "src/parsing/preparse-data.h"
#include "src/parsing/preparser.h"
#include "src/utils.h"
+#include "src/zone/zone-chunk-list.h"
namespace v8 {
@@ -262,10 +262,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void ParseImportDeclaration(bool* ok);
Statement* ParseExportDeclaration(bool* ok);
Statement* ParseExportDefault(bool* ok);
- void ParseExportClause(ZonePtrList<const AstRawString>* export_names,
- ZoneList<Scanner::Location>* export_locations,
- ZonePtrList<const AstRawString>* local_names,
- Scanner::Location* reserved_loc, bool* ok);
+ struct ExportClauseData {
+ const AstRawString* export_name;
+ const AstRawString* local_name;
+ Scanner::Location location;
+ };
+ ZoneChunkList<ExportClauseData>* ParseExportClause(
+ Scanner::Location* reserved_loc, bool* ok);
struct NamedImport : public ZoneObject {
const AstRawString* import_name;
const AstRawString* local_name;
@@ -280,8 +283,9 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Block* BuildInitializationBlock(DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names,
bool* ok);
- ZonePtrList<const AstRawString>* DeclareLabel(
- ZonePtrList<const AstRawString>* labels, VariableProxy* expr, bool* ok);
+ void DeclareLabel(ZonePtrList<const AstRawString>** labels,
+ ZonePtrList<const AstRawString>** own_labels,
+ VariableProxy* expr, bool* ok);
bool ContainsLabel(ZonePtrList<const AstRawString>* labels,
const AstRawString* label);
Expression* RewriteReturn(Expression* return_value, int pos);
@@ -954,7 +958,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void SetFunctionNameFromIdentifierRef(Expression* value,
Expression* identifier);
- V8_INLINE ZoneList<typename ExpressionClassifier::Error>*
+ V8_INLINE ZoneVector<typename ExpressionClassifier::Error>*
GetReportedErrorList() const {
return function_state_->GetReportedErrorList();
}
diff --git a/deps/v8/src/parsing/pattern-rewriter.cc b/deps/v8/src/parsing/pattern-rewriter.cc
index b981b6d12e..ed3231c151 100644
--- a/deps/v8/src/parsing/pattern-rewriter.cc
+++ b/deps/v8/src/parsing/pattern-rewriter.cc
@@ -671,7 +671,8 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
// #maybe_store_and_unset_done;
// #increment_index;
// }
- WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
+ WhileStatement* loop =
+ factory()->NewWhileStatement(nullptr, nullptr, nopos);
{
Expression* condition = factory()->NewUnaryOperation(
Token::NOT, factory()->NewVariableProxy(done), nopos);
diff --git a/deps/v8/src/parsing/preparse-data.cc b/deps/v8/src/parsing/preparse-data.cc
deleted file mode 100644
index e39218111d..0000000000
--- a/deps/v8/src/parsing/preparse-data.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2010 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/preparse-data.h"
-#include "src/base/hashmap.h"
-#include "src/base/logging.h"
-#include "src/globals.h"
-#include "src/objects-inl.h"
-#include "src/parsing/parser.h"
-
-namespace v8 {
-namespace internal {
-
-PreParseData::FunctionData PreParseData::GetFunctionData(int start) const {
- auto it = functions_.find(start);
- if (it != functions_.end()) {
- return it->second;
- }
- return FunctionData();
-}
-
-void PreParseData::AddFunctionData(int start, FunctionData&& data) {
- DCHECK(data.is_valid());
- functions_[start] = std::move(data);
-}
-
-void PreParseData::AddFunctionData(int start, const FunctionData& data) {
- DCHECK(data.is_valid());
- functions_[start] = data;
-}
-
-size_t PreParseData::size() const { return functions_.size(); }
-
-PreParseData::const_iterator PreParseData::begin() const {
- return functions_.begin();
-}
-
-PreParseData::const_iterator PreParseData::end() const {
- return functions_.end();
-}
-
-} // namespace internal
-} // namespace v8.
diff --git a/deps/v8/src/parsing/preparse-data.h b/deps/v8/src/parsing/preparse-data.h
deleted file mode 100644
index 0e40c76927..0000000000
--- a/deps/v8/src/parsing/preparse-data.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_PARSING_PREPARSE_DATA_H_
-#define V8_PARSING_PREPARSE_DATA_H_
-
-#include <unordered_map>
-
-#include "src/allocation.h"
-#include "src/base/hashmap.h"
-#include "src/collector.h"
-#include "src/messages.h"
-namespace v8 {
-namespace internal {
-
-class PreParserLogger final {
- public:
- PreParserLogger()
- : end_(-1),
- num_parameters_(-1),
- num_inner_functions_(-1) {}
-
- void LogFunction(int end, int num_parameters, int num_inner_functions) {
- end_ = end;
- num_parameters_ = num_parameters;
- num_inner_functions_ = num_inner_functions;
- }
-
- int end() const { return end_; }
- int num_parameters() const {
- return num_parameters_;
- }
- int num_inner_functions() const { return num_inner_functions_; }
-
- private:
- int end_;
- // For function entries.
- int num_parameters_;
- int num_inner_functions_;
-};
-
-class PreParseData final {
- public:
- struct FunctionData {
- int end;
- int num_parameters;
- int num_inner_functions;
- LanguageMode language_mode;
- bool uses_super_property : 1;
-
- FunctionData() : end(kNoSourcePosition) {}
-
- FunctionData(int end, int num_parameters, int num_inner_functions,
- LanguageMode language_mode, bool uses_super_property)
- : end(end),
- num_parameters(num_parameters),
- num_inner_functions(num_inner_functions),
- language_mode(language_mode),
- uses_super_property(uses_super_property) {}
-
- bool is_valid() const {
- DCHECK_IMPLIES(end < 0, end == kNoSourcePosition);
- return end != kNoSourcePosition;
- }
- };
-
- FunctionData GetFunctionData(int start) const;
- void AddFunctionData(int start, FunctionData&& data);
- void AddFunctionData(int start, const FunctionData& data);
- size_t size() const;
-
- typedef std::unordered_map<int, FunctionData>::const_iterator const_iterator;
- const_iterator begin() const;
- const_iterator end() const;
-
- private:
- std::unordered_map<int, FunctionData> functions_;
-};
-
-} // namespace internal
-} // namespace v8.
-
-#endif // V8_PARSING_PREPARSE_DATA_H_
diff --git a/deps/v8/src/parsing/preparsed-scope-data.cc b/deps/v8/src/parsing/preparsed-scope-data.cc
index 0dab3f9ee1..90e8819e32 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.cc
+++ b/deps/v8/src/parsing/preparsed-scope-data.cc
@@ -481,6 +481,11 @@ uint8_t ConsumedPreParsedScopeData::ByteData::ReadQuarter() {
return result;
}
+size_t ConsumedPreParsedScopeData::ByteData::RemainingBytes() const {
+ DCHECK_NOT_NULL(data_);
+ return data_->length() - index_;
+}
+
ConsumedPreParsedScopeData::ConsumedPreParsedScopeData()
: isolate_(nullptr), scope_data_(new ByteData()), child_index_(0) {}
@@ -577,7 +582,7 @@ void ConsumedPreParsedScopeData::RestoreData(Scope* scope) {
if (scope_data_->RemainingBytes() < kUint8Size) {
// Temporary debugging code for detecting inconsistent data. Write debug
// information on the stack, then crash.
- data_->GetIsolate()->PushStackTraceAndDie();
+ isolate_->PushStackTraceAndDie();
}
// scope_type is stored only in debug mode.
diff --git a/deps/v8/src/parsing/preparsed-scope-data.h b/deps/v8/src/parsing/preparsed-scope-data.h
index 6ad0f491f8..61d67291a4 100644
--- a/deps/v8/src/parsing/preparsed-scope-data.h
+++ b/deps/v8/src/parsing/preparsed-scope-data.h
@@ -12,7 +12,6 @@
#include "src/globals.h"
#include "src/handles.h"
#include "src/objects/shared-function-info.h"
-#include "src/parsing/preparse-data.h"
#include "src/zone/zone-chunk-list.h"
namespace v8 {
@@ -212,10 +211,7 @@ class ConsumedPreParsedScopeData {
uint8_t ReadUint8();
uint8_t ReadQuarter();
- size_t RemainingBytes() const {
- DCHECK_NOT_NULL(data_);
- return data_->length() - index_;
- }
+ size_t RemainingBytes() const;
// private:
PodArray<uint8_t>* data_;
diff --git a/deps/v8/src/parsing/preparser-logger.h b/deps/v8/src/parsing/preparser-logger.h
new file mode 100644
index 0000000000..55394ca2be
--- /dev/null
+++ b/deps/v8/src/parsing/preparser-logger.h
@@ -0,0 +1,35 @@
+// Copyright 2018 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_PREPARSER_LOGGER_H_
+#define V8_PARSING_PREPARSER_LOGGER_H_
+
+namespace v8 {
+namespace internal {
+
+class PreParserLogger final {
+ public:
+ PreParserLogger() : end_(-1), num_parameters_(-1), num_inner_functions_(-1) {}
+
+ void LogFunction(int end, int num_parameters, int num_inner_functions) {
+ end_ = end;
+ num_parameters_ = num_parameters;
+ num_inner_functions_ = num_inner_functions;
+ }
+
+ int end() const { return end_; }
+ int num_parameters() const { return num_parameters_; }
+ int num_inner_functions() const { return num_inner_functions_; }
+
+ private:
+ int end_;
+ // For function entries.
+ int num_parameters_;
+ int num_inner_functions_;
+};
+
+} // namespace internal
+} // namespace v8.
+
+#endif // V8_PARSING_PREPARSER_LOGGER_H_
diff --git a/deps/v8/src/parsing/preparser.cc b/deps/v8/src/parsing/preparser.cc
index 832d2033f2..d449c8d76b 100644
--- a/deps/v8/src/parsing/preparser.cc
+++ b/deps/v8/src/parsing/preparser.cc
@@ -11,7 +11,6 @@
#include "src/globals.h"
#include "src/parsing/duplicate-finder.h"
#include "src/parsing/parser-base.h"
-#include "src/parsing/preparse-data.h"
#include "src/parsing/preparsed-scope-data.h"
#include "src/parsing/preparser.h"
#include "src/unicode.h"
diff --git a/deps/v8/src/parsing/preparser.h b/deps/v8/src/parsing/preparser.h
index aa4f06d354..10c42fa940 100644
--- a/deps/v8/src/parsing/preparser.h
+++ b/deps/v8/src/parsing/preparser.h
@@ -8,8 +8,9 @@
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parser-base.h"
-#include "src/parsing/preparse-data.h"
+#include "src/parsing/preparser-logger.h"
#include "src/pending-compilation-error-handler.h"
+#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
@@ -64,7 +65,7 @@ class PreParserIdentifier {
bool IsPrivateName() const { return type_ == kPrivateNameIdentifier; }
private:
- enum Type {
+ enum Type : uint8_t {
kNullIdentifier,
kUnknownIdentifier,
kEvalIdentifier,
@@ -76,10 +77,11 @@ class PreParserIdentifier {
kPrivateNameIdentifier
};
- explicit PreParserIdentifier(Type type) : type_(type), string_(nullptr) {}
- Type type_;
+ explicit PreParserIdentifier(Type type) : string_(nullptr), type_(type) {}
// Only non-nullptr when PreParser.track_unresolved_variables_ is true.
const AstRawString* string_;
+
+ Type type_;
friend class PreParserExpression;
friend class PreParser;
friend class PreParserFactory;
@@ -341,6 +343,7 @@ class PreParserExpression {
// More dummy implementations of things PreParser doesn't need to track:
void SetShouldEagerCompile() {}
+ void mark_as_iife() {}
int position() const { return kNoSourcePosition; }
void set_function_token_position(int position) {}
@@ -400,7 +403,7 @@ class PreParserExpression {
typedef BitField<ExpressionType, TypeField::kNext, 4> ExpressionTypeField;
typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseAsmField;
- typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 10>
+ typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 8>
IdentifierTypeField;
typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField;
@@ -787,12 +790,14 @@ class PreParserFactory {
}
PreParserStatement NewDoWhileStatement(
- ZonePtrList<const AstRawString>* labels, int pos) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
}
- PreParserStatement NewWhileStatement(ZonePtrList<const AstRawString>* labels,
- int pos) {
+ PreParserStatement NewWhileStatement(
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
}
@@ -807,25 +812,28 @@ class PreParserFactory {
return PreParserStatement::Default();
}
- PreParserStatement NewForStatement(ZonePtrList<const AstRawString>* labels,
- int pos) {
+ PreParserStatement NewForStatement(
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
}
PreParserStatement NewForEachStatement(
ForEachStatement::VisitMode visit_mode,
- ZonePtrList<const AstRawString>* labels, int pos) {
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
}
- PreParserStatement NewForOfStatement(ZonePtrList<const AstRawString>* labels,
- int pos) {
+ PreParserStatement NewForOfStatement(
+ ZonePtrList<const AstRawString>* labels,
+ ZonePtrList<const AstRawString>* own_labels, int pos) {
return PreParserStatement::Default();
}
- PreParserExpression NewCallRuntime(Runtime::FunctionId id,
- ZoneList<PreParserExpression>* arguments,
- int pos) {
+ PreParserExpression NewCallRuntime(
+ Runtime::FunctionId id, ZoneChunkList<PreParserExpression>* arguments,
+ int pos) {
return PreParserExpression::Default();
}
@@ -1070,12 +1078,11 @@ class PreParser : public ParserBase<PreParser> {
const DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names, bool* ok);
- V8_INLINE ZonePtrList<const AstRawString>* DeclareLabel(
- ZonePtrList<const AstRawString>* labels, const PreParserExpression& expr,
- bool* ok) {
+ V8_INLINE void DeclareLabel(ZonePtrList<const AstRawString>** labels,
+ ZonePtrList<const AstRawString>** own_labels,
+ const PreParserExpression& expr, bool* ok) {
DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait());
DCHECK(IsIdentifier(expr));
- return labels;
}
// TODO(nikolaos): The preparser currently does not keep track of labels.
@@ -1726,7 +1733,7 @@ class PreParser : public ParserBase<PreParser> {
const PreParserExpression& value, const PreParserExpression& identifier) {
}
- V8_INLINE ZoneList<typename ExpressionClassifier::Error>*
+ V8_INLINE ZoneVector<typename ExpressionClassifier::Error>*
GetReportedErrorList() const {
return function_state_->GetReportedErrorList();
}
diff --git a/deps/v8/src/parsing/scanner-character-streams.cc b/deps/v8/src/parsing/scanner-character-streams.cc
index 052b6007ae..d38fdd7c42 100644
--- a/deps/v8/src/parsing/scanner-character-streams.cc
+++ b/deps/v8/src/parsing/scanner-character-streams.cc
@@ -88,8 +88,8 @@ class ExternalStringStream {
template <typename Char>
class ChunkedStream {
public:
- explicit ChunkedStream(ScriptCompiler::ExternalSourceStream* source,
- RuntimeCallStats* stats)
+ ChunkedStream(ScriptCompiler::ExternalSourceStream* source,
+ RuntimeCallStats* stats)
: source_(source), stats_(stats) {}
Range<Char> GetDataAt(size_t pos) {
@@ -100,15 +100,15 @@ class ChunkedStream {
}
~ChunkedStream() {
- for (size_t i = 0; i < chunks_.size(); i++) {
- delete[] chunks_[i].data;
- }
+ for (Chunk& chunk : chunks_) delete[] chunk.data;
}
static const bool kCanAccessHeap = false;
private:
struct Chunk {
+ Chunk(const Char* const data, size_t position, size_t length)
+ : data(data), position(position), length(length) {}
const Char* const data;
// The logical position of data.
const size_t position;
@@ -117,7 +117,7 @@ class ChunkedStream {
};
Chunk FindChunk(size_t position) {
- if (chunks_.empty()) FetchChunk(size_t{0});
+ while (V8_UNLIKELY(chunks_.empty())) FetchChunk(size_t{0});
// Walk forwards while the position is in front of the current chunk.
while (position >= chunks_.back().end_position() &&
@@ -134,6 +134,14 @@ class ChunkedStream {
UNREACHABLE();
}
+ virtual void ProcessChunk(const uint8_t* data, size_t position,
+ size_t length) {
+ // Incoming data has to be aligned to Char size.
+ DCHECK_EQ(0, length % sizeof(Char));
+ chunks_.emplace_back(reinterpret_cast<const Char*>(data), position,
+ length / sizeof(Char));
+ }
+
void FetchChunk(size_t position) {
const uint8_t* data = nullptr;
size_t length;
@@ -142,21 +150,110 @@ class ChunkedStream {
RuntimeCallCounterId::kGetMoreDataCallback);
length = source_->GetMoreData(&data);
}
- // Incoming data has to be aligned to Char size.
- DCHECK_EQ(0, length % sizeof(Char));
- chunks_.push_back(
- {reinterpret_cast<const Char*>(data), position, length / sizeof(Char)});
+ ProcessChunk(data, position, length);
}
- std::vector<struct Chunk> chunks_;
ScriptCompiler::ExternalSourceStream* source_;
RuntimeCallStats* stats_;
+
+ protected:
+ std::vector<struct Chunk> chunks_;
+};
+
+template <typename Char>
+class Utf8ChunkedStream : public ChunkedStream<uint16_t> {
+ public:
+ Utf8ChunkedStream(ScriptCompiler::ExternalSourceStream* source,
+ RuntimeCallStats* stats)
+ : ChunkedStream<uint16_t>(source, stats) {}
+
+ STATIC_ASSERT(sizeof(Char) == sizeof(uint16_t));
+ void ProcessChunk(const uint8_t* data, size_t position, size_t length) final {
+ if (length == 0) {
+ unibrow::uchar t = unibrow::Utf8::ValueOfIncrementalFinish(&state_);
+ if (t != unibrow::Utf8::kBufferEmpty) {
+ DCHECK_EQ(t, unibrow::Utf8::kBadChar);
+ incomplete_char_ = 0;
+ uint16_t* result = new uint16_t[1];
+ result[0] = unibrow::Utf8::kBadChar;
+ chunks_.emplace_back(result, position, 1);
+ position++;
+ }
+ chunks_.emplace_back(nullptr, position, 0);
+ delete[] data;
+ return;
+ }
+
+ // First count the number of complete characters that can be produced.
+
+ unibrow::Utf8::State state = state_;
+ uint32_t incomplete_char = incomplete_char_;
+ bool seen_bom = seen_bom_;
+
+ size_t i = 0;
+ size_t chars = 0;
+ while (i < length) {
+ unibrow::uchar t = unibrow::Utf8::ValueOfIncremental(data[i], &i, &state,
+ &incomplete_char);
+ if (!seen_bom && t == kUtf8Bom && position + chars == 0) {
+ seen_bom = true;
+ // BOM detected at beginning of the stream. Don't copy it.
+ } else if (t != unibrow::Utf8::kIncomplete) {
+ chars++;
+ if (t > unibrow::Utf16::kMaxNonSurrogateCharCode) chars++;
+ }
+ }
+
+ // Process the data.
+
+ // If there aren't any complete characters, update the state without
+ // producing a chunk.
+ if (chars == 0) {
+ state_ = state;
+ incomplete_char_ = incomplete_char;
+ seen_bom_ = seen_bom;
+ delete[] data;
+ return;
+ }
+
+ // Update the state and produce a chunk with complete characters.
+ uint16_t* result = new uint16_t[chars];
+ uint16_t* cursor = result;
+ i = 0;
+
+ while (i < length) {
+ unibrow::uchar t = unibrow::Utf8::ValueOfIncremental(data[i], &i, &state_,
+ &incomplete_char_);
+ if (V8_LIKELY(t < kUtf8Bom)) {
+ *(cursor++) = static_cast<uc16>(t); // The by most frequent case.
+ } else if (t == unibrow::Utf8::kIncomplete) {
+ continue;
+ } else if (!seen_bom_ && t == kUtf8Bom && position == 0 &&
+ cursor == result) {
+ // BOM detected at beginning of the stream. Don't copy it.
+ seen_bom_ = true;
+ } else if (t <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+ *(cursor++) = static_cast<uc16>(t);
+ } else {
+ *(cursor++) = unibrow::Utf16::LeadSurrogate(t);
+ *(cursor++) = unibrow::Utf16::TrailSurrogate(t);
+ }
+ }
+
+ chunks_.emplace_back(result, position, chars);
+ delete[] data;
+ }
+
+ private:
+ uint32_t incomplete_char_ = 0;
+ unibrow::Utf8::State state_ = unibrow::Utf8::State::kAccept;
+ bool seen_bom_ = false;
};
// Provides a buffered utf-16 view on the bytes from the underlying ByteStream.
// Chars are buffered if either the underlying stream isn't utf-16 or the
// underlying utf-16 stream might move (is on-heap).
-template <typename Char, template <typename T> class ByteStream>
+template <template <typename T> class ByteStream>
class BufferedCharacterStream : public Utf16CharacterStream {
public:
template <class... TArgs>
@@ -165,13 +262,13 @@ class BufferedCharacterStream : public Utf16CharacterStream {
}
protected:
- bool ReadBlock() override {
+ bool ReadBlock() final {
size_t position = pos();
buffer_pos_ = position;
buffer_start_ = &buffer_[0];
buffer_cursor_ = buffer_start_;
- Range<Char> range = byte_stream_.GetDataAt(position);
+ Range<uint8_t> range = byte_stream_.GetDataAt(position);
if (range.length() == 0) {
buffer_end_ = buffer_start_;
return false;
@@ -183,14 +280,12 @@ class BufferedCharacterStream : public Utf16CharacterStream {
return true;
}
- bool can_access_heap() override {
- return ByteStream<uint16_t>::kCanAccessHeap;
- }
+ bool can_access_heap() final { return ByteStream<uint8_t>::kCanAccessHeap; }
private:
static const size_t kBufferSize = 512;
uc16 buffer_[kBufferSize];
- ByteStream<Char> byte_stream_;
+ ByteStream<uint8_t> byte_stream_;
};
// Provides a unbuffered utf-16 view on the bytes from the underlying
@@ -200,12 +295,11 @@ class UnbufferedCharacterStream : public Utf16CharacterStream {
public:
template <class... TArgs>
UnbufferedCharacterStream(size_t pos, TArgs... args) : byte_stream_(args...) {
- DCHECK(!ByteStream<uint16_t>::kCanAccessHeap);
buffer_pos_ = pos;
}
protected:
- bool ReadBlock() override {
+ bool ReadBlock() final {
size_t position = pos();
buffer_pos_ = position;
Range<uint16_t> range = byte_stream_.GetDataAt(position);
@@ -219,12 +313,50 @@ class UnbufferedCharacterStream : public Utf16CharacterStream {
return true;
}
- bool can_access_heap() override { return false; }
+ bool can_access_heap() final { return ByteStream<uint16_t>::kCanAccessHeap; }
- private:
ByteStream<uint16_t> byte_stream_;
};
+// Provides a unbuffered utf-16 view on the bytes from the underlying
+// ByteStream.
+class RelocatingCharacterStream
+ : public UnbufferedCharacterStream<OnHeapStream> {
+ public:
+ template <class... TArgs>
+ RelocatingCharacterStream(Isolate* isolate, size_t pos, TArgs... args)
+ : UnbufferedCharacterStream<OnHeapStream>(pos, args...),
+ isolate_(isolate) {
+ isolate->heap()->AddGCEpilogueCallback(UpdateBufferPointersCallback,
+ v8::kGCTypeAll, this);
+ }
+
+ private:
+ ~RelocatingCharacterStream() final {
+ isolate_->heap()->RemoveGCEpilogueCallback(UpdateBufferPointersCallback,
+ this);
+ }
+
+ static void UpdateBufferPointersCallback(v8::Isolate* v8_isolate,
+ v8::GCType type,
+ v8::GCCallbackFlags flags,
+ void* stream) {
+ reinterpret_cast<RelocatingCharacterStream*>(stream)
+ ->UpdateBufferPointers();
+ }
+
+ void UpdateBufferPointers() {
+ Range<uint16_t> range = byte_stream_.GetDataAt(0);
+ if (range.start != buffer_start_) {
+ buffer_cursor_ = (buffer_cursor_ - buffer_start_) + range.start;
+ buffer_start_ = range.start;
+ buffer_end_ = range.end;
+ }
+ }
+
+ Isolate* isolate_;
+};
+
// ----------------------------------------------------------------------------
// BufferedUtf16CharacterStreams
//
@@ -240,7 +372,7 @@ class BufferedUtf16CharacterStream : public Utf16CharacterStream {
protected:
static const size_t kBufferSize = 512;
- bool ReadBlock() override;
+ bool ReadBlock() final;
// FillBuffer should read up to kBufferSize characters at position and store
// them into buffer_[0..]. It returns the number of characters stored.
@@ -285,14 +417,14 @@ class Utf8ExternalStreamingStream : public BufferedUtf16CharacterStream {
: current_({0, {0, 0, 0, unibrow::Utf8::State::kAccept}}),
source_stream_(source_stream),
stats_(stats) {}
- ~Utf8ExternalStreamingStream() override {
+ ~Utf8ExternalStreamingStream() final {
for (size_t i = 0; i < chunks_.size(); i++) delete[] chunks_[i].data;
}
- bool can_access_heap() override { return false; }
+ bool can_access_heap() final { return false; }
protected:
- size_t FillBuffer(size_t position) override;
+ size_t FillBuffer(size_t position) final;
private:
// A position within the data stream. It stores:
@@ -571,7 +703,7 @@ Utf16CharacterStream* ScannerStream::For(Isolate* isolate, Handle<String> data,
data = String::Flatten(isolate, data);
}
if (data->IsExternalOneByteString()) {
- return new BufferedCharacterStream<uint8_t, ExternalStringStream>(
+ return new BufferedCharacterStream<ExternalStringStream>(
static_cast<size_t>(start_pos),
ExternalOneByteString::cast(*data)->GetChars() + start_offset,
static_cast<size_t>(end_pos));
@@ -581,13 +713,14 @@ Utf16CharacterStream* ScannerStream::For(Isolate* isolate, Handle<String> data,
ExternalTwoByteString::cast(*data)->GetChars() + start_offset,
static_cast<size_t>(end_pos));
} else if (data->IsSeqOneByteString()) {
- return new BufferedCharacterStream<uint8_t, OnHeapStream>(
+ return new BufferedCharacterStream<OnHeapStream>(
static_cast<size_t>(start_pos), Handle<SeqOneByteString>::cast(data),
start_offset, static_cast<size_t>(end_pos));
} else if (data->IsSeqTwoByteString()) {
- return new BufferedCharacterStream<uint16_t, OnHeapStream>(
- static_cast<size_t>(start_pos), Handle<SeqTwoByteString>::cast(data),
- start_offset, static_cast<size_t>(end_pos));
+ return new RelocatingCharacterStream(
+ isolate, static_cast<size_t>(start_pos),
+ Handle<SeqTwoByteString>::cast(data), start_offset,
+ static_cast<size_t>(end_pos));
} else {
UNREACHABLE();
}
@@ -601,7 +734,7 @@ std::unique_ptr<Utf16CharacterStream> ScannerStream::ForTesting(
std::unique_ptr<Utf16CharacterStream> ScannerStream::ForTesting(
const char* data, size_t length) {
return std::unique_ptr<Utf16CharacterStream>(
- new BufferedCharacterStream<uint8_t, ExternalStringStream>(
+ new BufferedCharacterStream<ExternalStringStream>(
static_cast<size_t>(0), reinterpret_cast<const uint8_t*>(data),
static_cast<size_t>(length)));
}
@@ -615,8 +748,8 @@ Utf16CharacterStream* ScannerStream::For(
return new UnbufferedCharacterStream<ChunkedStream>(
static_cast<size_t>(0), source_stream, stats);
case v8::ScriptCompiler::StreamedSource::ONE_BYTE:
- return new BufferedCharacterStream<uint8_t, ChunkedStream>(
- static_cast<size_t>(0), source_stream, stats);
+ return new BufferedCharacterStream<ChunkedStream>(static_cast<size_t>(0),
+ source_stream, stats);
case v8::ScriptCompiler::StreamedSource::UTF8:
return new Utf8ExternalStreamingStream(source_stream, stats);
}
diff --git a/deps/v8/src/parsing/scanner-character-streams.h b/deps/v8/src/parsing/scanner-character-streams.h
index 12c5847f2f..091ef5b8ea 100644
--- a/deps/v8/src/parsing/scanner-character-streams.h
+++ b/deps/v8/src/parsing/scanner-character-streams.h
@@ -27,7 +27,6 @@ class V8_EXPORT_PRIVATE ScannerStream {
ScriptCompiler::StreamedSource::Encoding encoding,
RuntimeCallStats* stats);
- // For testing:
static std::unique_ptr<Utf16CharacterStream> ForTesting(const char* data);
static std::unique_ptr<Utf16CharacterStream> ForTesting(const char* data,
size_t length);
diff --git a/deps/v8/src/parsing/scanner-inl.h b/deps/v8/src/parsing/scanner-inl.h
new file mode 100644
index 0000000000..809ef655a7
--- /dev/null
+++ b/deps/v8/src/parsing/scanner-inl.h
@@ -0,0 +1,43 @@
+// Copyright 2018 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_SCANNER_INL_H_
+#define V8_PARSING_SCANNER_INL_H_
+
+#include "src/parsing/scanner.h"
+#include "src/unicode-cache-inl.h"
+
+namespace v8 {
+namespace internal {
+
+V8_INLINE Token::Value Scanner::SkipWhiteSpace() {
+ int start_position = source_pos();
+
+ while (true) {
+ // We won't skip behind the end of input.
+ DCHECK(!unicode_cache_->IsWhiteSpace(kEndOfInput));
+
+ // Advance as long as character is a WhiteSpace or LineTerminator.
+ // Remember if the latter is the case.
+ if (unibrow::IsLineTerminator(c0_)) {
+ next().after_line_terminator = true;
+ } else if (!unicode_cache_->IsWhiteSpace(c0_)) {
+ break;
+ }
+ Advance();
+ }
+
+ // Return whether or not we skipped any characters.
+ if (source_pos() == start_position) {
+ DCHECK_NE('0', c0_);
+ return Token::ILLEGAL;
+ }
+
+ return Token::WHITESPACE;
+}
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_PARSING_SCANNER_INL_H_
diff --git a/deps/v8/src/parsing/scanner.cc b/deps/v8/src/parsing/scanner.cc
index 852b5e400b..781832c2e6 100644
--- a/deps/v8/src/parsing/scanner.cc
+++ b/deps/v8/src/parsing/scanner.cc
@@ -15,7 +15,7 @@
#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"
+#include "src/parsing/scanner-inl.h"
namespace v8 {
namespace internal {
@@ -60,6 +60,7 @@ class Scanner::ErrorState {
// Scanner::LiteralBuffer
Handle<String> Scanner::LiteralBuffer::Internalize(Isolate* isolate) const {
+ DCHECK(is_used_);
if (is_one_byte()) {
return isolate->factory()->InternalizeOneByteString(one_byte_literal());
}
@@ -103,16 +104,9 @@ void Scanner::LiteralBuffer::ConvertToTwoByte() {
is_one_byte_ = false;
}
-void Scanner::LiteralBuffer::AddCharSlow(uc32 code_unit) {
+void Scanner::LiteralBuffer::AddTwoByteChar(uc32 code_unit) {
+ DCHECK(!is_one_byte_);
if (position_ >= backing_store_.length()) ExpandBuffer();
- if (is_one_byte_) {
- if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
- backing_store_[position_] = static_cast<byte>(code_unit);
- position_ += kOneByteSize;
- return;
- }
- ConvertToTwoByte();
- }
if (code_unit <=
static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
*reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
@@ -140,16 +134,16 @@ const size_t Scanner::BookmarkScope::kBookmarkWasApplied =
void Scanner::BookmarkScope::Set() {
DCHECK_EQ(bookmark_, kNoBookmark);
- DCHECK_EQ(scanner_->next_next_.token, Token::UNINITIALIZED);
+ DCHECK_EQ(scanner_->next_next().token, Token::UNINITIALIZED);
// The first token is a bit special, since current_ will still be
// uninitialized. In this case, store kBookmarkAtFirstPos and special-case it
// when
// applying the bookmark.
- DCHECK_IMPLIES(
- scanner_->current_.token == Token::UNINITIALIZED,
- scanner_->current_.location.beg_pos == scanner_->next_.location.beg_pos);
- bookmark_ = (scanner_->current_.token == Token::UNINITIALIZED)
+ DCHECK_IMPLIES(scanner_->current().token == Token::UNINITIALIZED,
+ scanner_->current().location.beg_pos ==
+ scanner_->next().location.beg_pos);
+ bookmark_ = (scanner_->current().token == Token::UNINITIALIZED)
? kBookmarkAtFirstPos
: scanner_->location().beg_pos;
}
@@ -177,22 +171,24 @@ bool Scanner::BookmarkScope::HasBeenApplied() {
// ----------------------------------------------------------------------------
// Scanner
-Scanner::Scanner(UnicodeCache* unicode_cache)
+Scanner::Scanner(UnicodeCache* unicode_cache, Utf16CharacterStream* source,
+ bool is_module)
: unicode_cache_(unicode_cache),
+ source_(source),
octal_pos_(Location::invalid()),
octal_message_(MessageTemplate::kNone),
found_html_comment_(false),
allow_harmony_bigint_(false),
- allow_harmony_numeric_separator_(false) {}
-
-void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
+ allow_harmony_numeric_separator_(false),
+ is_module_(is_module) {
DCHECK_NOT_NULL(source);
- source_ = source;
- is_module_ = is_module;
+}
+
+void Scanner::Initialize() {
// Need to capture identifiers in order to recognize "get" and "set"
// in object literals.
Init();
- has_line_terminator_before_next_ = true;
+ next().after_line_terminator = true;
Scan();
}
@@ -377,96 +373,43 @@ static const byte one_char_tokens[] = {
// clang-format on
Token::Value Scanner::Next() {
- if (next_.token == Token::EOS) {
- next_.location.beg_pos = current_.location.beg_pos;
- next_.location.end_pos = current_.location.end_pos;
- }
+ if (next().token == Token::EOS) next().location = current().location;
+ // Rotate through tokens.
+ TokenDesc* previous = current_;
current_ = next_;
- if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
+ // Either we already have the next token lined up, in which case next_next_
+ // simply becomes next_. In that case we use current_ as new next_next_ and
+ // clear its token to indicate that it wasn't scanned yet. Otherwise we use
+ // current_ as next_ and scan into it, leaving next_next_ uninitialized.
+ if (V8_LIKELY(next_next().token == Token::UNINITIALIZED)) {
+ next_ = previous;
+ next().after_line_terminator = false;
+ Scan();
+ } else {
next_ = next_next_;
- next_next_.token = Token::UNINITIALIZED;
- next_next_.contextual_token = Token::UNINITIALIZED;
- has_line_terminator_before_next_ = has_line_terminator_after_next_;
- return current_.token;
+ next_next_ = previous;
+ previous->token = Token::UNINITIALIZED;
+ previous->contextual_token = Token::UNINITIALIZED;
+ DCHECK_NE(Token::UNINITIALIZED, current().token);
}
- has_line_terminator_before_next_ = false;
- has_multiline_comment_before_next_ = false;
- Scan();
- return current_.token;
+ return current().token;
}
Token::Value Scanner::PeekAhead() {
- DCHECK(next_.token != Token::DIV);
- DCHECK(next_.token != Token::ASSIGN_DIV);
-
- if (next_next_.token != Token::UNINITIALIZED) {
- return next_next_.token;
- }
- TokenDesc prev = current_;
- bool has_line_terminator_before_next =
- has_line_terminator_before_next_ || has_multiline_comment_before_next_;
- Next();
- has_line_terminator_after_next_ =
- has_line_terminator_before_next_ || has_multiline_comment_before_next_;
- has_line_terminator_before_next_ = has_line_terminator_before_next;
- Token::Value ret = next_.token;
- next_next_ = next_;
- next_ = current_;
- current_ = prev;
- return ret;
-}
-
-
-Token::Value Scanner::SkipWhiteSpace() {
- int start_position = source_pos();
-
- while (true) {
- while (true) {
- // We won't skip behind the end of input.
- DCHECK(!unicode_cache_->IsWhiteSpace(kEndOfInput));
-
- // Advance as long as character is a WhiteSpace or LineTerminator.
- // Remember if the latter is the case.
- if (unibrow::IsLineTerminator(c0_)) {
- has_line_terminator_before_next_ = true;
- } else if (!unicode_cache_->IsWhiteSpace(c0_)) {
- break;
- }
- Advance();
- }
+ DCHECK(next().token != Token::DIV);
+ DCHECK(next().token != Token::ASSIGN_DIV);
- // If there is an HTML comment end '-->' at the beginning of a
- // line (with only whitespace in front of it), we treat the rest
- // of the line as a comment. This is in line with the way
- // SpiderMonkey handles it.
- if (c0_ != '-' || !has_line_terminator_before_next_) break;
-
- Advance();
- if (c0_ != '-') {
- PushBack('-'); // undo Advance()
- break;
- }
-
- Advance();
- if (c0_ != '>') {
- PushBack2('-', '-'); // undo 2x Advance();
- break;
- }
-
- // Treat the rest of the line as a comment.
- Token::Value token = SkipSingleHTMLComment();
- if (token == Token::ILLEGAL) {
- return token;
- }
+ if (next_next().token != Token::UNINITIALIZED) {
+ return next_next().token;
}
-
- // Return whether or not we skipped any characters.
- if (source_pos() == start_position) {
- return Token::ILLEGAL;
- }
-
- return Token::WHITESPACE;
+ TokenDesc* temp = next_;
+ next_ = next_next_;
+ next().after_line_terminator = false;
+ Scan();
+ next_next_ = next_;
+ next_ = temp;
+ return next_next().token;
}
Token::Value Scanner::SkipSingleHTMLComment() {
@@ -478,21 +421,16 @@ Token::Value Scanner::SkipSingleHTMLComment() {
}
Token::Value Scanner::SkipSingleLineComment() {
- Advance();
-
// The line terminator at the end of the line is not considered
// to be part of the single-line comment; it is recognized
// separately by the lexical grammar and becomes part of the
// stream of input elements for the syntactic grammar (see
// ECMA-262, section 7.4).
- while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
- Advance();
- }
+ AdvanceUntil([](uc32 c0_) { return unibrow::IsLineTerminator(c0_); });
return Token::WHITESPACE;
}
-
Token::Value Scanner::SkipSourceURLComment() {
TryToParseSourceURLComment();
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
@@ -502,7 +440,6 @@ Token::Value Scanner::SkipSourceURLComment() {
return Token::WHITESPACE;
}
-
void Scanner::TryToParseSourceURLComment() {
// Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
// function will just return if it cannot parse a magic comment.
@@ -510,6 +447,7 @@ void Scanner::TryToParseSourceURLComment() {
if (!unicode_cache_->IsWhiteSpace(c0_)) return;
Advance();
LiteralBuffer name;
+ name.Start();
while (c0_ != kEndOfInput &&
!unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) && c0_ != '=') {
@@ -528,15 +466,16 @@ void Scanner::TryToParseSourceURLComment() {
}
if (c0_ != '=')
return;
+ value->Drop();
+ value->Start();
Advance();
- value->Reset();
while (unicode_cache_->IsWhiteSpace(c0_)) {
Advance();
}
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
// Disallowed characters.
if (c0_ == '"' || c0_ == '\'') {
- value->Reset();
+ value->Drop();
return;
}
if (unicode_cache_->IsWhiteSpace(c0_)) {
@@ -548,34 +487,33 @@ void Scanner::TryToParseSourceURLComment() {
// Allow whitespace at the end.
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) {
if (!unicode_cache_->IsWhiteSpace(c0_)) {
- value->Reset();
+ value->Drop();
break;
}
Advance();
}
}
-
Token::Value Scanner::SkipMultiLineComment() {
DCHECK_EQ(c0_, '*');
Advance();
while (c0_ != kEndOfInput) {
- uc32 ch = c0_;
- Advance();
DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
- if (unibrow::IsLineTerminator(ch)) {
+ if (!HasLineTerminatorBeforeNext() && unibrow::IsLineTerminator(c0_)) {
// Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator.
- has_multiline_comment_before_next_ = true;
+ next().after_line_terminator = true;
}
- // If we have reached the end of the multi-line comment, we
- // consume the '/' and insert a whitespace. This way all
- // multi-line comments are treated as whitespace.
- if (ch == '*' && c0_ == '/') {
- c0_ = ' ';
- return Token::WHITESPACE;
+
+ while (V8_UNLIKELY(c0_ == '*')) {
+ Advance();
+ if (c0_ == '/') {
+ Advance();
+ return Token::WHITESPACE;
+ }
}
+ Advance();
}
// Unterminated multi-line comment.
@@ -586,25 +524,20 @@ Token::Value Scanner::ScanHtmlComment() {
// Check for <!-- comments.
DCHECK_EQ(c0_, '!');
Advance();
- if (c0_ != '-') {
+ if (c0_ != '-' || Peek() != '-') {
PushBack('!'); // undo Advance()
return Token::LT;
}
-
Advance();
- if (c0_ != '-') {
- PushBack2('-', '!'); // undo 2x Advance()
- return Token::LT;
- }
found_html_comment_ = true;
return SkipSingleHTMLComment();
}
void Scanner::Scan() {
- next_.literal_chars = nullptr;
- next_.raw_literal_chars = nullptr;
- next_.invalid_template_escape_message = MessageTemplate::kNone;
+ next().literal_chars.Drop();
+ next().raw_literal_chars.Drop();
+ next().invalid_template_escape_message = MessageTemplate::kNone;
Token::Value token;
do {
@@ -612,17 +545,17 @@ void Scanner::Scan() {
Token::Value token = static_cast<Token::Value>(one_char_tokens[c0_]);
if (token != Token::ILLEGAL) {
int pos = source_pos();
- next_.token = token;
- next_.contextual_token = Token::UNINITIALIZED;
- next_.location.beg_pos = pos;
- next_.location.end_pos = pos + 1;
+ next().token = token;
+ next().contextual_token = Token::UNINITIALIZED;
+ next().location.beg_pos = pos;
+ next().location.end_pos = pos + 1;
Advance();
return;
}
}
// Remember the position of the next token
- next_.location.beg_pos = source_pos();
+ next().location.beg_pos = source_pos();
switch (c0_) {
case '"':
@@ -703,7 +636,7 @@ void Scanner::Scan() {
Advance();
if (c0_ == '-') {
Advance();
- if (c0_ == '>' && HasAnyLineTerminatorBeforeNext()) {
+ if (c0_ == '>' && HasLineTerminatorBeforeNext()) {
// For compatibility with SpiderMonkey, we skip lines that
// start with an HTML comment end '-->'.
token = SkipSingleHTMLComment();
@@ -738,12 +671,12 @@ void Scanner::Scan() {
// / // /* /=
Advance();
if (c0_ == '/') {
- Advance();
- if (c0_ == '#' || c0_ == '@') {
+ uc32 c = Peek();
+ if (c == '#' || c == '@') {
+ Advance();
Advance();
token = SkipSourceURLComment();
} else {
- PushBack(c0_);
token = SkipSingleLineComment();
}
} else if (c0_ == '*') {
@@ -792,12 +725,10 @@ void Scanner::Scan() {
} else {
token = Token::PERIOD;
if (c0_ == '.') {
- Advance();
- if (c0_ == '.') {
+ if (Peek() == '.') {
+ Advance();
Advance();
token = Token::ELLIPSIS;
- } else {
- PushBack('.');
}
}
}
@@ -831,19 +762,19 @@ void Scanner::Scan() {
// whitespace.
} while (token == Token::WHITESPACE);
- next_.location.end_pos = source_pos();
+ next().location.end_pos = source_pos();
if (Token::IsContextualKeyword(token)) {
- next_.token = Token::IDENTIFIER;
- next_.contextual_token = token;
+ next().token = Token::IDENTIFIER;
+ next().contextual_token = token;
} else {
- next_.token = token;
- next_.contextual_token = Token::UNINITIALIZED;
+ next().token = token;
+ next().contextual_token = Token::UNINITIALIZED;
}
#ifdef DEBUG
- SanityCheckTokenDesc(current_);
- SanityCheckTokenDesc(next_);
- SanityCheckTokenDesc(next_next_);
+ SanityCheckTokenDesc(current());
+ SanityCheckTokenDesc(next());
+ SanityCheckTokenDesc(next_next());
#endif
}
@@ -864,8 +795,8 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
break;
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL:
- DCHECK_NOT_NULL(token.raw_literal_chars);
- DCHECK_NOT_NULL(token.literal_chars);
+ DCHECK(token.raw_literal_chars.is_used());
+ DCHECK(token.literal_chars.is_used());
break;
case Token::ESCAPED_KEYWORD:
case Token::ESCAPED_STRICT_RESERVED_WORD:
@@ -877,13 +808,13 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
case Token::SMI:
case Token::STRING:
case Token::PRIVATE_NAME:
- DCHECK_NOT_NULL(token.literal_chars);
- DCHECK_NULL(token.raw_literal_chars);
+ DCHECK(token.literal_chars.is_used());
+ DCHECK(!token.raw_literal_chars.is_used());
DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
break;
default:
- DCHECK_NULL(token.literal_chars);
- DCHECK_NULL(token.raw_literal_chars);
+ DCHECK(!token.literal_chars.is_used());
+ DCHECK(!token.raw_literal_chars.is_used());
DCHECK_EQ(token.invalid_template_escape_message, MessageTemplate::kNone);
break;
}
@@ -900,9 +831,9 @@ void Scanner::SanityCheckTokenDesc(const TokenDesc& token) const {
void Scanner::SeekForward(int pos) {
// After this call, we will have the token at the given position as
// the "next" token. The "current" token will be invalid.
- if (pos == next_.location.beg_pos) return;
+ if (pos == next().location.beg_pos) return;
int current_pos = source_pos();
- DCHECK_EQ(next_.location.end_pos, current_pos);
+ DCHECK_EQ(next().location.end_pos, current_pos);
// Positions inside the lookahead token aren't supported.
DCHECK(pos >= current_pos);
if (pos != current_pos) {
@@ -911,23 +842,21 @@ void Scanner::SeekForward(int pos) {
// This function is only called to seek to the location
// of the end of a function (at the "}" token). It doesn't matter
// whether there was a line terminator in the part we skip.
- has_line_terminator_before_next_ = false;
- has_multiline_comment_before_next_ = false;
+ next().after_line_terminator = false;
}
Scan();
}
-
-template <bool capture_raw, bool in_template_literal>
+template <bool capture_raw>
bool Scanner::ScanEscape() {
uc32 c = c0_;
Advance<capture_raw>();
// Skip escaped newlines.
DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
- if (!in_template_literal && unibrow::IsLineTerminator(c)) {
+ if (!capture_raw && unibrow::IsLineTerminator(c)) {
// Allow escaped CR+LF newlines in multiline string literals.
- if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
+ if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
return true;
}
@@ -961,7 +890,7 @@ bool Scanner::ScanEscape() {
case '5': // fall through
case '6': // fall through
case '7':
- c = ScanOctalEscape<capture_raw>(c, 2, in_template_literal);
+ c = ScanOctalEscape<capture_raw>(c, 2);
break;
}
@@ -971,7 +900,7 @@ bool Scanner::ScanEscape() {
}
template <bool capture_raw>
-uc32 Scanner::ScanOctalEscape(uc32 c, int length, bool in_template_literal) {
+uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
uc32 x = c - '0';
int i = 0;
for (; i < length; i++) {
@@ -989,14 +918,12 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length, bool in_template_literal) {
// occur before the "use strict" directive.
if (c != '0' || i > 0 || c0_ == '8' || c0_ == '9') {
octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
- octal_message_ = in_template_literal
- ? MessageTemplate::kTemplateOctalLiteral
- : MessageTemplate::kStrictOctalEscape;
+ octal_message_ = capture_raw ? MessageTemplate::kTemplateOctalLiteral
+ : MessageTemplate::kStrictOctalEscape;
}
return x;
}
-
Token::Value Scanner::ScanString() {
uc32 quote = c0_;
Advance(); // consume quote
@@ -1014,7 +941,7 @@ Token::Value Scanner::ScanString() {
if (c0_ == '\\') {
Advance();
// TODO(verwaest): Check whether we can remove the additional check.
- if (c0_ == kEndOfInput || !ScanEscape<false, false>()) {
+ if (c0_ == kEndOfInput || !ScanEscape<false>()) {
return Token::ILLEGAL;
}
continue;
@@ -1032,15 +959,14 @@ Token::Value Scanner::ScanPrivateName() {
LiteralScope literal(this);
DCHECK_EQ(c0_, '#');
- AddLiteralCharAdvance();
DCHECK(!unicode_cache_->IsIdentifierStart(kEndOfInput));
- if (!unicode_cache_->IsIdentifierStart(c0_)) {
- PushBack(c0_);
+ if (!unicode_cache_->IsIdentifierStart(Peek())) {
ReportScannerError(source_pos(),
MessageTemplate::kInvalidOrUnexpectedToken);
return Token::ILLEGAL;
}
+ AddLiteralCharAdvance();
Token::Value token = ScanIdentifierOrKeywordInner(&literal);
return token == Token::ILLEGAL ? Token::ILLEGAL : Token::PRIVATE_NAME;
}
@@ -1069,89 +995,87 @@ Token::Value Scanner::ScanTemplateSpan() {
LiteralScope literal(this);
StartRawLiteral();
const bool capture_raw = true;
- const bool in_template_literal = true;
while (true) {
uc32 c = c0_;
- Advance<capture_raw>();
if (c == '`') {
+ Advance(); // Consume '`'
result = Token::TEMPLATE_TAIL;
- ReduceRawLiteralLength(1);
break;
- } else if (c == '$' && c0_ == '{') {
- Advance<capture_raw>(); // Consume '{'
- ReduceRawLiteralLength(2);
+ } else if (c == '$' && Peek() == '{') {
+ Advance(); // Consume '$'
+ Advance(); // Consume '{'
break;
} else if (c == '\\') {
+ Advance(); // Consume '\\'
DCHECK(!unibrow::IsLineTerminator(kEndOfInput));
+ if (capture_raw) AddRawLiteralChar('\\');
if (unibrow::IsLineTerminator(c0_)) {
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty
// code unit sequence.
uc32 lastChar = c0_;
- Advance<capture_raw>();
+ Advance();
if (lastChar == '\r') {
- ReduceRawLiteralLength(1); // Remove \r
- if (c0_ == '\n') {
- Advance<capture_raw>(); // Adds \n
- } else {
- AddRawLiteralChar('\n');
- }
+ // Also skip \n.
+ if (c0_ == '\n') Advance();
+ lastChar = '\n';
}
+ if (capture_raw) AddRawLiteralChar(lastChar);
} else {
- bool success = ScanEscape<capture_raw, in_template_literal>();
+ bool success = ScanEscape<capture_raw>();
USE(success);
DCHECK_EQ(!success, has_error());
// For templates, invalid escape sequence checking is handled in the
// parser.
- scanner_error_state.MoveErrorTo(&next_);
- octal_error_state.MoveErrorTo(&next_);
+ scanner_error_state.MoveErrorTo(next_);
+ octal_error_state.MoveErrorTo(next_);
}
} else if (c < 0) {
// Unterminated template literal
- PushBack(c);
break;
} else {
+ Advance(); // Consume c.
// The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
// The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
// consisting of the CV 0x000A.
if (c == '\r') {
- ReduceRawLiteralLength(1); // Remove \r
- if (c0_ == '\n') {
- Advance<capture_raw>(); // Adds \n
- } else {
- AddRawLiteralChar('\n');
- }
+ if (c0_ == '\n') Advance(); // Consume '\n'
c = '\n';
}
+ if (capture_raw) AddRawLiteralChar(c);
AddLiteralChar(c);
}
}
literal.Complete();
- next_.location.end_pos = source_pos();
- next_.token = result;
- next_.contextual_token = Token::UNINITIALIZED;
+ next().location.end_pos = source_pos();
+ next().token = result;
+ next().contextual_token = Token::UNINITIALIZED;
return result;
}
-
Token::Value Scanner::ScanTemplateStart() {
- DCHECK_EQ(next_next_.token, Token::UNINITIALIZED);
+ DCHECK_EQ(next_next().token, Token::UNINITIALIZED);
DCHECK_EQ(c0_, '`');
- next_.location.beg_pos = source_pos();
+ next().location.beg_pos = source_pos();
Advance(); // Consume `
return ScanTemplateSpan();
}
Handle<String> Scanner::SourceUrl(Isolate* isolate) const {
Handle<String> tmp;
- if (source_url_.length() > 0) tmp = source_url_.Internalize(isolate);
+ if (source_url_.length() > 0) {
+ DCHECK(source_url_.is_used());
+ tmp = source_url_.Internalize(isolate);
+ }
return tmp;
}
Handle<String> Scanner::SourceMappingUrl(Isolate* isolate) const {
Handle<String> tmp;
- if (source_mapping_url_.length() > 0)
+ if (source_mapping_url_.length() > 0) {
+ DCHECK(source_mapping_url_.is_used());
tmp = source_mapping_url_.Internalize(isolate);
+ }
return tmp;
}
@@ -1375,10 +1299,10 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
return Token::ILLEGAL;
}
- if (next_.literal_chars->one_byte_literal().length() <= 10 &&
+ if (next().literal_chars.one_byte_literal().length() <= 10 &&
value <= Smi::kMaxValue && c0_ != '.' &&
!unicode_cache_->IsIdentifierStart(c0_)) {
- next_.smi_value_ = static_cast<uint32_t>(value);
+ next().smi_value_ = static_cast<uint32_t>(value);
literal.Complete();
if (kind == DECIMAL_WITH_LEADING_ZERO) {
@@ -1448,7 +1372,6 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
return is_bigint ? Token::BIGINT : Token::NUMBER;
}
-
uc32 Scanner::ScanIdentifierUnicodeEscape() {
Advance();
if (c0_ != 'u') return -1;
@@ -1456,7 +1379,6 @@ uc32 Scanner::ScanIdentifierUnicodeEscape() {
return ScanUnicodeEscape<false>();
}
-
template <bool capture_raw>
uc32 Scanner::ScanUnicodeEscape() {
// Accept both \uxxxx and \u{xxxxxx}. In the latter case, the number of
@@ -1622,13 +1544,15 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
bool escaped = false;
if (IsInRange(c0_, 'a', 'z') || c0_ == '_') {
do {
- AddLiteralCharAdvance();
+ AddLiteralChar(static_cast<char>(c0_));
+ Advance();
} while (IsInRange(c0_, 'a', 'z') || c0_ == '_');
if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '$') {
// Identifier starting with lowercase or _.
do {
- AddLiteralCharAdvance();
+ AddLiteralChar(static_cast<char>(c0_));
+ Advance();
} while (IsAsciiIdentifier(c0_));
if (c0_ <= kMaxAscii && c0_ != '\\') {
@@ -1637,7 +1561,7 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
}
} else if (c0_ <= kMaxAscii && c0_ != '\\') {
// Only a-z+ or _: could be a keyword or identifier.
- Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
+ Vector<const uint8_t> chars = next().literal_chars.one_byte_literal();
Token::Value token =
KeywordOrIdentifierToken(chars.start(), chars.length());
if (token == Token::IDENTIFIER ||
@@ -1648,7 +1572,8 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
}
} else if (IsInRange(c0_, 'A', 'Z') || c0_ == '$') {
do {
- AddLiteralCharAdvance();
+ AddLiteralChar(static_cast<char>(c0_));
+ Advance();
} while (IsAsciiIdentifier(c0_));
if (c0_ <= kMaxAscii && c0_ != '\\') {
@@ -1686,8 +1611,8 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
}
}
- if (next_.literal_chars->is_one_byte()) {
- Vector<const uint8_t> chars = next_.literal_chars->one_byte_literal();
+ if (next().literal_chars.is_one_byte()) {
+ Vector<const uint8_t> chars = next().literal_chars.one_byte_literal();
Token::Value token =
KeywordOrIdentifierToken(chars.start(), chars.length());
/* TODO(adamk): YIELD should be handled specially. */
@@ -1715,17 +1640,17 @@ Token::Value Scanner::ScanIdentifierOrKeywordInner(LiteralScope* literal) {
}
bool Scanner::ScanRegExpPattern() {
- DCHECK(next_next_.token == Token::UNINITIALIZED);
- DCHECK(next_.token == Token::DIV || next_.token == Token::ASSIGN_DIV);
+ DCHECK_EQ(Token::UNINITIALIZED, next_next().token);
+ DCHECK(next().token == Token::DIV || next().token == Token::ASSIGN_DIV);
// Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
bool in_character_class = false;
- bool seen_equal = (next_.token == Token::ASSIGN_DIV);
+ bool seen_equal = (next().token == Token::ASSIGN_DIV);
// Previous token is either '/' or '/=', in the second case, the
// pattern starts at =.
- next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
- next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
+ next().location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
+ next().location.end_pos = source_pos() - (seen_equal ? 1 : 0);
// Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
// the scanner should pass uninterpreted bodies to the RegExp
@@ -1764,14 +1689,14 @@ bool Scanner::ScanRegExpPattern() {
Advance(); // consume '/'
literal.Complete();
- next_.token = Token::REGEXP_LITERAL;
- next_.contextual_token = Token::UNINITIALIZED;
+ next().token = Token::REGEXP_LITERAL;
+ next().contextual_token = Token::UNINITIALIZED;
return true;
}
Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
- DCHECK(next_.token == Token::REGEXP_LITERAL);
+ DCHECK_EQ(Token::REGEXP_LITERAL, next().token);
// Scan regular expression flags.
int flags = 0;
@@ -1806,7 +1731,7 @@ Maybe<RegExp::Flags> Scanner::ScanRegExpFlags() {
flags |= flag;
}
- next_.location.end_pos = source_pos();
+ next().location.end_pos = source_pos();
return Just(RegExp::Flags(flags));
}
@@ -1869,24 +1794,17 @@ void Scanner::SeekNext(size_t position) {
// 1, Reset the current_, next_ and next_next_ tokens
// (next_ + next_next_ will be overwrittem by Next(),
// current_ will remain unchanged, so overwrite it fully.)
- current_ = {{0, 0},
- nullptr,
- nullptr,
- 0,
- Token::UNINITIALIZED,
- MessageTemplate::kNone,
- {0, 0},
- Token::UNINITIALIZED};
- next_.token = Token::UNINITIALIZED;
- next_.contextual_token = Token::UNINITIALIZED;
- next_next_.token = Token::UNINITIALIZED;
- next_next_.contextual_token = Token::UNINITIALIZED;
+ for (TokenDesc& token : token_storage_) {
+ token.token = Token::UNINITIALIZED;
+ token.contextual_token = Token::UNINITIALIZED;
+ }
// 2, reset the source to the desired position,
source_->Seek(position);
// 3, re-scan, by scanning the look-ahead char + 1 token (next_).
c0_ = source_->Advance();
- Next();
- DCHECK_EQ(next_.location.beg_pos, static_cast<int>(position));
+ next().after_line_terminator = false;
+ Scan();
+ DCHECK_EQ(next().location.beg_pos, static_cast<int>(position));
}
} // namespace internal
diff --git a/deps/v8/src/parsing/scanner.h b/deps/v8/src/parsing/scanner.h
index 34da5fafbf..e592debd8e 100644
--- a/deps/v8/src/parsing/scanner.h
+++ b/deps/v8/src/parsing/scanner.h
@@ -7,6 +7,8 @@
#ifndef V8_PARSING_SCANNER_H_
#define V8_PARSING_SCANNER_H_
+#include <algorithm>
+
#include "src/allocation.h"
#include "src/base/logging.h"
#include "src/char-predicates.h"
@@ -36,25 +38,51 @@ class Utf16CharacterStream {
public:
static const uc32 kEndOfInput = -1;
- virtual ~Utf16CharacterStream() { }
+ virtual ~Utf16CharacterStream() {}
- // Returns and advances past the next UTF-16 code unit in the input
- // stream. If there are no more code units it returns kEndOfInput.
- inline uc32 Advance() {
+ inline uc32 Peek() {
if (V8_LIKELY(buffer_cursor_ < buffer_end_)) {
- return static_cast<uc32>(*(buffer_cursor_++));
+ return static_cast<uc32>(*buffer_cursor_);
} else if (ReadBlockChecked()) {
- return static_cast<uc32>(*(buffer_cursor_++));
+ return static_cast<uc32>(*buffer_cursor_);
} else {
- // Note: currently the following increment is necessary to avoid a
- // parser problem! The scanner treats the final kEndOfInput as
- // a code unit with a position, and does math relative to that
- // position.
- buffer_cursor_++;
return kEndOfInput;
}
}
+ // Returns and advances past the next UTF-16 code unit in the input
+ // stream. If there are no more code units it returns kEndOfInput.
+ inline uc32 Advance() {
+ uc32 result = Peek();
+ buffer_cursor_++;
+ return result;
+ }
+
+ // Returns and advances past the next UTF-16 code unit in the input stream
+ // that meets the checks requirement. If there are no more code units it
+ // returns kEndOfInput.
+ template <typename FunctionType>
+ V8_INLINE uc32 AdvanceUntil(FunctionType check) {
+ while (true) {
+ auto next_cursor_pos =
+ std::find_if(buffer_cursor_, buffer_end_, [&check](uint16_t raw_c0_) {
+ uc32 c0_ = static_cast<uc32>(raw_c0_);
+ return check(c0_);
+ });
+
+ if (next_cursor_pos == buffer_end_) {
+ buffer_cursor_ = buffer_end_;
+ if (!ReadBlockChecked()) {
+ buffer_cursor_++;
+ return kEndOfInput;
+ }
+ } else {
+ buffer_cursor_ = next_cursor_pos + 1;
+ return static_cast<uc32>(*next_cursor_pos);
+ }
+ }
+ }
+
// Go back one by one character in the input stream.
// This undoes the most recent Advance().
inline void Back() {
@@ -68,17 +96,6 @@ class Utf16CharacterStream {
}
}
- // Go back one by two characters in the input stream. (This is the same as
- // calling Back() twice. But Back() may - in some instances - do substantial
- // work. Back2() guarantees this work will be done only once.)
- inline void Back2() {
- if (V8_LIKELY(buffer_cursor_ - 2 >= buffer_start_)) {
- buffer_cursor_ -= 2;
- } else {
- ReadBlockAt(pos() - 2);
- }
- }
-
inline size_t pos() const {
return buffer_pos_ + (buffer_cursor_ - buffer_start_);
}
@@ -157,7 +174,6 @@ class Utf16CharacterStream {
size_t buffer_pos_;
};
-
// ----------------------------------------------------------------------------
// JavaScript Scanner.
@@ -207,23 +223,24 @@ class Scanner {
static const int kNoOctalLocation = -1;
static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
- explicit Scanner(UnicodeCache* scanner_contants);
+ explicit Scanner(UnicodeCache* scanner_contants, Utf16CharacterStream* source,
+ bool is_module);
- void Initialize(Utf16CharacterStream* source, bool is_module);
+ void Initialize();
// Returns the next token and advances input.
Token::Value Next();
// Returns the token following peek()
Token::Value PeekAhead();
// Returns the current token again.
- Token::Value current_token() { return current_.token; }
+ Token::Value current_token() { return current().token; }
- Token::Value current_contextual_token() { return current_.contextual_token; }
- Token::Value next_contextual_token() { return next_.contextual_token; }
+ Token::Value current_contextual_token() { return current().contextual_token; }
+ Token::Value next_contextual_token() { return next().contextual_token; }
// Returns the location information for the current token
// (the token last returned by Next()).
- Location location() const { return current_.location; }
+ Location location() const { return current().location; }
// This error is specifically an invalid hex or unicode escape sequence.
bool has_error() const { return scanner_error_ != MessageTemplate::kNone; }
@@ -231,26 +248,26 @@ class Scanner {
Location error_location() const { return scanner_error_location_; }
bool has_invalid_template_escape() const {
- return current_.invalid_template_escape_message != MessageTemplate::kNone;
+ return current().invalid_template_escape_message != MessageTemplate::kNone;
}
MessageTemplate::Template invalid_template_escape_message() const {
DCHECK(has_invalid_template_escape());
- return current_.invalid_template_escape_message;
+ return current().invalid_template_escape_message;
}
Location invalid_template_escape_location() const {
DCHECK(has_invalid_template_escape());
- return current_.invalid_template_escape_location;
+ return current().invalid_template_escape_location;
}
// Similar functions for the upcoming token.
// One token look-ahead (past the token returned by Next()).
- Token::Value peek() const { return next_.token; }
+ Token::Value peek() const { return next().token; }
- Location peek_location() const { return next_.location; }
+ Location peek_location() const { return next().location; }
bool literal_contains_escapes() const {
- return LiteralContainsEscapes(current_);
+ return LiteralContainsEscapes(current());
}
const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory) const;
@@ -264,12 +281,12 @@ class Scanner {
inline bool CurrentMatches(Token::Value token) const {
DCHECK(Token::IsKeyword(token));
- return current_.token == token;
+ return current().token == token;
}
inline bool CurrentMatchesContextual(Token::Value token) const {
DCHECK(Token::IsContextualKeyword(token));
- return current_.contextual_token == token;
+ return current().contextual_token == token;
}
// Match the token against the contextual keyword or literal buffer.
@@ -278,17 +295,17 @@ class Scanner {
// Escaped keywords are not matched as tokens. So if we require escape
// and/or string processing we need to look at the literal content
// (which was escape-processed already).
- // Conveniently, current_.literal_chars == nullptr for all proper keywords,
- // so this second condition should exit early in common cases.
- return (current_.contextual_token == token) ||
- (current_.literal_chars &&
- current_.literal_chars->Equals(Vector<const char>(
+ // Conveniently, !current().literal_chars.is_used() for all proper
+ // keywords, so this second condition should exit early in common cases.
+ return (current().contextual_token == token) ||
+ (current().literal_chars.is_used() &&
+ current().literal_chars.Equals(Vector<const char>(
Token::String(token), Token::StringLength(token))));
}
bool IsUseStrict() const {
- return current_.token == Token::STRING &&
- current_.literal_chars->Equals(
+ return current().token == Token::STRING &&
+ current().literal_chars.Equals(
Vector<const char>("use strict", strlen("use strict")));
}
bool IsGetOrSet(bool* is_get, bool* is_set) const {
@@ -318,7 +335,7 @@ class Scanner {
MessageTemplate::Template octal_message() const { return octal_message_; }
// Returns the value of the last smi that was scanned.
- uint32_t smi_value() const { return current_.smi_value_; }
+ uint32_t smi_value() const { return current().smi_value_; }
// Seek forward to the given position. This operation does not
// work in general, for instance when there are pushed back
@@ -328,15 +345,14 @@ class Scanner {
// Returns true if there was a line terminator before the peek'ed token,
// possibly inside a multi-line comment.
- bool HasAnyLineTerminatorBeforeNext() const {
- return has_line_terminator_before_next_ ||
- has_multiline_comment_before_next_;
+ bool HasLineTerminatorBeforeNext() const {
+ return next().after_line_terminator;
}
- bool HasAnyLineTerminatorAfterNext() {
+ bool HasLineTerminatorAfterNext() {
Token::Value ensure_next_next = PeekAhead();
USE(ensure_next_next);
- return has_line_terminator_after_next_;
+ return next_next().after_line_terminator;
}
// Scans the input as a regular expression pattern, next token must be /(=).
@@ -348,8 +364,8 @@ class Scanner {
// Scans the input as a template literal
Token::Value ScanTemplateStart();
Token::Value ScanTemplateContinuation() {
- DCHECK_EQ(next_.token, Token::RBRACE);
- next_.location.beg_pos = source_pos() - 1; // We already consumed }
+ DCHECK_EQ(next().token, Token::RBRACE);
+ next().location.beg_pos = source_pos() - 1; // We already consumed }
return ScanTemplateSpan();
}
@@ -399,33 +415,40 @@ class Scanner {
// LiteralBuffer - Collector of chars of literals.
class LiteralBuffer {
public:
- LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() {}
+ LiteralBuffer()
+ : position_(0), is_one_byte_(true), is_used_(false), backing_store_() {}
~LiteralBuffer() { backing_store_.Dispose(); }
V8_INLINE void AddChar(char code_unit) {
+ DCHECK(is_used_);
DCHECK(IsValidAscii(code_unit));
AddOneByteChar(static_cast<byte>(code_unit));
}
V8_INLINE void AddChar(uc32 code_unit) {
- if (is_one_byte_ &&
- code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
- AddOneByteChar(static_cast<byte>(code_unit));
- } else {
- AddCharSlow(code_unit);
+ DCHECK(is_used_);
+ if (is_one_byte_) {
+ if (code_unit <= static_cast<uc32>(unibrow::Latin1::kMaxChar)) {
+ AddOneByteChar(static_cast<byte>(code_unit));
+ return;
+ }
+ ConvertToTwoByte();
}
+ AddTwoByteChar(code_unit);
}
bool is_one_byte() const { return is_one_byte_; }
bool Equals(Vector<const char> keyword) const {
+ DCHECK(is_used_);
return is_one_byte() && keyword.length() == position_ &&
(memcmp(keyword.start(), backing_store_.start(), position_) == 0);
}
Vector<const uint16_t> two_byte_literal() const {
DCHECK(!is_one_byte_);
+ DCHECK(is_used_);
DCHECK_EQ(position_ & 0x1, 0);
return Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(backing_store_.start()),
@@ -434,17 +457,23 @@ class Scanner {
Vector<const uint8_t> one_byte_literal() const {
DCHECK(is_one_byte_);
+ DCHECK(is_used_);
return Vector<const uint8_t>(
reinterpret_cast<const uint8_t*>(backing_store_.start()), position_);
}
int length() const { return is_one_byte_ ? position_ : (position_ >> 1); }
- void ReduceLength(int delta) {
- position_ -= delta * (is_one_byte_ ? kOneByteSize : kUC16Size);
+ void Start() {
+ DCHECK(!is_used_);
+ DCHECK_EQ(0, position_);
+ is_used_ = true;
}
- void Reset() {
+ bool is_used() const { return is_used_; }
+
+ void Drop() {
+ is_used_ = false;
position_ = 0;
is_one_byte_ = true;
}
@@ -472,13 +501,14 @@ class Scanner {
position_ += kOneByteSize;
}
- void AddCharSlow(uc32 code_unit);
+ void AddTwoByteChar(uc32 code_unit);
int NewCapacity(int min_capacity);
void ExpandBuffer();
void ConvertToTwoByte();
- bool is_one_byte_;
int position_;
+ bool is_one_byte_;
+ bool is_used_;
Vector<byte> backing_store_;
DISALLOW_COPY_AND_ASSIGN(LiteralBuffer);
@@ -486,14 +516,16 @@ class Scanner {
// The current and look-ahead token.
struct TokenDesc {
- Location location;
- LiteralBuffer* literal_chars;
- LiteralBuffer* raw_literal_chars;
- uint32_t smi_value_;
- Token::Value token;
- MessageTemplate::Template invalid_template_escape_message;
+ Location location = {0, 0};
+ LiteralBuffer literal_chars;
+ LiteralBuffer raw_literal_chars;
+ Token::Value token = Token::UNINITIALIZED;
+ MessageTemplate::Template invalid_template_escape_message =
+ MessageTemplate::kNone;
Location invalid_template_escape_location;
- Token::Value contextual_token;
+ Token::Value contextual_token = Token::UNINITIALIZED;
+ uint32_t smi_value_ = 0;
+ bool after_line_terminator = false;
};
enum NumberKind {
@@ -510,29 +542,18 @@ class Scanner {
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
template <bool capture_raw>
- uc32 ScanOctalEscape(uc32 c, int length, bool in_template_literal);
+ uc32 ScanOctalEscape(uc32 c, int length);
// Call this after setting source_ to the input.
void Init() {
// Set c0_ (one character ahead)
STATIC_ASSERT(kCharacterLookaheadBufferSize == 1);
Advance();
- // Initialize current_ to not refer to a literal.
- current_.token = Token::UNINITIALIZED;
- current_.contextual_token = Token::UNINITIALIZED;
- 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 = 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 = nullptr;
- next_next_.raw_literal_chars = nullptr;
- next_next_.invalid_template_escape_message = MessageTemplate::kNone;
+
+ current_ = &token_storage_[0];
+ next_ = &token_storage_[1];
+ next_next_ = &token_storage_[2];
+
found_html_comment_ = false;
scanner_error_ = MessageTemplate::kNone;
}
@@ -554,52 +575,23 @@ class Scanner {
void SeekNext(size_t position);
// Literal buffer support
- inline void StartLiteral() {
- LiteralBuffer* free_buffer =
- (current_.literal_chars == &literal_buffer0_)
- ? &literal_buffer1_
- : (current_.literal_chars == &literal_buffer1_) ? &literal_buffer2_
- : &literal_buffer0_;
- free_buffer->Reset();
- next_.literal_chars = free_buffer;
- }
+ inline void StartLiteral() { next().literal_chars.Start(); }
- inline void StartRawLiteral() {
- LiteralBuffer* free_buffer =
- (current_.raw_literal_chars == &raw_literal_buffer0_)
- ? &raw_literal_buffer1_
- : (current_.raw_literal_chars == &raw_literal_buffer1_)
- ? &raw_literal_buffer2_
- : &raw_literal_buffer0_;
- free_buffer->Reset();
- next_.raw_literal_chars = free_buffer;
- }
+ inline void StartRawLiteral() { next().raw_literal_chars.Start(); }
- V8_INLINE void AddLiteralChar(uc32 c) {
- DCHECK_NOT_NULL(next_.literal_chars);
- next_.literal_chars->AddChar(c);
- }
+ V8_INLINE void AddLiteralChar(uc32 c) { next().literal_chars.AddChar(c); }
- V8_INLINE void AddLiteralChar(char c) {
- DCHECK_NOT_NULL(next_.literal_chars);
- next_.literal_chars->AddChar(c);
- }
+ V8_INLINE void AddLiteralChar(char c) { next().literal_chars.AddChar(c); }
V8_INLINE void AddRawLiteralChar(uc32 c) {
- DCHECK_NOT_NULL(next_.raw_literal_chars);
- next_.raw_literal_chars->AddChar(c);
- }
-
- V8_INLINE void ReduceRawLiteralLength(int delta) {
- DCHECK_NOT_NULL(next_.raw_literal_chars);
- next_.raw_literal_chars->ReduceLength(delta);
+ next().raw_literal_chars.AddChar(c);
}
// Stops scanning of a literal and drop the collected characters,
// e.g., due to an encountered error.
inline void DropLiteral() {
- next_.literal_chars = nullptr;
- next_.raw_literal_chars = nullptr;
+ next().literal_chars.Drop();
+ next().raw_literal_chars.Drop();
}
inline void AddLiteralCharAdvance() {
@@ -616,6 +608,11 @@ class Scanner {
c0_ = source_->Advance();
}
+ template <typename FunctionType>
+ V8_INLINE void AdvanceUntil(FunctionType check) {
+ c0_ = source_->AdvanceUntil(check);
+ }
+
bool CombineSurrogatePair() {
DCHECK(!unibrow::Utf16::IsLeadSurrogate(kEndOfInput));
if (unibrow::Utf16::IsLeadSurrogate(c0_)) {
@@ -631,22 +628,12 @@ class Scanner {
}
void PushBack(uc32 ch) {
- if (c0_ > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
- source_->Back2();
- } else {
- source_->Back();
- }
+ DCHECK_LE(c0_, static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode));
+ source_->Back();
c0_ = ch;
}
- // Same as PushBack(ch1); PushBack(ch2).
- // - Potentially more efficient as it uses Back2() on the stream.
- // - Uses char as parameters, since we're only calling it with ASCII chars in
- // practice. This way, we can avoid a few edge cases.
- void PushBack2(char ch1, char ch2) {
- source_->Back2();
- c0_ = ch2;
- }
+ uc32 Peek() const { return source_->Peek(); }
inline Token::Value Select(Token::Value tok) {
Advance();
@@ -676,45 +663,46 @@ class Scanner {
// token as a one-byte literal. E.g. Token::FUNCTION pretends to have a
// literal "function".
Vector<const uint8_t> literal_one_byte_string() const {
- if (current_.literal_chars)
- return current_.literal_chars->one_byte_literal();
- const char* str = Token::String(current_.token);
+ if (current().literal_chars.is_used())
+ return current().literal_chars.one_byte_literal();
+ const char* str = Token::String(current().token);
const uint8_t* str_as_uint8 = reinterpret_cast<const uint8_t*>(str);
return Vector<const uint8_t>(str_as_uint8,
- Token::StringLength(current_.token));
+ Token::StringLength(current().token));
}
Vector<const uint16_t> literal_two_byte_string() const {
- DCHECK_NOT_NULL(current_.literal_chars);
- return current_.literal_chars->two_byte_literal();
+ DCHECK(current().literal_chars.is_used());
+ return current().literal_chars.two_byte_literal();
}
bool is_literal_one_byte() const {
- return !current_.literal_chars || current_.literal_chars->is_one_byte();
+ return !current().literal_chars.is_used() ||
+ current().literal_chars.is_one_byte();
}
// 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 {
- DCHECK_NOT_NULL(next_.literal_chars);
- return next_.literal_chars->one_byte_literal();
+ DCHECK(next().literal_chars.is_used());
+ return next().literal_chars.one_byte_literal();
}
Vector<const uint16_t> next_literal_two_byte_string() const {
- DCHECK_NOT_NULL(next_.literal_chars);
- return next_.literal_chars->two_byte_literal();
+ DCHECK(next().literal_chars.is_used());
+ return next().literal_chars.two_byte_literal();
}
bool is_next_literal_one_byte() const {
- DCHECK_NOT_NULL(next_.literal_chars);
- return next_.literal_chars->is_one_byte();
+ DCHECK(next().literal_chars.is_used());
+ return next().literal_chars.is_one_byte();
}
Vector<const uint8_t> raw_literal_one_byte_string() const {
- DCHECK_NOT_NULL(current_.raw_literal_chars);
- return current_.raw_literal_chars->one_byte_literal();
+ DCHECK(current().raw_literal_chars.is_used());
+ return current().raw_literal_chars.one_byte_literal();
}
Vector<const uint16_t> raw_literal_two_byte_string() const {
- DCHECK_NOT_NULL(current_.raw_literal_chars);
- return current_.raw_literal_chars->two_byte_literal();
+ DCHECK(current().raw_literal_chars.is_used());
+ return current().raw_literal_chars.two_byte_literal();
}
bool is_raw_literal_one_byte() const {
- DCHECK_NOT_NULL(current_.raw_literal_chars);
- return current_.raw_literal_chars->is_one_byte();
+ DCHECK(current().raw_literal_chars.is_used());
+ return current().raw_literal_chars.is_one_byte();
}
template <bool capture_raw, bool unicode = false>
@@ -728,7 +716,7 @@ class Scanner {
// Scans a single JavaScript token.
void Scan();
- Token::Value SkipWhiteSpace();
+ V8_INLINE Token::Value SkipWhiteSpace();
Token::Value SkipSingleHTMLComment();
Token::Value SkipSingleLineComment();
Token::Value SkipSourceURLComment();
@@ -759,7 +747,7 @@ class Scanner {
// Scans an escape-sequence which is part of a string and adds the
// decoded character to the current literal. Returns true if a pattern
// is scanned.
- template <bool capture_raw, bool in_template_literal>
+ template <bool capture_raw>
bool ScanEscape();
// Decodes a Unicode escape-sequence which is part of an identifier.
@@ -769,8 +757,6 @@ class Scanner {
template <bool capture_raw>
uc32 ScanUnicodeEscape();
- bool is_module_;
-
Token::Value ScanTemplateSpan();
// Return the current source position.
@@ -785,8 +771,8 @@ class Scanner {
// Subtract delimiters.
source_length -= 2;
}
- return token.literal_chars &&
- (token.literal_chars->length() != source_length);
+ return token.literal_chars.is_used() &&
+ (token.literal_chars.length() != source_length);
}
#ifdef DEBUG
@@ -795,26 +781,24 @@ class Scanner {
UnicodeCache* unicode_cache_;
- // Buffers collecting literal strings, numbers, etc.
- LiteralBuffer literal_buffer0_;
- LiteralBuffer literal_buffer1_;
- LiteralBuffer literal_buffer2_;
-
// Values parsed from magic comments.
LiteralBuffer source_url_;
LiteralBuffer source_mapping_url_;
- // Buffer to store raw string values
- LiteralBuffer raw_literal_buffer0_;
- LiteralBuffer raw_literal_buffer1_;
- LiteralBuffer raw_literal_buffer2_;
+ TokenDesc token_storage_[3];
+
+ TokenDesc& next() { return *next_; }
+
+ const TokenDesc& current() const { return *current_; }
+ const TokenDesc& next() const { return *next_; }
+ const TokenDesc& next_next() const { return *next_next_; }
- TokenDesc current_; // desc for current token (as returned by Next())
- TokenDesc next_; // desc for next token (one token look-ahead)
- TokenDesc next_next_; // desc for the token after next (after PeakAhead())
+ TokenDesc* current_; // desc for current token (as returned by Next())
+ TokenDesc* next_; // desc for next token (one token look-ahead)
+ TokenDesc* next_next_; // desc for the token after next (after PeakAhead())
// Input stream. Must be initialized to an Utf16CharacterStream.
- Utf16CharacterStream* source_;
+ Utf16CharacterStream* const source_;
// Last-seen positions of potentially problematic tokens.
Location octal_pos_;
@@ -823,15 +807,6 @@ class Scanner {
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
uc32 c0_;
- // Whether there is a line terminator whitespace character after
- // the current token, and before the next. Does not count newlines
- // inside multiline comments.
- bool has_line_terminator_before_next_;
- // Whether there is a multi-line comment that contains a
- // line-terminator after the current token, and before the next.
- bool has_multiline_comment_before_next_;
- bool has_line_terminator_after_next_;
-
// Whether this scanner encountered an HTML comment.
bool found_html_comment_;
@@ -840,6 +815,8 @@ class Scanner {
bool allow_harmony_private_fields_;
bool allow_harmony_numeric_separator_;
+ const bool is_module_;
+
MessageTemplate::Template scanner_error_;
Location scanner_error_location_;
};