Skip to content

Commit 07088e6

Browse files
committed
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 [email protected], [email protected], [email protected], [email protected], [email protected] Review-Url: https://codereview.chromium.org/2685683002 Cr-Commit-Position: refs/heads/master@{#43104} Fixes: #11960 PR-URL: #11752 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Franziska Hinkelmann <[email protected]>
1 parent 8394b05 commit 07088e6

10 files changed

+373
-38
lines changed

deps/v8/src/ast/ast-numbering.cc

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ void AstNumberingVisitor::VisitExpressionStatement(ExpressionStatement* node) {
211211
void AstNumberingVisitor::VisitReturnStatement(ReturnStatement* node) {
212212
IncrementNodeCount();
213213
Visit(node->expression());
214+
215+
DCHECK(!node->is_async_return() ||
216+
properties_.flags() & AstProperties::kMustUseIgnitionTurbo);
214217
}
215218

216219

deps/v8/src/ast/ast.h

+17-3
Original file line numberDiff line numberDiff line change
@@ -895,17 +895,25 @@ class BreakStatement final : public JumpStatement {
895895

896896
class ReturnStatement final : public JumpStatement {
897897
public:
898+
enum Type { kNormal, kAsyncReturn };
898899
Expression* expression() const { return expression_; }
899900

900901
void set_expression(Expression* e) { expression_ = e; }
902+
Type type() const { return TypeField::decode(bit_field_); }
903+
bool is_async_return() const { return type() == kAsyncReturn; }
901904

902905
private:
903906
friend class AstNodeFactory;
904907

905-
ReturnStatement(Expression* expression, int pos)
906-
: JumpStatement(pos, kReturnStatement), expression_(expression) {}
908+
ReturnStatement(Expression* expression, Type type, int pos)
909+
: JumpStatement(pos, kReturnStatement), expression_(expression) {
910+
bit_field_ |= TypeField::encode(type);
911+
}
907912

908913
Expression* expression_;
914+
915+
class TypeField
916+
: public BitField<Type, JumpStatement::kNextBitFieldIndex, 1> {};
909917
};
910918

911919

@@ -3217,7 +3225,13 @@ class AstNodeFactory final BASE_EMBEDDED {
32173225
}
32183226

32193227
ReturnStatement* NewReturnStatement(Expression* expression, int pos) {
3220-
return new (zone_) ReturnStatement(expression, pos);
3228+
return new (zone_)
3229+
ReturnStatement(expression, ReturnStatement::kNormal, pos);
3230+
}
3231+
3232+
ReturnStatement* NewAsyncReturnStatement(Expression* expression, int pos) {
3233+
return new (zone_)
3234+
ReturnStatement(expression, ReturnStatement::kAsyncReturn, pos);
32213235
}
32223236

32233237
WithStatement* NewWithStatement(Scope* scope,

deps/v8/src/ast/scopes.cc

+22-5
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ void DeclarationScope::SetDefaults() {
294294
new_target_ = nullptr;
295295
function_ = nullptr;
296296
arguments_ = nullptr;
297-
this_function_ = nullptr;
297+
rare_data_ = nullptr;
298298
should_eager_compile_ = false;
299299
was_lazily_parsed_ = false;
300300
#ifdef DEBUG
@@ -672,7 +672,7 @@ void DeclarationScope::DeclareDefaultFunctionVariables(
672672

673673
if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
674674
IsAccessorFunction(function_kind_)) {
675-
this_function_ =
675+
EnsureRareData()->this_function =
676676
Declare(zone(), ast_value_factory->this_function_string(), CONST);
677677
}
678678
}
@@ -693,6 +693,24 @@ Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
693693
return function_;
694694
}
695695

696+
Variable* DeclarationScope::DeclareGeneratorObjectVar(
697+
const AstRawString* name) {
698+
DCHECK(is_function_scope() || is_module_scope());
699+
DCHECK_NULL(generator_object_var());
700+
701+
Variable* result = EnsureRareData()->generator_object = NewTemporary(name);
702+
result->set_is_used();
703+
return result;
704+
}
705+
706+
Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
707+
DCHECK(is_function_scope());
708+
DCHECK_NULL(promise_var());
709+
Variable* result = EnsureRareData()->promise = NewTemporary(name);
710+
result->set_is_used();
711+
return result;
712+
}
713+
696714
bool Scope::HasBeenRemoved() const {
697715
if (sibling() == this) {
698716
DCHECK_NULL(inner_scope_);
@@ -2053,9 +2071,8 @@ void DeclarationScope::AllocateLocals() {
20532071
new_target_ = nullptr;
20542072
}
20552073

2056-
if (this_function_ != nullptr && !MustAllocate(this_function_)) {
2057-
this_function_ = nullptr;
2058-
}
2074+
NullifyRareVariableIf(RareVariable::kThisFunction,
2075+
[=](Variable* var) { return !MustAllocate(var); });
20592076
}
20602077

20612078
void ModuleScope::AllocateModuleVariables() {

deps/v8/src/ast/scopes.h

+64-4
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,11 @@ class DeclarationScope : public Scope {
676676
// calls sloppy eval.
677677
Variable* DeclareFunctionVar(const AstRawString* name);
678678

679+
// Declare some special internal variables which must be accessible to
680+
// Ignition without ScopeInfo.
681+
Variable* DeclareGeneratorObjectVar(const AstRawString* name);
682+
Variable* DeclarePromiseVar(const AstRawString* name);
683+
679684
// Declare a parameter in this scope. When there are duplicated
680685
// parameters the rightmost one 'wins'. However, the implementation
681686
// expects all parameters to be declared and from left to right.
@@ -714,6 +719,17 @@ class DeclarationScope : public Scope {
714719
return function_;
715720
}
716721

722+
Variable* generator_object_var() const {
723+
DCHECK(is_function_scope() || is_module_scope());
724+
return GetRareVariable(RareVariable::kGeneratorObject);
725+
}
726+
727+
Variable* promise_var() const {
728+
DCHECK(is_function_scope());
729+
DCHECK(IsAsyncFunction(function_kind_));
730+
return GetRareVariable(RareVariable::kPromise);
731+
}
732+
717733
// Parameters. The left-most parameter has index 0.
718734
// Only valid for function and module scopes.
719735
Variable* parameter(int index) const {
@@ -754,12 +770,14 @@ class DeclarationScope : public Scope {
754770
}
755771

756772
Variable* this_function_var() const {
773+
Variable* this_function = GetRareVariable(RareVariable::kThisFunction);
774+
757775
// This is only used in derived constructors atm.
758-
DCHECK(this_function_ == nullptr ||
776+
DCHECK(this_function == nullptr ||
759777
(is_function_scope() && (IsClassConstructor(function_kind()) ||
760778
IsConciseMethod(function_kind()) ||
761779
IsAccessorFunction(function_kind()))));
762-
return this_function_;
780+
return this_function;
763781
}
764782

765783
// Adds a local variable in this scope's locals list. This is for adjusting
@@ -867,8 +885,50 @@ class DeclarationScope : public Scope {
867885
Variable* new_target_;
868886
// Convenience variable; function scopes only.
869887
Variable* arguments_;
870-
// Convenience variable; Subclass constructor only
871-
Variable* this_function_;
888+
889+
struct RareData : public ZoneObject {
890+
void* operator new(size_t size, Zone* zone) { return zone->New(size); }
891+
892+
// Convenience variable; Subclass constructor only
893+
Variable* this_function = nullptr;
894+
895+
// Generator object, if any; generator function scopes and module scopes
896+
// only.
897+
Variable* generator_object = nullptr;
898+
// Promise, if any; async function scopes only.
899+
Variable* promise = nullptr;
900+
};
901+
902+
enum class RareVariable {
903+
kThisFunction = offsetof(RareData, this_function),
904+
kGeneratorObject = offsetof(RareData, generator_object),
905+
kPromise = offsetof(RareData, promise)
906+
};
907+
908+
V8_INLINE RareData* EnsureRareData() {
909+
if (rare_data_ == nullptr) {
910+
rare_data_ = new (zone_) RareData;
911+
}
912+
return rare_data_;
913+
}
914+
915+
V8_INLINE Variable* GetRareVariable(RareVariable id) const {
916+
if (rare_data_ == nullptr) return nullptr;
917+
return *reinterpret_cast<Variable**>(
918+
reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
919+
}
920+
921+
// Set `var` to null if it's non-null and Predicate (Variable*) -> bool
922+
// returns true.
923+
template <typename Predicate>
924+
V8_INLINE void NullifyRareVariableIf(RareVariable id, Predicate predicate) {
925+
if (V8_LIKELY(rare_data_ == nullptr)) return;
926+
Variable** var = reinterpret_cast<Variable**>(
927+
reinterpret_cast<uint8_t*>(rare_data_) + static_cast<ptrdiff_t>(id));
928+
if (*var && predicate(*var)) *var = nullptr;
929+
}
930+
931+
RareData* rare_data_ = nullptr;
872932
};
873933

874934
class ModuleScope final : public DeclarationScope {

deps/v8/src/interpreter/bytecode-generator.cc

+43-2
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,19 @@ class BytecodeGenerator::ControlScope BASE_EMBEDDED {
106106
void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
107107
void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
108108
void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); }
109+
void AsyncReturnAccumulator() { PerformCommand(CMD_ASYNC_RETURN, nullptr); }
109110
void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); }
110111

111112
class DeferredCommands;
112113

113114
protected:
114-
enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW };
115+
enum Command {
116+
CMD_BREAK,
117+
CMD_CONTINUE,
118+
CMD_RETURN,
119+
CMD_ASYNC_RETURN,
120+
CMD_RETHROW
121+
};
115122
void PerformCommand(Command command, Statement* statement);
116123
virtual bool Execute(Command command, Statement* statement) = 0;
117124

@@ -221,6 +228,9 @@ class BytecodeGenerator::ControlScopeForTopLevel final
221228
case CMD_RETURN:
222229
generator()->BuildReturn();
223230
return true;
231+
case CMD_ASYNC_RETURN:
232+
generator()->BuildAsyncReturn();
233+
return true;
224234
case CMD_RETHROW:
225235
generator()->BuildReThrow();
226236
return true;
@@ -249,6 +259,7 @@ class BytecodeGenerator::ControlScopeForBreakable final
249259
return true;
250260
case CMD_CONTINUE:
251261
case CMD_RETURN:
262+
case CMD_ASYNC_RETURN:
252263
case CMD_RETHROW:
253264
break;
254265
}
@@ -286,6 +297,7 @@ class BytecodeGenerator::ControlScopeForIteration final
286297
loop_builder_->Continue();
287298
return true;
288299
case CMD_RETURN:
300+
case CMD_ASYNC_RETURN:
289301
case CMD_RETHROW:
290302
break;
291303
}
@@ -311,6 +323,7 @@ class BytecodeGenerator::ControlScopeForTryCatch final
311323
case CMD_BREAK:
312324
case CMD_CONTINUE:
313325
case CMD_RETURN:
326+
case CMD_ASYNC_RETURN:
314327
break;
315328
case CMD_RETHROW:
316329
generator()->BuildReThrow();
@@ -337,6 +350,7 @@ class BytecodeGenerator::ControlScopeForTryFinally final
337350
case CMD_BREAK:
338351
case CMD_CONTINUE:
339352
case CMD_RETURN:
353+
case CMD_ASYNC_RETURN:
340354
case CMD_RETHROW:
341355
commands_->RecordCommand(command, statement);
342356
try_finally_builder_->LeaveTry();
@@ -1045,7 +1059,12 @@ void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
10451059
void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
10461060
builder()->SetStatementPosition(stmt);
10471061
VisitForAccumulatorValue(stmt->expression());
1048-
execution_control()->ReturnAccumulator();
1062+
1063+
if (stmt->is_async_return()) {
1064+
execution_control()->AsyncReturnAccumulator();
1065+
} else {
1066+
execution_control()->ReturnAccumulator();
1067+
}
10491068
}
10501069

10511070
void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
@@ -1982,6 +2001,28 @@ void BytecodeGenerator::BuildReturn() {
19822001
builder()->Return();
19832002
}
19842003

2004+
void BytecodeGenerator::BuildAsyncReturn() {
2005+
DCHECK(IsAsyncFunction(info()->literal()->kind()));
2006+
RegisterAllocationScope register_scope(this);
2007+
RegisterList args = register_allocator()->NewRegisterList(3);
2008+
Register receiver = args[0];
2009+
Register promise = args[1];
2010+
Register return_value = args[2];
2011+
builder()->StoreAccumulatorInRegister(return_value);
2012+
2013+
Variable* var_promise = scope()->promise_var();
2014+
DCHECK_NOT_NULL(var_promise);
2015+
BuildVariableLoad(var_promise, FeedbackVectorSlot::Invalid(),
2016+
HoleCheckMode::kElided);
2017+
builder()
2018+
->StoreAccumulatorInRegister(promise)
2019+
.LoadUndefined()
2020+
.StoreAccumulatorInRegister(receiver)
2021+
.CallJSRuntime(Context::PROMISE_RESOLVE_INDEX, args)
2022+
.LoadAccumulatorWithRegister(promise);
2023+
BuildReturn();
2024+
}
2025+
19852026
void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); }
19862027

