Skip to content

Commit

Permalink
[vm] New async*/yield/yield* implementation based on suspend/resume s…
Browse files Browse the repository at this point in the history
…tubs

TEST=ci
Issue: #48378
Change-Id: I0c2ca9269b2c8f008a79c139a0ce10231996732d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/242923
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
  • Loading branch information
alexmarkov authored and Commit Bot committed May 2, 2022
1 parent 0d5d34a commit 4075e8b
Show file tree
Hide file tree
Showing 48 changed files with 1,289 additions and 766 deletions.
2 changes: 1 addition & 1 deletion pkg/kernel/binary.md
Original file line number Diff line number Diff line change
Expand Up @@ -1371,7 +1371,7 @@ type TryFinally extends Statement {
type YieldStatement extends Statement {
Byte tag = 77;
FileOffset fileOffset;
Byte flags (isYieldStar);
Byte flags (isYieldStar, isNative);
Expression expression;
}

Expand Down
13 changes: 10 additions & 3 deletions pkg/vm/lib/transformations/continuation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,16 @@ class RecursiveContinuationRewriter extends RemovingTransformer {
return node;
}
case AsyncMarker.AsyncStar:
return new AsyncStarFunctionRewriter(
helper, node, staticTypeContext, desugarAsync)
.rewrite();
if (desugarAsync) {
return new AsyncStarFunctionRewriter(
helper, node, staticTypeContext, desugarAsync)
.rewrite();
} else {
node.transformOrRemoveChildren(new RecursiveContinuationRewriter(
helper, staticTypeContext, desugarAsync,
desugarAwaitFor: true));
return node;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion runtime/vm/code_descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ class ExceptionHandlerList : public ZoneAllocated {
};

explicit ExceptionHandlerList(const Function& function)
: list_(), has_async_handler_(function.IsCompactAsyncFunction()) {}
: list_(),
has_async_handler_(function.IsCompactAsyncFunction() ||
function.IsCompactAsyncStarFunction()) {}

intptr_t Length() const { return list_.length(); }

Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ void FlowGraphCompiler::EmitPrologue() {
} else if (parsed_function().suspend_state_var() != nullptr) {
// Initialize synthetic :suspend_state variable early
// as it may be accessed by GC and exception handling before
// InitAsync stub is called.
// InitSuspendableFunction stub is called.
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariable(
parsed_function().suspend_state_var());
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ void FlowGraphCompiler::EmitPrologue() {
} else if (parsed_function().suspend_state_var() != nullptr) {
// Initialize synthetic :suspend_state variable early
// as it may be accessed by GC and exception handling before
// InitAsync stub is called.
// InitSuspendableFunction stub is called.
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariable(
parsed_function().suspend_state_var());
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ void FlowGraphCompiler::EmitPrologue() {
} else if (parsed_function().suspend_state_var() != nullptr) {
// Initialize synthetic :suspend_state variable early
// as it may be accessed by GC and exception handling before
// InitAsync stub is called.
// InitSuspendableFunction stub is called.
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariable(
parsed_function().suspend_state_var());
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ void FlowGraphCompiler::EmitPrologue() {
} else if (parsed_function().suspend_state_var() != nullptr) {
// Initialize synthetic :suspend_state variable early
// as it may be accessed by GC and exception handling before
// InitAsync stub is called.
// InitSuspendableFunction stub is called.
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariable(
parsed_function().suspend_state_var());
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ void FlowGraphCompiler::EmitPrologue() {
} else if (parsed_function().suspend_state_var() != nullptr) {
// Initialize synthetic :suspend_state variable early
// as it may be accessed by GC and exception handling before
// InitAsync stub is called.
// InitSuspendableFunction stub is called.
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariable(
parsed_function().suspend_state_var());
Expand Down
45 changes: 31 additions & 14 deletions runtime/vm/compiler/backend/il.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6901,16 +6901,25 @@ void RawStoreFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}

const Code& ReturnInstr::GetReturnStub(FlowGraphCompiler* compiler) const {
ASSERT(compiler->parsed_function().function().IsCompactAsyncFunction());
if (!value()->Type()->CanBeFuture()) {
return Code::ZoneHandle(compiler->zone(),
compiler->isolate_group()
->object_store()
->return_async_not_future_stub());
}
return Code::ZoneHandle(
compiler->zone(),
compiler->isolate_group()->object_store()->return_async_stub());
const Function& function = compiler->parsed_function().function();
ASSERT(function.IsSuspendableFunction());
if (function.IsCompactAsyncFunction()) {
if (!value()->Type()->CanBeFuture()) {
return Code::ZoneHandle(compiler->zone(),
compiler->isolate_group()
->object_store()
->return_async_not_future_stub());
}
return Code::ZoneHandle(
compiler->zone(),
compiler->isolate_group()->object_store()->return_async_stub());
} else if (function.IsCompactAsyncStarFunction()) {
return Code::ZoneHandle(
compiler->zone(),
compiler->isolate_group()->object_store()->return_async_star_stub());
} else {
UNREACHABLE();
}
}

void NativeReturnInstr::EmitReturnMoves(FlowGraphCompiler* compiler) {
Expand Down Expand Up @@ -7230,10 +7239,12 @@ LocationSummary* Call1ArgStubInstr::MakeLocationSummary(Zone* zone,
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
switch (stub_id_) {
case StubId::kInitAsync:
case StubId::kInitAsyncStar:
locs->set_in(0, Location::RegisterLocation(
InitSuspendableFunctionStubABI::kTypeArgsReg));
break;
case StubId::kAwaitAsync:
case StubId::kAwait:
case StubId::kYieldAsyncStar:
locs->set_in(0, Location::RegisterLocation(SuspendStubABI::kArgumentReg));
break;
}
Expand All @@ -7248,15 +7259,21 @@ void Call1ArgStubInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
case StubId::kInitAsync:
stub = object_store->init_async_stub();
break;
case StubId::kAwaitAsync:
stub = object_store->await_async_stub();
case StubId::kAwait:
stub = object_store->await_stub();
break;
case StubId::kInitAsyncStar:
stub = object_store->init_async_star_stub();
break;
case StubId::kYieldAsyncStar:
stub = object_store->yield_async_star_stub();
break;
}
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
locs(), deopt_id(), env());

#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
if (stub_id_ == StubId::kAwaitAsync) {
if ((stub_id_ == StubId::kAwait) || (stub_id_ == StubId::kYieldAsyncStar)) {
// On x86 (X64 and IA32) mismatch between calls and returns
// significantly regresses performance. So suspend stub
// does not return directly to the caller. Instead, a small
Expand Down
4 changes: 3 additions & 1 deletion runtime/vm/compiler/backend/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -9567,8 +9567,10 @@ class SimdOpInstr : public Definition {
class Call1ArgStubInstr : public TemplateDefinition<1, Throws> {
public:
enum class StubId {
kAwait,
kInitAsync,
kAwaitAsync,
kInitAsyncStar,
kYieldAsyncStar,
};

Call1ArgStubInstr(const InstructionSource& source,
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/il_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}

if (compiler->parsed_function().function().IsCompactAsyncFunction()) {
if (compiler->parsed_function().function().IsSuspendableFunction()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/il_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}

if (compiler->parsed_function().function().IsCompactAsyncFunction()) {
if (compiler->parsed_function().function().IsSuspendableFunction()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/il_ia32.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register result = locs()->in(0).reg();
ASSERT(result == EAX);

if (compiler->parsed_function().function().IsCompactAsyncFunction()) {
if (compiler->parsed_function().function().IsSuspendableFunction()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);
Expand Down
10 changes: 8 additions & 2 deletions runtime/vm/compiler/backend/il_printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1362,8 +1362,14 @@ void Call1ArgStubInstr::PrintOperandsTo(BaseTextBuffer* f) const {
case StubId::kInitAsync:
name = "InitAsync";
break;
case StubId::kAwaitAsync:
name = "AwaitAsync";
case StubId::kAwait:
name = "Await";
break;
case StubId::kInitAsyncStar:
name = "InitAsyncStar";
break;
case StubId::kYieldAsyncStar:
name = "YieldAsyncStar";
break;
}
f->Printf("%s(", name);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/il_riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}

if (compiler->parsed_function().function().IsCompactAsyncFunction()) {
if (compiler->parsed_function().function().IsSuspendableFunction()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/il_x64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}

if (compiler->parsed_function().function().IsCompactAsyncFunction()) {
if (compiler->parsed_function().function().IsSuspendableFunction()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/range_analysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2814,7 +2814,7 @@ void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
case Slot::Kind::kInstance_native_fields_array:
case Slot::Kind::kSuspendState_future:
case Slot::Kind::kSuspendState_function_data:
case Slot::Kind::kSuspendState_then_callback:
case Slot::Kind::kSuspendState_error_callback:
case Slot::Kind::kTypedDataView_typed_data:
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/slot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ bool Slot::IsImmutableLengthSlot() const {
case Slot::Kind::kFunctionType_named_parameter_names:
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
case Slot::Kind::kSuspendState_future:
case Slot::Kind::kSuspendState_function_data:
case Slot::Kind::kSuspendState_then_callback:
case Slot::Kind::kSuspendState_error_callback:
case Slot::Kind::kType_arguments:
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/compiler/backend/slot.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ParsedFunction;
V(ImmutableLinkedHashBase, UntaggedLinkedHashBase, index, \
TypedDataUint32Array, VAR) \
V(Instance, UntaggedInstance, native_fields_array, Dynamic, VAR) \
V(SuspendState, UntaggedSuspendState, future, Dynamic, VAR) \
V(SuspendState, UntaggedSuspendState, function_data, Dynamic, VAR) \
V(SuspendState, UntaggedSuspendState, then_callback, Closure, VAR) \
V(SuspendState, UntaggedSuspendState, error_callback, Closure, VAR) \
V(Type, UntaggedType, arguments, TypeArguments, FINAL) \
Expand Down
Loading

0 comments on commit 4075e8b

Please sign in to comment.