aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/ast
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-03-21 16:16:48 +0100
committerMichaël Zasso <targos@protonmail.com>2017-03-25 09:44:11 +0100
commit07088e6fc1342b5581d9e6f7ce084308573e3139 (patch)
tree05df5e41276c73c3f3392e1aa0bce02084866d2b /deps/v8/src/ast
parent8394b05e20d3b661bb36cf778cd1f8c323334d7d (diff)
downloadandroid-node-v8-07088e6fc1342b5581d9e6f7ce084308573e3139.tar.gz
android-node-v8-07088e6fc1342b5581d9e6f7ce084308573e3139.tar.bz2
android-node-v8-07088e6fc1342b5581d9e6f7ce084308573e3139.zip
deps: backport 39642fa from upstream V8
This is an almost clean cherry-pick of the original commit. The only conflict was related to a rename of an internal class. Original commit message: [async-await] (simpler) fix for Return in try/finally in async functions Alternative approach to https://codereview.chromium.org/2667983004/, which does not depend on implicit control flow changes from https://codereview.chromium.org/2664083002 - Remove handling for `async function` from Parser::RewriteReturn(). This functionality is moved to BytecodeGenerator::BuildAsyncReturn(). This ensures that promise resolution is deferred until all finally blocks are evaluated fully. - Add a new deferred command (CMD_ASYNC_RETURN), which instructs ControlScope to generate return code using BuildAsyncReturn rather than BuildReturn. - Parser has a new `NewReturnStatement()` helper which determines what type of return statement to generate based on the type of function. BUG=v8:5896, v8:4483 R=littledan@chromium.org, neis@chromium.org, rmcilroy@chromium.org, adamk@chromium.org, gsathya@chromium.org Review-Url: https://codereview.chromium.org/2685683002 Cr-Commit-Position: refs/heads/master@{#43104} Fixes: https://github.com/nodejs/node/issues/11960 PR-URL: https://github.com/nodejs/node/pull/11752 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'deps/v8/src/ast')
-rw-r--r--deps/v8/src/ast/ast-numbering.cc3
-rw-r--r--deps/v8/src/ast/ast.h20
-rw-r--r--deps/v8/src/ast/scopes.cc27
-rw-r--r--deps/v8/src/ast/scopes.h68
4 files changed, 106 insertions, 12 deletions
diff --git a/deps/v8/src/ast/ast-numbering.cc b/deps/v8/src/ast/ast-numbering.cc
index 25aa9d7a5a..49040f7841 100644
--- a/deps/v8/src/ast/ast-numbering.cc
+++ b/deps/v8/src/ast/ast-numbering.cc
@@ -211,6 +211,9 @@ void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
IncrementNodeCount();
Visit(node->expression());
+
+ DCHECK(!node->is_async_return() ||
+ properties_.flags() & AstProperties::kMustUseIgnitionTurbo);
}
diff --git a/deps/v8/src/ast/ast.h b/deps/v8/src/ast/ast.h
index af561e0a3f..0cf20b0e4c 100644
--- a/deps/v8/src/ast/ast.h
+++ b/deps/v8/src/ast/ast.h
@@ -895,17 +895,25 @@ class BreakStatement final : public JumpStatement {
class ReturnStatement final : public JumpStatement {
public:
+ enum Type { kNormal, kAsyncReturn };
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
+ Type type() const { return TypeField::decode(bit_field_); }
+ bool is_async_return() const { return type() == kAsyncReturn; }
private:
friend class AstNodeFactory;
- ReturnStatement(Expression* expression, int pos)
- : JumpStatement(pos, kReturnStatement), expression_(expression) {}
+ ReturnStatement(Expression* expression, Type type, int pos)
+ : JumpStatement(pos, kReturnStatement), expression_(expression) {
+ bit_field_ |= TypeField::encode(type);
+ }
Expression* expression_;
+
+ class TypeField
+ : public BitField<Type, JumpStatement::kNextBitFieldIndex, 1> {};
};
@@ -3217,7 +3225,13 @@ class AstNodeFactory final BASE_EMBEDDED {
}
ReturnStatement* NewReturnStatement(Expression* expression, int pos) {
- return new (zone_) ReturnStatement(expression, pos);
+ return new (zone_)
+ ReturnStatement(expression, ReturnStatement::kNormal, pos);
+ }
+
+ ReturnStatement* NewAsyncReturnStatement(Expression* expression, int pos) {
+ return new (zone_)
+ ReturnStatement(expression, ReturnStatement::kAsyncReturn, pos);
}
WithStatement* NewWithStatement(Scope* scope,
diff --git a/deps/v8/src/ast/scopes.cc b/deps/v8/src/ast/scopes.cc
index b61bcdab55..27654c20f6 100644
--- a/deps/v8/src/ast/scopes.cc
+++ b/deps/v8/src/ast/scopes.cc
@@ -294,7 +294,7 @@ void DeclarationScope::SetDefaults() {
new_target_ = nullptr;
function_ = nullptr;
arguments_ = nullptr;
- this_function_ = nullptr;
+ rare_data_ = nullptr;
should_eager_compile_ = false;
was_lazily_parsed_ = false;
#ifdef DEBUG
@@ -672,7 +672,7 @@ void DeclarationScope::DeclareDefaultFunctionVariables(
if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
IsAccessorFunction(function_kind_)) {
- this_function_ =
+ EnsureRareData()->this_function =
Declare(zone(), ast_value_factory->this_function_string(), CONST);
}
}
@@ -693,6 +693,24 @@ Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
return function_;
}
+Variable* DeclarationScope::DeclareGeneratorObjectVar(
+ const AstRawString* name) {
+ DCHECK(is_function_scope() || is_module_scope());
+ DCHECK_NULL(generator_object_var());
+
+ Variable* result = EnsureRareData()->generator_object = NewTemporary(name);
+ result->set_is_used();
+ return result;
+}
+
+Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
+ DCHECK(is_function_scope());
+ DCHECK_NULL(promise_var());
+ Variable* result = EnsureRareData()->promise = NewTemporary(name);
+ result->set_is_used();
+ return result;
+}
+
bool Scope::HasBeenRemoved() const {
if (sibling() == this) {
DCHECK_NULL(inner_scope_);
@@ -2053,9 +2071,8 @@ void DeclarationScope::AllocateLocals() {
new_target_ = nullptr;
}
- if (this_function_ != nullptr && !MustAllocate(this_function_)) {
- this_function_ = nullptr;
- }
+ NullifyRareVariableIf(RareVariable::kThisFunction,
+ [=](Variable* var) { return !MustAllocate(var); });
}
void ModuleScope::AllocateModuleVariables() {
diff --git a/deps/v8/src/ast/scopes.h b/deps/v8/src/ast/scopes.h
index 49cfdffba7..9e80e1c8e6 100644
--- a/deps/v8/src/ast/scopes.h
+++ b/deps/v8/src/ast/scopes.h
@@ -676,6 +676,11 @@ class DeclarationScope : public Scope {
// calls sloppy eval.
Variable* DeclareFunctionVar(const AstRawString* name);
+ // Declare some special internal variables which must be accessible to
+ // Ignition without ScopeInfo.
+ Variable* DeclareGeneratorObjectVar(const AstRawString* name);
+ Variable* DeclarePromiseVar(const AstRawString* name);
+
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right.
@@ -714,6 +719,17 @@ class DeclarationScope : public Scope {
return function_;
}
+ Variable* generator_object_var() const {
+ DCHECK(is_function_scope() || is_module_scope());
+ return GetRareVariable(RareVariable::kGeneratorObject);
+ }
+
+ Variable* promise_var() const {
+ DCHECK(is_function_scope());
+ DCHECK(IsAsyncFunction(function_kind_));
+ return GetRareVariable(RareVariable::kPromise);
+ }
+
// Parameters. The left-most parameter has index 0.
// Only valid for function and module scopes.
Variable* parameter(int index) const {
@@ -754,12 +770,14 @@ class DeclarationScope : public Scope {
}
Variable* this_function_var() const {
+ Variable* this_function = GetRareVariable(RareVariable::kThisFunction);
+
// This is only used in derived constructors atm.
- DCHECK(this_function_ == nullptr ||
+ DCHECK(this_function == nullptr ||
(is_function_scope() && (IsClassConstructor(function_kind()) ||
IsConciseMethod(function_kind()) ||
IsAccessorFunction(function_kind()))));
- return this_function_;
+ return this_function;
}
// Adds a local variable in this scope's locals list. This is for adjusting
@@ -867,8 +885,50 @@ class DeclarationScope : public Scope {
Variable* new_target_;
// Convenience variable; function scopes only.
Variable* arguments_;
- // Convenience variable; Subclass constructor only
- Variable* this_function_;
+
+ struct RareData : public ZoneObject {
+ void* operator new(size_t size, Zone* zone) { return zone->New(size); }
+
+ // Convenience variable; Subclass constructor only
+ Variable* this_function = nullptr;
+
+ // Generator object, if any; generator function scopes and module scopes
+ // only.
+ Variable* generator_object = nullptr;
+ // Promise, if any; async function scopes only.
+ Variable* promise = nullptr;
+ };
+
+ enum class RareVariable {
+ kThisFunction = offsetof(RareData, this_function),
+ kGeneratorObject = offsetof(RareData, generator_object),
+ kPromise = offsetof(RareData, promise)
+ };
+
+ V8_INLINE RareData* EnsureRareData() {
+ if (rare_data_ == nullptr) {
+ rare_data_ = new (zone_) RareData;
+ }
+ return rare_data_;
+ }
+
+ V8_INLINE Variable* GetRareVariable(RareVariable id) const {
+ if (rare_data_ == nullptr) return nullptr;
+ return *reinterpret_cast<Variable**>(
+ reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
+ }
+
+ // Set `var` to null if it's non-null and Predicate (Variable*) -> bool
+ // returns true.
+ template <typename Predicate>
+ V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate) {
+ if (V8_LIKELY(rare_data_ == nullptr)) return;
+ Variable** var = reinterpret_cast<Variable**>(
+ reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
+ if (*var && predicate(*var)) *var = nullptr;
+ }
+
+ RareData* rare_data_ = nullptr;
};
class ModuleScope final : public DeclarationScope {