19872028
void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {

deps/v8/src/interpreter/bytecode-generator.h

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
106106
HoleCheckMode hole_check_mode);
107107

108108
void BuildReturn();
109+
void BuildAsyncReturn();
109110
void BuildReThrow();
110111
void BuildAbort(BailoutReason bailout_reason);
111112
void BuildThrowIfHole(Handle<String> name);

deps/v8/src/parsing/parser-base.h

+14-17
Original file line numberDiff line numberDiff line change
@@ -419,23 +419,12 @@ class ParserBase {
419419
FunctionKind kind() const { return scope()->function_kind(); }
420420
FunctionState* outer() const { return outer_function_state_; }
421421

422-
void set_generator_object_variable(typename Types::Variable* variable) {
423-
DCHECK_NOT_NULL(variable);
424-
DCHECK(IsResumableFunction(kind()));
425-
DCHECK(scope()->has_forced_context_allocation());
426-
generator_object_variable_ = variable;
427-
}
428422
typename Types::Variable* generator_object_variable() const {
429-
return generator_object_variable_;
423+
return scope()->generator_object_var();
430424
}
431425

432-
void set_promise_variable(typename Types::Variable* variable) {
433-
DCHECK(variable != NULL);
434-
DCHECK(IsAsyncFunction(kind()));
435-
promise_variable_ = variable;
436-
}
437426
typename Types::Variable* promise_variable() const {
438-
return promise_variable_;
427+
return scope()->promise_var();
439428
}
440429

441430
const ZoneList<DestructuringAssignment>&
@@ -1336,6 +1325,15 @@ class ParserBase {
13361325
return Call::NOT_EVAL;
13371326
}
13381327

1328+
// Convenience method which determines the type of return statement to emit
1329+
// depending on the current function type.
1330+
inline StatementT BuildReturnStatement(ExpressionT expr, int pos) {
1331+
if (V8_UNLIKELY(is_async_function())) {
1332+
return factory()->NewAsyncReturnStatement(expr, pos);
1333+
}
1334+
return factory()->NewReturnStatement(expr, pos);
1335+
}
1336+
13391337
// Validation per ES6 object literals.
13401338
class ObjectLiteralChecker {
13411339
public:
@@ -4074,9 +4072,8 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
40744072
} else {
40754073
ExpressionT expression = ParseAssignmentExpression(accept_IN, CHECK_OK);
40764074
impl()->RewriteNonPattern(CHECK_OK);
4077-
body->Add(
4078-
factory()->NewReturnStatement(expression, expression->position()),
4079-
zone());
4075+
body->Add(BuildReturnStatement(expression, expression->position()),
4076+
zone());
40804077
if (allow_tailcalls() && !is_sloppy(language_mode())) {
40814078
// ES6 14.6.1 Static Semantics: IsInTailPosition
40824079
impl()->MarkTailPosition(expression);
@@ -4981,7 +4978,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseReturnStatement(
49814978
}
49824979
ExpectSemicolon(CHECK_OK);
49834980
return_value = impl()->RewriteReturn(return_value, loc.beg_pos);
4984-
return factory()->NewReturnStatement(return_value, loc.beg_pos);
4981+
return BuildReturnStatement(return_value, loc.beg_pos);
49854982
}
49864983

49874984
template <typename Impl>

0 commit comments

Comments
 (0)