summaryrefslogtreecommitdiff
path: root/deps/v8/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ast')
-rw-r--r--deps/v8/src/ast/ast-function-literal-id-reindexer.cc2
-rw-r--r--deps/v8/src/ast/ast-source-ranges.h25
-rw-r--r--deps/v8/src/ast/ast-value-factory.cc11
-rw-r--r--deps/v8/src/ast/ast-value-factory.h96
-rw-r--r--deps/v8/src/ast/ast.cc6
-rw-r--r--deps/v8/src/ast/ast.h36
-rw-r--r--deps/v8/src/ast/prettyprinter.cc4
-rw-r--r--deps/v8/src/ast/scopes-inl.h66
-rw-r--r--deps/v8/src/ast/scopes.cc231
-rw-r--r--deps/v8/src/ast/scopes.h73
-rw-r--r--deps/v8/src/ast/variables.h3
11 files changed, 325 insertions, 228 deletions
diff --git a/deps/v8/src/ast/ast-function-literal-id-reindexer.cc b/deps/v8/src/ast/ast-function-literal-id-reindexer.cc
index 5cb1e87d23..7e3a25890b 100644
--- a/deps/v8/src/ast/ast-function-literal-id-reindexer.cc
+++ b/deps/v8/src/ast/ast-function-literal-id-reindexer.cc
@@ -14,7 +14,7 @@ AstFunctionLiteralIdReindexer::AstFunctionLiteralIdReindexer(size_t stack_limit,
int delta)
: AstTraversalVisitor(stack_limit), delta_(delta) {}
-AstFunctionLiteralIdReindexer::~AstFunctionLiteralIdReindexer() {}
+AstFunctionLiteralIdReindexer::~AstFunctionLiteralIdReindexer() = default;
void AstFunctionLiteralIdReindexer::Reindex(Expression* pattern) {
Visit(pattern);
diff --git a/deps/v8/src/ast/ast-source-ranges.h b/deps/v8/src/ast/ast-source-ranges.h
index cf7bab53da..60222a4035 100644
--- a/deps/v8/src/ast/ast-source-ranges.h
+++ b/deps/v8/src/ast/ast-source-ranges.h
@@ -21,8 +21,9 @@ struct SourceRange {
static SourceRange OpenEnded(int32_t start) {
return SourceRange(start, kNoSourcePosition);
}
- static SourceRange ContinuationOf(const SourceRange& that) {
- return that.IsEmpty() ? Empty() : OpenEnded(that.end);
+ static SourceRange ContinuationOf(const SourceRange& that,
+ int end = kNoSourcePosition) {
+ return that.IsEmpty() ? Empty() : SourceRange(that.end, end);
}
int32_t start, end;
};
@@ -56,7 +57,7 @@ enum class SourceRangeKind {
class AstNodeSourceRanges : public ZoneObject {
public:
- virtual ~AstNodeSourceRanges() {}
+ virtual ~AstNodeSourceRanges() = default;
virtual SourceRange GetRange(SourceRangeKind kind) = 0;
};
@@ -65,7 +66,7 @@ class BinaryOperationSourceRanges final : public AstNodeSourceRanges {
explicit BinaryOperationSourceRanges(const SourceRange& right_range)
: right_range_(right_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
DCHECK_EQ(kind, SourceRangeKind::kRight);
return right_range_;
}
@@ -79,7 +80,7 @@ class ContinuationSourceRanges : public AstNodeSourceRanges {
explicit ContinuationSourceRanges(int32_t continuation_position)
: continuation_position_(continuation_position) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
DCHECK_EQ(kind, SourceRangeKind::kContinuation);
return SourceRange::OpenEnded(continuation_position_);
}
@@ -99,7 +100,7 @@ class CaseClauseSourceRanges final : public AstNodeSourceRanges {
explicit CaseClauseSourceRanges(const SourceRange& body_range)
: body_range_(body_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
DCHECK_EQ(kind, SourceRangeKind::kBody);
return body_range_;
}
@@ -114,7 +115,7 @@ class ConditionalSourceRanges final : public AstNodeSourceRanges {
const SourceRange& else_range)
: then_range_(then_range), else_range_(else_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
switch (kind) {
case SourceRangeKind::kThen:
return then_range_;
@@ -136,7 +137,7 @@ class IfStatementSourceRanges final : public AstNodeSourceRanges {
const SourceRange& else_range)
: then_range_(then_range), else_range_(else_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
switch (kind) {
case SourceRangeKind::kElse:
return else_range_;
@@ -162,7 +163,7 @@ class IterationStatementSourceRanges final : public AstNodeSourceRanges {
explicit IterationStatementSourceRanges(const SourceRange& body_range)
: body_range_(body_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
switch (kind) {
case SourceRangeKind::kBody:
return body_range_;
@@ -198,7 +199,7 @@ class NaryOperationSourceRanges final : public AstNodeSourceRanges {
void AddRange(const SourceRange& range) { ranges_.push_back(range); }
size_t RangeCount() const { return ranges_.size(); }
- SourceRange GetRange(SourceRangeKind kind) { UNREACHABLE(); }
+ SourceRange GetRange(SourceRangeKind kind) override { UNREACHABLE(); }
private:
ZoneVector<SourceRange> ranges_;
@@ -227,7 +228,7 @@ class TryCatchStatementSourceRanges final : public AstNodeSourceRanges {
explicit TryCatchStatementSourceRanges(const SourceRange& catch_range)
: catch_range_(catch_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
switch (kind) {
case SourceRangeKind::kCatch:
return catch_range_;
@@ -247,7 +248,7 @@ class TryFinallyStatementSourceRanges final : public AstNodeSourceRanges {
explicit TryFinallyStatementSourceRanges(const SourceRange& finally_range)
: finally_range_(finally_range) {}
- SourceRange GetRange(SourceRangeKind kind) {
+ SourceRange GetRange(SourceRangeKind kind) override {
switch (kind) {
case SourceRangeKind::kFinally:
return finally_range_;
diff --git a/deps/v8/src/ast/ast-value-factory.cc b/deps/v8/src/ast/ast-value-factory.cc
index 8cf81b24a5..67ea77bfbf 100644
--- a/deps/v8/src/ast/ast-value-factory.cc
+++ b/deps/v8/src/ast/ast-value-factory.cc
@@ -242,6 +242,17 @@ const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
return result;
}
+const AstRawString* AstValueFactory::CloneFromOtherFactory(
+ const AstRawString* raw_string) {
+ const AstRawString* result = GetString(
+ raw_string->hash_field(), raw_string->is_one_byte(),
+ Vector<const byte>(raw_string->raw_data(), raw_string->byte_length()));
+ // Check we weren't trying to clone a string that was already in this
+ // ast-value-factory.
+ DCHECK_NE(result, raw_string);
+ return result;
+}
+
AstConsString* AstValueFactory::NewConsString() {
AstConsString* new_string = new (zone_) AstConsString;
DCHECK_NOT_NULL(new_string);
diff --git a/deps/v8/src/ast/ast-value-factory.h b/deps/v8/src/ast/ast-value-factory.h
index e85b0675bf..726d961362 100644
--- a/deps/v8/src/ast/ast-value-factory.h
+++ b/deps/v8/src/ast/ast-value-factory.h
@@ -194,48 +194,49 @@ class AstBigInt {
};
// For generating constants.
-#define AST_STRING_CONSTANTS(F) \
- F(anonymous_function, "(anonymous function)") \
- F(arguments, "arguments") \
- F(async, "async") \
- F(await, "await") \
- F(bigint, "bigint") \
- F(boolean, "boolean") \
- F(constructor, "constructor") \
- F(default, "default") \
- F(done, "done") \
- F(dot, ".") \
- F(dot_for, ".for") \
- F(dot_generator_object, ".generator_object") \
- F(dot_iterator, ".iterator") \
- F(dot_result, ".result") \
- F(dot_switch_tag, ".switch_tag") \
- F(dot_catch, ".catch") \
- F(empty, "") \
- F(eval, "eval") \
- F(function, "function") \
- F(get_space, "get ") \
- F(length, "length") \
- F(let, "let") \
- F(name, "name") \
- F(native, "native") \
- F(new_target, ".new.target") \
- F(next, "next") \
- F(number, "number") \
- F(object, "object") \
- F(proto, "__proto__") \
- F(prototype, "prototype") \
- F(return, "return") \
- F(set_space, "set ") \
- F(star_default_star, "*default*") \
- F(string, "string") \
- F(symbol, "symbol") \
- F(this, "this") \
- F(this_function, ".this_function") \
- F(throw, "throw") \
- F(undefined, "undefined") \
- F(use_asm, "use asm") \
- F(use_strict, "use strict") \
+#define AST_STRING_CONSTANTS(F) \
+ F(anonymous_function, "(anonymous function)") \
+ F(arguments, "arguments") \
+ F(async, "async") \
+ F(await, "await") \
+ F(bigint, "bigint") \
+ F(boolean, "boolean") \
+ F(constructor, "constructor") \
+ F(default, "default") \
+ F(done, "done") \
+ F(dot, ".") \
+ F(dot_for, ".for") \
+ F(dot_generator_object, ".generator_object") \
+ F(dot_iterator, ".iterator") \
+ F(dot_promise, ".promise") \
+ F(dot_result, ".result") \
+ F(dot_switch_tag, ".switch_tag") \
+ F(dot_catch, ".catch") \
+ F(empty, "") \
+ F(eval, "eval") \
+ F(function, "function") \
+ F(get_space, "get ") \
+ F(length, "length") \
+ F(let, "let") \
+ F(name, "name") \
+ F(native, "native") \
+ F(new_target, ".new.target") \
+ F(next, "next") \
+ F(number, "number") \
+ F(object, "object") \
+ F(proto, "__proto__") \
+ F(prototype, "prototype") \
+ F(return, "return") \
+ F(set_space, "set ") \
+ F(star_default_star, "*default*") \
+ F(string, "string") \
+ F(symbol, "symbol") \
+ F(this, "this") \
+ F(this_function, ".this_function") \
+ F(throw, "throw") \
+ F(undefined, "undefined") \
+ F(use_asm, "use asm") \
+ F(use_strict, "use strict") \
F(value, "value")
class AstStringConstants final {
@@ -297,10 +298,15 @@ class AstValueFactory {
return GetTwoByteStringInternal(literal);
}
const AstRawString* GetString(Handle<String> literal);
+
+ // Clones an AstRawString from another ast value factory, adding it to this
+ // factory and returning the clone.
+ const AstRawString* CloneFromOtherFactory(const AstRawString* raw_string);
+
V8_EXPORT_PRIVATE AstConsString* NewConsString();
- AstConsString* NewConsString(const AstRawString* str);
- AstConsString* NewConsString(const AstRawString* str1,
- const AstRawString* str2);
+ V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str);
+ V8_EXPORT_PRIVATE AstConsString* NewConsString(const AstRawString* str1,
+ const AstRawString* str2);
V8_EXPORT_PRIVATE void Internalize(Isolate* isolate);
diff --git a/deps/v8/src/ast/ast.cc b/deps/v8/src/ast/ast.cc
index 5a4add6039..617a26b937 100644
--- a/deps/v8/src/ast/ast.cc
+++ b/deps/v8/src/ast/ast.cc
@@ -551,12 +551,6 @@ bool ObjectLiteral::IsFastCloningSupported() const {
ConstructorBuiltins::kMaximumClonedShallowObjectProperties;
}
-bool ArrayLiteral::is_empty() const {
- DCHECK(is_initialized());
- return values()->is_empty() && (boilerplate_description().is_null() ||
- boilerplate_description()->is_empty());
-}
-
int ArrayLiteral::InitDepthAndFlags() {
if (is_initialized()) return depth();
diff --git a/deps/v8/src/ast/ast.h b/deps/v8/src/ast/ast.h
index 6c1e989d30..6cc2cbc8ec 100644
--- a/deps/v8/src/ast/ast.h
+++ b/deps/v8/src/ast/ast.h
@@ -383,7 +383,7 @@ class DoExpression final : public Expression {
class Declaration : public AstNode {
public:
- typedef ThreadedList<Declaration> List;
+ typedef base::ThreadedList<Declaration> List;
VariableProxy* proxy() const { return proxy_; }
@@ -397,6 +397,7 @@ class Declaration : public AstNode {
Declaration** next() { return &next_; }
Declaration* next_;
friend List;
+ friend base::ThreadedListTraits<Declaration>;
};
class VariableDeclaration : public Declaration {
@@ -1477,8 +1478,6 @@ class ArrayLiteral final : public AggregateLiteral {
int first_spread_index() const { return first_spread_index_; }
- bool is_empty() const;
-
// Populate the depth field and flags, returns the depth.
int InitDepthAndFlags();
@@ -1578,8 +1577,15 @@ class VariableProxy final : public Expression {
// Bind this proxy to the variable var.
void BindTo(Variable* var);
- void set_next_unresolved(VariableProxy* next) { next_unresolved_ = next; }
- VariableProxy* next_unresolved() { return next_unresolved_; }
+ V8_INLINE VariableProxy* next_unresolved() { return next_unresolved_; }
+
+ // Provides an access type for the ThreadedList used by the PreParsers
+ // expressions, lists, and formal parameters.
+ struct PreParserNext {
+ static VariableProxy** next(VariableProxy* t) {
+ return t->pre_parser_expr_next();
+ }
+ };
private:
friend class AstNodeFactory;
@@ -1590,7 +1596,8 @@ class VariableProxy final : public Expression {
int start_position)
: Expression(start_position, kVariableProxy),
raw_name_(name),
- next_unresolved_(nullptr) {
+ next_unresolved_(nullptr),
+ pre_parser_expr_next_(nullptr) {
bit_field_ |= IsThisField::encode(variable_kind == THIS_VARIABLE) |
IsAssignedField::encode(false) |
IsResolvedField::encode(false) |
@@ -1613,9 +1620,15 @@ class VariableProxy final : public Expression {
const AstRawString* raw_name_; // if !is_resolved_
Variable* var_; // if is_resolved_
};
+
+ V8_INLINE VariableProxy** next() { return &next_unresolved_; }
VariableProxy* next_unresolved_;
-};
+ VariableProxy** pre_parser_expr_next() { return &pre_parser_expr_next_; }
+ VariableProxy* pre_parser_expr_next_;
+
+ friend base::ThreadedListTraits<VariableProxy>;
+};
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
@@ -2248,7 +2261,7 @@ class FunctionLiteral final : public Expression {
void mark_as_iife() { bit_field_ = IIFEBit::update(bit_field_, true); }
bool is_iife() const { return IIFEBit::decode(bit_field_); }
- bool is_top_level() const {
+ bool is_toplevel() const {
return function_literal_id() == FunctionLiteral::kIdTypeTopLevel;
}
bool is_wrapped() const { return function_type() == kWrapped; }
@@ -2308,7 +2321,7 @@ class FunctionLiteral final : public Expression {
// - (function() { ... })();
// - var x = function() { ... }();
bool ShouldEagerCompile() const;
- void SetShouldEagerCompile();
+ V8_EXPORT_PRIVATE void SetShouldEagerCompile();
FunctionType function_type() const {
return FunctionTypeBits::decode(bit_field_);
@@ -2736,7 +2749,7 @@ class TemplateLiteral final : public Expression {
// class SpecificVisitor : public AstVisitor<SpecificVisitor> { ... }
template <class Subclass>
-class AstVisitor BASE_EMBEDDED {
+class AstVisitor {
public:
void Visit(AstNode* node) { impl()->Visit(node); }
@@ -2823,7 +2836,7 @@ class AstVisitor BASE_EMBEDDED {
// ----------------------------------------------------------------------------
// AstNode factory
-class AstNodeFactory final BASE_EMBEDDED {
+class AstNodeFactory final {
public:
AstNodeFactory(AstValueFactory* ast_value_factory, Zone* zone)
: zone_(zone), ast_value_factory_(ast_value_factory) {}
@@ -3330,7 +3343,6 @@ class AstNodeFactory final BASE_EMBEDDED {
}
Zone* zone() const { return zone_; }
- void set_zone(Zone* zone) { zone_ = zone; }
private:
// This zone may be deallocated upon returning from parsing a function body
diff --git a/deps/v8/src/ast/prettyprinter.cc b/deps/v8/src/ast/prettyprinter.cc
index d2e56a9335..f9c2243099 100644
--- a/deps/v8/src/ast/prettyprinter.cc
+++ b/deps/v8/src/ast/prettyprinter.cc
@@ -31,7 +31,7 @@ CallPrinter::CallPrinter(Isolate* isolate, bool is_user_js)
InitializeAstVisitor(isolate);
}
-CallPrinter::~CallPrinter() {}
+CallPrinter::~CallPrinter() = default;
CallPrinter::ErrorHint CallPrinter::GetErrorHint() const {
if (is_call_error_) {
@@ -666,7 +666,7 @@ void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) {
//-----------------------------------------------------------------------------
-class IndentedScope BASE_EMBEDDED {
+class IndentedScope {
public:
IndentedScope(AstPrinter* printer, const char* txt)
: ast_printer_(printer) {
diff --git a/deps/v8/src/ast/scopes-inl.h b/deps/v8/src/ast/scopes-inl.h
new file mode 100644
index 0000000000..a70166c5ca
--- /dev/null
+++ b/deps/v8/src/ast/scopes-inl.h
@@ -0,0 +1,66 @@
+// 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_AST_SCOPES_INL_H_
+#define V8_AST_SCOPES_INL_H_
+
+#include "src/ast/scopes.h"
+
+namespace v8 {
+namespace internal {
+
+template <typename T>
+void Scope::ResolveScopesThenForEachVariable(DeclarationScope* max_outer_scope,
+ T variable_proxy_stackvisitor,
+ ParseInfo* info) {
+ // Module variables must be allocated before variable resolution
+ // to ensure that UpdateNeedsHoleCheck() can detect import variables.
+ if (info != nullptr && is_module_scope()) {
+ AsModuleScope()->AllocateModuleVariables();
+ }
+ // Lazy parsed declaration scopes are already partially analyzed. If there are
+ // unresolved references remaining, they just need to be resolved in outer
+ // scopes.
+ Scope* lookup =
+ is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
+ ? outer_scope()
+ : this;
+
+ for (VariableProxy *proxy = unresolved_list_.first(), *next = nullptr;
+ proxy != nullptr; proxy = next) {
+ next = proxy->next_unresolved();
+
+ DCHECK(!proxy->is_resolved());
+ Variable* var =
+ lookup->LookupRecursive(info, proxy, max_outer_scope->outer_scope());
+ if (var == nullptr) {
+ variable_proxy_stackvisitor(proxy);
+ } else if (var != Scope::kDummyPreParserVariable &&
+ var != Scope::kDummyPreParserLexicalVariable) {
+ if (info != nullptr) {
+ // In this case we need to leave scopes in a way that they can be
+ // allocated. If we resolved variables from lazy parsed scopes, we need
+ // to context allocate the var.
+ ResolveTo(info, proxy, var);
+ if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
+ } else {
+ var->set_is_used();
+ if (proxy->is_assigned()) var->set_maybe_assigned();
+ }
+ }
+ }
+
+ // Clear unresolved_list_ as it's in an inconsistent state.
+ unresolved_list_.Clear();
+
+ for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
+ scope->ResolveScopesThenForEachVariable(max_outer_scope,
+ variable_proxy_stackvisitor, info);
+ }
+}
+
+} // namespace internal
+} // namespace v8
+
+#endif // V8_AST_SCOPES_INL_H_
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index 74d50c44de..e9fb195609 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -8,6 +8,7 @@
#include "src/accessors.h"
#include "src/ast/ast.h"
+#include "src/ast/scopes-inl.h"
#include "src/base/optional.h"
#include "src/bootstrapper.h"
#include "src/counters.h"
@@ -23,15 +24,11 @@ namespace v8 {
namespace internal {
namespace {
-void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
-void* kDummyPreParserLexicalVariable = reinterpret_cast<void*>(0x2);
-
bool IsLexical(Variable* variable) {
- if (variable == kDummyPreParserLexicalVariable) return true;
- if (variable == kDummyPreParserVariable) return false;
+ if (variable == Scope::kDummyPreParserLexicalVariable) return true;
+ if (variable == Scope::kDummyPreParserVariable) return false;
return IsLexicalVariableMode(variable->mode());
}
-
} // namespace
// ----------------------------------------------------------------------------
@@ -76,8 +73,9 @@ Variable* VariableMap::DeclareName(Zone* zone, const AstRawString* name,
if (p->value == nullptr) {
// The variable has not been declared yet -> insert it.
DCHECK_EQ(name, p->key);
- p->value = mode == VariableMode::kVar ? kDummyPreParserVariable
- : kDummyPreParserLexicalVariable;
+ p->value = mode == VariableMode::kVar
+ ? Scope::kDummyPreParserVariable
+ : Scope::kDummyPreParserLexicalVariable;
}
return reinterpret_cast<Variable*>(p->value);
}
@@ -154,7 +152,7 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
Scope::Snapshot::Snapshot(Scope* scope)
: outer_scope_(scope),
top_inner_scope_(scope->inner_scope_),
- top_unresolved_(scope->unresolved_),
+ top_unresolved_(scope->unresolved_list_.first()),
top_local_(scope->GetClosureScope()->locals_.end()),
top_decl_(scope->GetClosureScope()->decls_.end()),
outer_scope_calls_eval_(scope->scope_calls_eval_) {
@@ -310,6 +308,8 @@ void DeclarationScope::SetDefaults() {
has_arguments_parameter_ = false;
scope_uses_super_property_ = false;
has_rest_ = false;
+ has_promise_ = false;
+ has_generator_object_ = false;
sloppy_block_function_map_ = nullptr;
receiver_ = nullptr;
new_target_ = nullptr;
@@ -319,7 +319,7 @@ void DeclarationScope::SetDefaults() {
should_eager_compile_ = false;
was_lazily_parsed_ = false;
is_skipped_function_ = false;
- produced_preparsed_scope_data_ = nullptr;
+ preparsed_scope_data_builder_ = nullptr;
#ifdef DEBUG
DeclarationScope* outer_declaration_scope =
outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
@@ -337,7 +337,7 @@ void Scope::SetDefaults() {
#endif
inner_scope_ = nullptr;
sibling_ = nullptr;
- unresolved_ = nullptr;
+ unresolved_list_.Clear();
start_position_ = kNoSourcePosition;
end_position_ = kNoSourcePosition;
@@ -779,6 +779,7 @@ Variable* DeclarationScope::DeclareGeneratorObjectVar(
Variable* result = EnsureRareData()->generator_object =
NewTemporary(name, kNotAssigned);
result->set_is_used();
+ has_generator_object_ = true;
return result;
}
@@ -787,6 +788,7 @@ Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
DCHECK_NULL(promise_var());
Variable* result = EnsureRareData()->promise = NewTemporary(name);
result->set_is_used();
+ has_promise_ = true;
return result;
}
@@ -834,16 +836,9 @@ Scope* Scope::FinalizeBlockScope() {
}
// Move unresolved variables
- if (unresolved_ != nullptr) {
- if (outer_scope()->unresolved_ != nullptr) {
- VariableProxy* unresolved = unresolved_;
- while (unresolved->next_unresolved() != nullptr) {
- unresolved = unresolved->next_unresolved();
- }
- unresolved->set_next_unresolved(outer_scope()->unresolved_);
- }
- outer_scope()->unresolved_ = unresolved_;
- unresolved_ = nullptr;
+ if (!unresolved_list_.is_empty()) {
+ outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
+ unresolved_list_.Clear();
}
if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
@@ -887,7 +882,7 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
DCHECK_EQ(new_parent->outer_scope_, outer_scope_);
DCHECK_EQ(new_parent, new_parent->GetClosureScope());
DCHECK_NULL(new_parent->inner_scope_);
- DCHECK_NULL(new_parent->unresolved_);
+ DCHECK(new_parent->unresolved_list_.is_empty());
DCHECK(new_parent->locals_.is_empty());
Scope* inner_scope = new_parent->sibling_;
if (inner_scope != top_inner_scope_) {
@@ -910,14 +905,21 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
new_parent->sibling_ = top_inner_scope_;
}
- if (outer_scope_->unresolved_ != top_unresolved_) {
- VariableProxy* last = outer_scope_->unresolved_;
- while (last->next_unresolved() != top_unresolved_) {
- last = last->next_unresolved();
+ if (outer_scope_->unresolved_list_.first() != top_unresolved_) {
+ // If the marked VariableProxy (snapshoted) is not the first, we need to
+ // find it and move all VariableProxys up to that point into the new_parent,
+ // then we restore the snapshoted state by reinitializing the outer_scope
+ // list.
+ {
+ auto iter = outer_scope_->unresolved_list_.begin();
+ while (*iter != top_unresolved_) {
+ ++iter;
+ }
+ outer_scope_->unresolved_list_.Rewind(iter);
}
- last->set_next_unresolved(nullptr);
- new_parent->unresolved_ = outer_scope_->unresolved_;
- outer_scope_->unresolved_ = top_unresolved_;
+
+ new_parent->unresolved_list_ = std::move(outer_scope_->unresolved_list_);
+ outer_scope_->unresolved_list_.ReinitializeHead(top_unresolved_);
}
// TODO(verwaest): This currently only moves do-expression declared variables
@@ -1261,8 +1263,7 @@ void Scope::DeclareCatchVariableName(const AstRawString* name) {
void Scope::AddUnresolved(VariableProxy* proxy) {
DCHECK(!already_resolved_);
DCHECK(!proxy->is_resolved());
- proxy->set_next_unresolved(unresolved_);
- unresolved_ = proxy;
+ unresolved_list_.AddFront(proxy);
}
Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
@@ -1274,22 +1275,7 @@ Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
}
bool Scope::RemoveUnresolved(VariableProxy* var) {
- if (unresolved_ == var) {
- unresolved_ = var->next_unresolved();
- var->set_next_unresolved(nullptr);
- return true;
- }
- VariableProxy* current = unresolved_;
- while (current != nullptr) {
- VariableProxy* next = current->next_unresolved();
- if (var == next) {
- current->set_next_unresolved(next->next_unresolved());
- var->set_next_unresolved(nullptr);
- return true;
- }
- current = next;
- }
- return false;
+ return unresolved_list_.Remove(var);
}
Variable* Scope::NewTemporary(const AstRawString* name) {
@@ -1483,11 +1469,12 @@ Scope* Scope::GetOuterScopeWithContext() {
Handle<StringSet> DeclarationScope::CollectNonLocals(
Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
- VariableProxy* free_variables = FetchFreeVariables(this, info);
- for (VariableProxy* proxy = free_variables; proxy != nullptr;
- proxy = proxy->next_unresolved()) {
- non_locals = StringSet::Add(isolate, non_locals, proxy->name());
- }
+ ResolveScopesThenForEachVariable(this,
+ [=, &non_locals](VariableProxy* proxy) {
+ non_locals = StringSet::Add(
+ isolate, non_locals, proxy->name());
+ },
+ info);
return non_locals;
}
@@ -1504,10 +1491,15 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
decls_.Clear();
locals_.Clear();
inner_scope_ = nullptr;
- unresolved_ = nullptr;
+ unresolved_list_.Clear();
sloppy_block_function_map_ = nullptr;
rare_data_ = nullptr;
has_rest_ = false;
+ has_promise_ = false;
+ has_generator_object_ = false;
+
+ DCHECK_NE(zone_, ast_value_factory->zone());
+ zone_->ReleaseMemory();
if (aborted) {
// Prepare scope for use in the outer zone.
@@ -1532,7 +1524,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
void Scope::SavePreParsedScopeData() {
DCHECK(FLAG_preparser_scope_analysis);
- if (ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(this)) {
+ if (PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(this)) {
AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
}
@@ -1542,30 +1534,33 @@ void Scope::SavePreParsedScopeData() {
}
void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
- if (produced_preparsed_scope_data_ != nullptr) {
+ if (preparsed_scope_data_builder_ != nullptr) {
DCHECK(FLAG_preparser_scope_analysis);
- produced_preparsed_scope_data_->SaveScopeAllocationData(this);
+ preparsed_scope_data_builder_->SaveScopeAllocationData(this);
}
}
void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
DCHECK(!force_eager_compilation_);
- VariableProxy* unresolved = nullptr;
-
- if (!outer_scope_->is_script_scope() ||
- (FLAG_preparser_scope_analysis &&
- produced_preparsed_scope_data_ != nullptr &&
- produced_preparsed_scope_data_->ContainsInnerFunctions())) {
+ base::ThreadedList<VariableProxy> new_unresolved_list;
+ if (!IsArrowFunction(function_kind_) &&
+ (!outer_scope_->is_script_scope() ||
+ (FLAG_preparser_scope_analysis &&
+ preparsed_scope_data_builder_ != nullptr &&
+ preparsed_scope_data_builder_->ContainsInnerFunctions()))) {
// Try to resolve unresolved variables for this Scope and migrate those
// which cannot be resolved inside. It doesn't make sense to try to resolve
// them in the outer Scopes here, because they are incomplete.
- for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr;
- proxy = proxy->next_unresolved()) {
- DCHECK(!proxy->is_resolved());
- VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
- copy->set_next_unresolved(unresolved);
- unresolved = copy;
- }
+ ResolveScopesThenForEachVariable(
+ this, [=, &new_unresolved_list](VariableProxy* proxy) {
+ // Don't copy unresolved references to the script scope, unless it's a
+ // reference to a private field. In that case keep it so we can fail
+ // later.
+ if (!outer_scope_->is_script_scope() || proxy->is_private_field()) {
+ VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
+ new_unresolved_list.AddFront(copy);
+ }
+ });
// Migrate function_ to the right Zone.
if (function_ != nullptr) {
@@ -1586,7 +1581,7 @@ void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
- unresolved_ = unresolved;
+ unresolved_list_ = std::move(new_unresolved_list);
}
#ifdef DEBUG
@@ -1673,8 +1668,8 @@ void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
Variable* var = reinterpret_cast<Variable*>(p->value);
if (var == function_var) continue;
- if (var == kDummyPreParserVariable ||
- var == kDummyPreParserLexicalVariable) {
+ if (var == Scope::kDummyPreParserVariable ||
+ var == Scope::kDummyPreParserLexicalVariable) {
continue;
}
bool local = !IsDynamicVariableMode(var->mode());
@@ -2045,8 +2040,7 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
// scopes.
if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
DCHECK_EQ(variables_.occupancy(), 0);
- for (VariableProxy* proxy = unresolved_; proxy != nullptr;
- proxy = proxy->next_unresolved()) {
+ for (VariableProxy* proxy : unresolved_list_) {
Variable* var = outer_scope()->LookupRecursive(info, proxy, nullptr);
if (var == nullptr) {
DCHECK(proxy->is_private_field());
@@ -2060,8 +2054,7 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
}
} else {
// Resolve unresolved variables for this scope.
- for (VariableProxy* proxy = unresolved_; proxy != nullptr;
- proxy = proxy->next_unresolved()) {
+ for (VariableProxy* proxy : unresolved_list_) {
if (!ResolveVariable(info, proxy)) return false;
}
@@ -2074,57 +2067,6 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
return true;
}
-VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
- ParseInfo* info,
- VariableProxy* stack) {
- // Module variables must be allocated before variable resolution
- // to ensure that UpdateNeedsHoleCheck() can detect import variables.
- if (info != nullptr && is_module_scope()) {
- AsModuleScope()->AllocateModuleVariables();
- }
- // Lazy parsed declaration scopes are already partially analyzed. If there are
- // unresolved references remaining, they just need to be resolved in outer
- // scopes.
- Scope* lookup =
- is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
- ? outer_scope()
- : this;
- for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
- proxy = next) {
- next = proxy->next_unresolved();
- DCHECK(!proxy->is_resolved());
- Variable* var =
- lookup->LookupRecursive(info, proxy, max_outer_scope->outer_scope());
- if (var == nullptr) {
- proxy->set_next_unresolved(stack);
- stack = proxy;
- } else if (var != kDummyPreParserVariable &&
- var != kDummyPreParserLexicalVariable) {
- if (info != nullptr) {
- // In this case we need to leave scopes in a way that they can be
- // allocated. If we resolved variables from lazy parsed scopes, we need
- // to context allocate the var.
- ResolveTo(info, proxy, var);
- if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
- } else {
- var->set_is_used();
- if (proxy->is_assigned()) {
- var->set_maybe_assigned();
- }
- }
- }
- }
-
- // Clear unresolved_ as it's in an inconsistent state.
- unresolved_ = nullptr;
-
- for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
- stack = scope->FetchFreeVariables(max_outer_scope, info, stack);
- }
-
- return stack;
-}
-
bool Scope::MustAllocate(Variable* var) {
if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
return true;
@@ -2236,6 +2178,24 @@ void DeclarationScope::AllocateReceiver() {
AllocateParameter(receiver(), -1);
}
+void DeclarationScope::AllocatePromise() {
+ if (!has_promise_) return;
+ DCHECK_NOT_NULL(promise_var());
+ DCHECK_EQ(this, promise_var()->scope());
+ AllocateStackSlot(promise_var());
+ DCHECK_EQ(VariableLocation::LOCAL, promise_var()->location());
+ DCHECK_EQ(kPromiseVarIndex, promise_var()->index());
+}
+
+void DeclarationScope::AllocateGeneratorObject() {
+ if (!has_generator_object_) return;
+ DCHECK_NOT_NULL(generator_object_var());
+ DCHECK_EQ(this, generator_object_var()->scope());
+ AllocateStackSlot(generator_object_var());
+ DCHECK_EQ(VariableLocation::LOCAL, generator_object_var()->location());
+ DCHECK_EQ(kGeneratorObjectVarIndex, generator_object_var()->index());
+}
+
void Scope::AllocateNonParameterLocal(Variable* var) {
DCHECK(var->scope() == this);
if (var->IsUnallocated() && MustAllocate(var)) {
@@ -2304,6 +2264,19 @@ void Scope::AllocateVariablesRecursively() {
return;
}
+ // Make sure to allocate the .promise (for async functions) or
+ // .generator_object (for async generators) first, so that it
+ // get's the required stack slot 0 in case it's needed. See
+ // http://bit.ly/v8-zero-cost-async-stack-traces for details.
+ if (is_function_scope()) {
+ FunctionKind kind = GetClosureScope()->function_kind();
+ if (IsAsyncGeneratorFunction(kind)) {
+ AsDeclarationScope()->AllocateGeneratorObject();
+ } else if (IsAsyncFunction(kind)) {
+ AsDeclarationScope()->AllocatePromise();
+ }
+ }
+
// Allocate variables for inner scopes.
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
scope->AllocateVariablesRecursively();
@@ -2410,5 +2383,9 @@ int Scope::ContextLocalCount() const {
(is_function_var_in_context ? 1 : 0);
}
+void* const Scope::kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
+void* const Scope::kDummyPreParserLexicalVariable =
+ reinterpret_cast<void*>(0x2);
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/ast/scopes.h b/deps/v8/src/ast/scopes.h
index f43761af58..0b88cc027c 100644
--- a/deps/v8/src/ast/scopes.h
+++ b/deps/v8/src/ast/scopes.h
@@ -20,8 +20,7 @@ class AstValueFactory;
class AstRawString;
class Declaration;
class ParseInfo;
-class PreParsedScopeData;
-class ProducedPreParsedScopeData;
+class PreParsedScopeDataBuilder;
class SloppyBlockFunctionStatement;
class Statement;
class StringSet;
@@ -103,7 +102,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
void SetScopeName(const AstRawString* scope_name) {
scope_name_ = scope_name;
}
- void set_needs_migration() { needs_migration_ = true; }
#endif
// TODO(verwaest): Is this needed on Scope?
@@ -114,7 +112,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
ModuleScope* AsModuleScope();
const ModuleScope* AsModuleScope() const;
- class Snapshot final BASE_EMBEDDED {
+ class Snapshot final {
public:
explicit Snapshot(Scope* scope);
~Snapshot();
@@ -125,8 +123,8 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
Scope* outer_scope_;
Scope* top_inner_scope_;
VariableProxy* top_unresolved_;
- ThreadedList<Variable>::Iterator top_local_;
- ThreadedList<Declaration>::Iterator top_decl_;
+ base::ThreadedList<Variable>::Iterator top_local_;
+ base::ThreadedList<Declaration>::Iterator top_decl_;
const bool outer_scope_calls_eval_;
};
@@ -203,9 +201,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
void DeclareCatchVariableName(const AstRawString* name);
// Declarations list.
- ThreadedList<Declaration>* declarations() { return &decls_; }
+ base::ThreadedList<Declaration>* declarations() { return &decls_; }
- ThreadedList<Variable>* locals() { return &locals_; }
+ base::ThreadedList<Variable>* locals() { return &locals_; }
// Create a new unresolved variable.
VariableProxy* NewUnresolved(AstNodeFactory* factory,
@@ -218,8 +216,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
DCHECK(!already_resolved_);
DCHECK_EQ(factory->zone(), zone());
VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_pos);
- proxy->set_next_unresolved(unresolved_);
- unresolved_ = proxy;
+ AddUnresolved(proxy);
return proxy;
}
@@ -480,6 +477,9 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
return false;
}
+ static void* const kDummyPreParserVariable;
+ static void* const kDummyPreParserLexicalVariable;
+
protected:
explicit Scope(Zone* zone);
@@ -522,12 +522,12 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
VariableMap variables_;
// In case of non-scopeinfo-backed scopes, this contains the variables of the
// map above in order of addition.
- ThreadedList<Variable> locals_;
+ base::ThreadedList<Variable> locals_;
// Unresolved variables referred to from this scope. The proxies themselves
// form a linked list of all unresolved proxies.
- VariableProxy* unresolved_;
+ base::ThreadedList<VariableProxy> unresolved_list_;
// Declarations.
- ThreadedList<Declaration> decls_;
+ base::ThreadedList<Declaration> decls_;
// Serialized scope info support.
Handle<ScopeInfo> scope_info_;
@@ -597,9 +597,10 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// Finds free variables of this scope. This mutates the unresolved variables
// list along the way, so full resolution cannot be done afterwards.
// If a ParseInfo* is passed, non-free variables will be resolved.
- VariableProxy* FetchFreeVariables(DeclarationScope* max_outer_scope,
- ParseInfo* info = nullptr,
- VariableProxy* stack = nullptr);
+ template <typename T>
+ void ResolveScopesThenForEachVariable(DeclarationScope* max_outer_scope,
+ T variable_proxy_stackvisitor,
+ ParseInfo* info = nullptr);
// Predicates.
bool MustAllocate(Variable* var);
@@ -682,6 +683,12 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
}
bool is_being_lazily_parsed() const { return is_being_lazily_parsed_; }
#endif
+ void set_zone(Zone* zone) {
+#ifdef DEBUG
+ needs_migration_ = true;
+#endif
+ zone_ = zone;
+ }
bool ShouldEagerCompile() const;
void set_should_eager_compile();
@@ -759,11 +766,22 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// literals, or nullptr. Only valid for function scopes.
Variable* function_var() const { return function_; }
+ // The variable holding the JSGeneratorObject for generator, async
+ // and async generator functions, and modules. Only valid for
+ // function and module scopes.
Variable* generator_object_var() const {
DCHECK(is_function_scope() || is_module_scope());
return GetRareVariable(RareVariable::kGeneratorObject);
}
+ // For async generators, the .generator_object variable is always
+ // allocated to a fixed stack slot, such that the stack trace
+ // construction logic can access it.
+ static constexpr int kGeneratorObjectVarIndex = 0;
+
+ // The variable holding the promise returned from async functions.
+ // Only valid for function scopes in async functions (i.e. not
+ // for async generators).
Variable* promise_var() const {
DCHECK(is_function_scope());
DCHECK(IsAsyncFunction(function_kind_));
@@ -771,6 +789,11 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
return GetRareVariable(RareVariable::kPromise);
}
+ // For async functions, the .promise variable is always allocated
+ // to a fixed stack slot, such that the stack trace construction
+ // logic can access it.
+ static constexpr int kPromiseVarIndex = 0;
+
// Parameters. The left-most parameter has index 0.
// Only valid for function and module scopes.
Variable* parameter(int index) const {
@@ -898,6 +921,8 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
void AllocateLocals();
void AllocateParameterLocals();
void AllocateReceiver();
+ void AllocatePromise();
+ void AllocateGeneratorObject();
void ResetAfterPreparsing(AstValueFactory* ast_value_factory, bool aborted);
@@ -919,13 +944,13 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// saved in produced_preparsed_scope_data_.
void SavePreParsedScopeDataForDeclarationScope();
- void set_produced_preparsed_scope_data(
- ProducedPreParsedScopeData* produced_preparsed_scope_data) {
- produced_preparsed_scope_data_ = produced_preparsed_scope_data;
+ void set_preparsed_scope_data_builder(
+ PreParsedScopeDataBuilder* preparsed_scope_data_builder) {
+ preparsed_scope_data_builder_ = preparsed_scope_data_builder;
}
- ProducedPreParsedScopeData* produced_preparsed_scope_data() const {
- return produced_preparsed_scope_data_;
+ PreParsedScopeDataBuilder* preparsed_scope_data_builder() const {
+ return preparsed_scope_data_builder_;
}
private:
@@ -954,6 +979,10 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
bool force_eager_compilation_ : 1;
// This function scope has a rest parameter.
bool has_rest_ : 1;
+ // This function scope has a .promise variable.
+ bool has_promise_ : 1;
+ // This function scope has a .generator_object variable.
+ bool has_generator_object_ : 1;
// This scope has a parameter called "arguments".
bool has_arguments_parameter_ : 1;
// This scope uses "super" property ('super.foo').
@@ -981,7 +1010,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
Variable* arguments_;
// For producing the scope allocation data during preparsing.
- ProducedPreParsedScopeData* produced_preparsed_scope_data_;
+ PreParsedScopeDataBuilder* preparsed_scope_data_builder_;
struct RareData : public ZoneObject {
// Convenience variable; Subclass constructor only
diff --git a/deps/v8/src/ast/variables.h b/deps/v8/src/ast/variables.h
index 10ac5c48a5..d33062973b 100644
--- a/deps/v8/src/ast/variables.h
+++ b/deps/v8/src/ast/variables.h
@@ -181,7 +181,7 @@ class Variable final : public ZoneObject {
: kNeedsInitialization;
}
- typedef ThreadedList<Variable> List;
+ typedef base::ThreadedList<Variable> List;
private:
Scope* scope_;
@@ -215,6 +215,7 @@ class Variable final : public ZoneObject {
ForceHoleInitializationField::kNext, 1> {};
Variable** next() { return &next_; }
friend List;
+ friend base::ThreadedListTraits<Variable>;
};
} // namespace internal
} // namespace v8