diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-03-21 16:16:48 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-03-25 09:44:11 +0100 |
commit | 07088e6fc1342b5581d9e6f7ce084308573e3139 (patch) | |
tree | 05df5e41276c73c3f3392e1aa0bce02084866d2b /deps/v8/src/ast | |
parent | 8394b05e20d3b661bb36cf778cd1f8c323334d7d (diff) | |
download | android-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.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/ast/ast.h | 20 | ||||
-rw-r--r-- | deps/v8/src/ast/scopes.cc | 27 | ||||
-rw-r--r-- | deps/v8/src/ast/scopes.h | 68 |
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 { |