[vm] Reduce number of callbacks used in sync* functions

This change introduces separate stubs for suspending sync* functions
at start and at yield/yield*. Suspend stub for yield/yield*
no longer calls Dart callback (in order to make it faster).

Also, ReturnSyncStar stub is removed - sync* functions now directly
return false instead of going through the stub.

TEST=ci

Issue: https://github.com/dart-lang/sdk/issues/48378
Change-Id: Iee9a1f48cab2812cf0f9f0e4e6d8e847547e49f7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250420
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2022-07-12 19:30:12 +00:00 committed by Commit Bot
parent 61caeca47a
commit fb7b291886
26 changed files with 2317 additions and 2442 deletions

View file

@ -6851,10 +6851,6 @@ const Code& ReturnInstr::GetReturnStub(FlowGraphCompiler* compiler) const {
return Code::ZoneHandle(
compiler->zone(),
compiler->isolate_group()->object_store()->return_async_star_stub());
} else if (function.IsSyncGenerator()) {
return Code::ZoneHandle(
compiler->zone(),
compiler->isolate_group()->object_store()->return_sync_star_stub());
} else {
UNREACHABLE();
}
@ -7357,8 +7353,11 @@ void SuspendInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
case StubId::kYieldAsyncStar:
stub = object_store->yield_async_star_stub();
break;
case StubId::kYieldSyncStar:
stub = object_store->yield_sync_star_stub();
case StubId::kSuspendSyncStarAtStart:
stub = object_store->suspend_sync_star_at_start_stub();
break;
case StubId::kSuspendSyncStarAtYield:
stub = object_store->suspend_sync_star_at_yield_stub();
break;
}
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,

View file

@ -9620,7 +9620,8 @@ class SuspendInstr : public TemplateDefinition<1, Throws> {
enum class StubId {
kAwait,
kYieldAsyncStar,
kYieldSyncStar,
kSuspendSyncStarAtStart,
kSuspendSyncStarAtYield,
};
SuspendInstr(const InstructionSource& source,

View file

@ -484,7 +484,8 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}
if (compiler->parsed_function().function().IsSuspendableFunction()) {
if (compiler->parsed_function().function().IsAsyncFunction() ||
compiler->parsed_function().function().IsAsyncGenerator()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);

View file

@ -421,7 +421,8 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}
if (compiler->parsed_function().function().IsSuspendableFunction()) {
if (compiler->parsed_function().function().IsAsyncFunction() ||
compiler->parsed_function().function().IsAsyncGenerator()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);

View file

@ -233,7 +233,8 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register result = locs()->in(0).reg();
ASSERT(result == EAX);
if (compiler->parsed_function().function().IsSuspendableFunction()) {
if (compiler->parsed_function().function().IsAsyncFunction() ||
compiler->parsed_function().function().IsAsyncGenerator()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);

View file

@ -1394,8 +1394,11 @@ void SuspendInstr::PrintOperandsTo(BaseTextBuffer* f) const {
case StubId::kYieldAsyncStar:
name = "YieldAsyncStar";
break;
case StubId::kYieldSyncStar:
name = "YieldSyncStar";
case StubId::kSuspendSyncStarAtStart:
name = "SuspendSyncStarAtStart";
break;
case StubId::kSuspendSyncStarAtYield:
name = "SuspendSyncStarAtYield";
break;
}
f->Printf("%s(", name);

View file

@ -496,7 +496,8 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}
if (compiler->parsed_function().function().IsSuspendableFunction()) {
if (compiler->parsed_function().function().IsAsyncFunction() ||
compiler->parsed_function().function().IsAsyncGenerator()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);

View file

@ -338,7 +338,8 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(result == CallingConventions::kReturnFpuReg);
}
if (compiler->parsed_function().function().IsSuspendableFunction()) {
if (compiler->parsed_function().function().IsAsyncFunction() ||
compiler->parsed_function().function().IsAsyncGenerator()) {
ASSERT(compiler->flow_graph().graph_entry()->NeedsFrame());
const Code& stub = GetReturnStub(compiler);
compiler->EmitJumpToStub(stub);

View file

@ -608,7 +608,7 @@ Fragment StreamingFlowGraphBuilder::InitSuspendableFunction(
body += Drop();
body += NullConstant();
body += B->Suspend(TokenPosition::kNoSource,
SuspendInstr::StubId::kYieldSyncStar);
SuspendInstr::StubId::kSuspendSyncStarAtStart);
body += Drop();
// Clone context if there are any captured parameter variables, so
// each invocation of .iterator would get its own copy of parameters.
@ -686,7 +686,12 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionBody(
}
if (body.is_open()) {
body += NullConstant();
if (parsed_function()->function().IsSyncGenerator()) {
// Return false from sync* function to indicate the end of iteration.
body += Constant(Bool::False());
} else {
body += NullConstant();
}
body += Return(dart_function.end_token_pos());
}
@ -4908,9 +4913,19 @@ Fragment StreamingFlowGraphBuilder::BuildReturnStatement(
bool inside_try_finally = try_finally_block() != nullptr;
Fragment instructions = tag == kNothing
? NullConstant()
: BuildExpression(); // read rest of expression.
Fragment instructions;
if (parsed_function()->function().IsSyncGenerator()) {
// Return false from sync* function to indicate the end of iteration.
instructions += Constant(Bool::False());
if (tag != kNothing) {
ASSERT(PeekTag() == kNullLiteral);
SkipExpression();
}
} else {
instructions +=
(tag == kNothing ? NullConstant()
: BuildExpression()); // read rest of expression.
}
if (instructions.is_open()) {
if (inside_try_finally) {
@ -5265,8 +5280,9 @@ Fragment StreamingFlowGraphBuilder::BuildYieldStatement(
field = IG->object_store()->sync_star_iterator_current();
}
instructions += B->StoreInstanceFieldGuarded(field);
instructions += NullConstant();
instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldSyncStar);
instructions += B->Constant(Bool::True());
instructions +=
B->Suspend(pos, SuspendInstr::StubId::kSuspendSyncStarAtYield);
instructions += Drop();
} else {
UNREACHABLE();

View file

@ -1212,7 +1212,6 @@ class Thread : public AllStatic {
static word return_async_not_future_stub_offset();
static word return_async_star_stub_offset();
static word return_async_stub_offset();
static word return_sync_star_stub_offset();
static word stack_overflow_shared_without_fpu_regs_entry_point_offset();
static word stack_overflow_shared_without_fpu_regs_stub_offset();
static word stack_overflow_shared_with_fpu_regs_entry_point_offset();
@ -1262,8 +1261,7 @@ class Thread : public AllStatic {
static word suspend_state_return_async_star_entry_point_offset();
static word suspend_state_init_sync_star_entry_point_offset();
static word suspend_state_yield_sync_star_entry_point_offset();
static word suspend_state_return_sync_star_entry_point_offset();
static word suspend_state_suspend_sync_star_at_start_entry_point_offset();
static word suspend_state_handle_exception_entry_point_offset();
@ -1300,9 +1298,8 @@ class ObjectStore : public AllStatic {
static word suspend_state_return_async_offset();
static word suspend_state_return_async_not_future_offset();
static word suspend_state_return_async_star_offset();
static word suspend_state_return_sync_star_offset();
static word suspend_state_suspend_sync_star_at_start_offset();
static word suspend_state_yield_async_star_offset();
static word suspend_state_yield_sync_star_offset();
};
class Isolate : public AllStatic {

File diff suppressed because it is too large Load diff

View file

@ -185,9 +185,8 @@
FIELD(ObjectStore, suspend_state_return_async_offset) \
FIELD(ObjectStore, suspend_state_return_async_not_future_offset) \
FIELD(ObjectStore, suspend_state_return_async_star_offset) \
FIELD(ObjectStore, suspend_state_return_sync_star_offset) \
FIELD(ObjectStore, suspend_state_suspend_sync_star_at_start_offset) \
FIELD(ObjectStore, suspend_state_yield_async_star_offset) \
FIELD(ObjectStore, suspend_state_yield_sync_star_offset) \
FIELD(OneByteString, data_offset) \
FIELD(PointerBase, data_offset) \
FIELD(Pointer, type_arguments_offset) \
@ -281,7 +280,6 @@
FIELD(Thread, return_async_not_future_stub_offset) \
FIELD(Thread, return_async_star_stub_offset) \
FIELD(Thread, return_async_stub_offset) \
FIELD(Thread, return_sync_star_stub_offset) \
\
FIELD(Thread, object_null_offset) \
FIELD(Thread, predefined_symbols_address_offset) \
@ -307,8 +305,7 @@
FIELD(Thread, suspend_state_yield_async_star_entry_point_offset) \
FIELD(Thread, suspend_state_return_async_star_entry_point_offset) \
FIELD(Thread, suspend_state_init_sync_star_entry_point_offset) \
FIELD(Thread, suspend_state_yield_sync_star_entry_point_offset) \
FIELD(Thread, suspend_state_return_sync_star_entry_point_offset) \
FIELD(Thread, suspend_state_suspend_sync_star_at_start_entry_point_offset) \
FIELD(Thread, suspend_state_handle_exception_entry_point_offset) \
FIELD(Thread, top_exit_frame_info_offset) \
FIELD(Thread, top_offset) \

View file

@ -1379,6 +1379,7 @@ static void GenerateAllocateSuspendState(Assembler* assembler,
void StubCodeCompiler::GenerateSuspendStub(
Assembler* assembler,
bool call_suspend_function,
intptr_t suspend_entry_point_offset_in_thread,
intptr_t suspend_function_offset_in_object_store) {
const Register kArgument = SuspendStubABI::kArgumentReg;
@ -1516,17 +1517,28 @@ void StubCodeCompiler::GenerateSuspendStub(
}
#endif
// Push arguments for suspend Dart function.
__ PushRegistersInOrder({kSuspendState, kArgument});
if (call_suspend_function) {
// Push arguments for suspend Dart function early to preserve them
// across write barrier.
__ PushRegistersInOrder({kSuspendState, kArgument});
}
// Write barrier.
__ BranchIfBit(kSuspendState, target::ObjectAlignment::kNewObjectBitPosition,
ZERO, &old_gen_object);
__ Bind(&call_dart);
__ Comment("Call suspend Dart function");
CallDartCoreLibraryFunction(assembler, suspend_entry_point_offset_in_thread,
suspend_function_offset_in_object_store);
if (call_suspend_function) {
__ Comment("Call suspend Dart function");
CallDartCoreLibraryFunction(assembler, suspend_entry_point_offset_in_thread,
suspend_function_offset_in_object_store);
} else {
// SuspendStub returns either the result of Dart callback,
// or SuspendStub argument (if Dart callback is not used).
// The latter is used by yield/yield* in sync* functions
// to indicate that iteration should be continued.
__ MoveRegister(CallingConventions::kReturnReg, kArgument);
}
__ LeaveStubFrame();
@ -1585,6 +1597,11 @@ void StubCodeCompiler::GenerateSuspendStub(
__ Bind(&old_gen_object);
__ Comment("Old gen SuspendState slow case");
if (!call_suspend_function) {
// Save kArgument which contains the return value
// if suspend function is not called.
__ PushRegister(kArgument);
}
{
#if defined(TARGET_ARCH_IA32)
LeafRuntimeScope rt(assembler, /*frame_size=*/2 * target::kWordSize,
@ -1599,11 +1616,15 @@ void StubCodeCompiler::GenerateSuspendStub(
#endif
rt.Call(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);
}
if (!call_suspend_function) {
__ PopRegister(kArgument);
}
__ Jump(&call_dart);
}
void StubCodeCompiler::GenerateAwaitStub(Assembler* assembler) {
GenerateSuspendStub(assembler,
/*call_suspend_function=*/true,
target::Thread::suspend_state_await_entry_point_offset(),
target::ObjectStore::suspend_state_await_offset());
}
@ -1611,15 +1632,25 @@ void StubCodeCompiler::GenerateAwaitStub(Assembler* assembler) {
void StubCodeCompiler::GenerateYieldAsyncStarStub(Assembler* assembler) {
GenerateSuspendStub(
assembler,
/*call_suspend_function=*/true,
target::Thread::suspend_state_yield_async_star_entry_point_offset(),
target::ObjectStore::suspend_state_yield_async_star_offset());
}
void StubCodeCompiler::GenerateYieldSyncStarStub(Assembler* assembler) {
void StubCodeCompiler::GenerateSuspendSyncStarAtStartStub(
Assembler* assembler) {
GenerateSuspendStub(
assembler,
target::Thread::suspend_state_yield_sync_star_entry_point_offset(),
target::ObjectStore::suspend_state_yield_sync_star_offset());
/*call_suspend_function=*/true,
target::Thread::
suspend_state_suspend_sync_star_at_start_entry_point_offset(),
target::ObjectStore::suspend_state_suspend_sync_star_at_start_offset());
}
void StubCodeCompiler::GenerateSuspendSyncStarAtYieldStub(
Assembler* assembler) {
GenerateSuspendStub(assembler,
/*call_suspend_function=*/false, -1, -1);
}
void StubCodeCompiler::GenerateInitSuspendableFunctionStub(
@ -1901,14 +1932,6 @@ void StubCodeCompiler::GenerateReturnAsyncStarStub(Assembler* assembler) {
target::Thread::return_async_star_stub_offset());
}
void StubCodeCompiler::GenerateReturnSyncStarStub(Assembler* assembler) {
GenerateReturnStub(
assembler,
target::Thread::suspend_state_return_sync_star_entry_point_offset(),
target::ObjectStore::suspend_state_return_sync_star_offset(),
target::Thread::return_sync_star_stub_offset());
}
void StubCodeCompiler::GenerateAsyncExceptionHandlerStub(Assembler* assembler) {
const Register kSuspendState = AsyncExceptionHandlerStubABI::kSuspendStateReg;
ASSERT(kSuspendState != kExceptionObjectReg);

View file

@ -201,6 +201,7 @@ class StubCodeCompiler : public AllStatic {
static void GenerateSuspendStub(
Assembler* assembler,
bool call_suspend_function,
intptr_t suspend_entry_point_offset_in_thread,
intptr_t suspend_function_offset_in_object_store);
static void GenerateInitSuspendableFunctionStub(

View file

@ -533,7 +533,8 @@ struct DoubleToIntegerStubABI {
static const Register kResultReg = R0;
};
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub, YieldSyncStarStub).
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub,
// SuspendSyncStarAtStartStub, SuspendSyncStarAtYieldStub).
struct SuspendStubABI {
static const Register kArgumentReg = R0;
static const Register kTempReg = R1;
@ -567,7 +568,7 @@ struct ResumeStubABI {
};
// ABI for ReturnStub (ReturnAsyncStub, ReturnAsyncNotFutureStub,
// ReturnAsyncStarStub, ReturnSyncStarStub).
// ReturnAsyncStarStub).
struct ReturnStubABI {
static const Register kSuspendStateReg = R2;
};

View file

@ -367,7 +367,8 @@ struct DoubleToIntegerStubABI {
static const Register kResultReg = R0;
};
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub, YieldSyncStarStub).
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub,
// SuspendSyncStarAtStartStub, SuspendSyncStarAtYieldStub).
struct SuspendStubABI {
static const Register kArgumentReg = R0;
static const Register kTempReg = R1;
@ -401,7 +402,7 @@ struct ResumeStubABI {
};
// ABI for ReturnStub (ReturnAsyncStub, ReturnAsyncNotFutureStub,
// ReturnAsyncStarStub, ReturnSyncStarStub).
// ReturnAsyncStarStub).
struct ReturnStubABI {
static const Register kSuspendStateReg = R2;
};

View file

@ -263,7 +263,8 @@ struct DoubleToIntegerStubABI {
static const Register kResultReg = EAX;
};
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub, YieldSyncStarStub).
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub,
// SuspendSyncStarAtStartStub, SuspendSyncStarAtYieldStub).
struct SuspendStubABI {
static const Register kArgumentReg = EAX;
static const Register kTempReg = EDX;
@ -306,7 +307,7 @@ struct ResumeStubABI {
};
// ABI for ReturnStub (ReturnAsyncStub, ReturnAsyncNotFutureStub,
// ReturnAsyncStarStub, ReturnSyncStarStub).
// ReturnAsyncStarStub).
struct ReturnStubABI {
static const Register kSuspendStateReg = EBX;
};

View file

@ -377,7 +377,8 @@ struct DoubleToIntegerStubABI {
static constexpr Register kResultReg = A0;
};
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub, YieldSyncStarStub).
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub,
// SuspendSyncStarAtStartStub, SuspendSyncStarAtYieldStub).
struct SuspendStubABI {
static const Register kArgumentReg = A0;
static const Register kTempReg = T0;
@ -411,7 +412,7 @@ struct ResumeStubABI {
};
// ABI for ReturnStub (ReturnAsyncStub, ReturnAsyncNotFutureStub,
// ReturnAsyncStarStub, ReturnSyncStarStub).
// ReturnAsyncStarStub).
struct ReturnStubABI {
static const Register kSuspendStateReg = T1;
};

View file

@ -338,7 +338,8 @@ struct DoubleToIntegerStubABI {
static const Register kResultReg = RAX;
};
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub, YieldSyncStarStub).
// ABI for SuspendStub (AwaitStub, YieldAsyncStarStub,
// SuspendSyncStarAtStartStub, SuspendSyncStarAtYieldStub).
struct SuspendStubABI {
static const Register kArgumentReg = RAX;
static const Register kTempReg = RDX;
@ -377,7 +378,7 @@ struct ResumeStubABI {
};
// ABI for ReturnStub (ReturnAsyncStub, ReturnAsyncNotFutureStub,
// ReturnAsyncStarStub, ReturnSyncStarStub).
// ReturnAsyncStarStub).
struct ReturnStubABI {
static const Register kSuspendStateReg = RBX;
};

View file

@ -324,13 +324,9 @@ void ObjectStore::InitKnownObjects() {
ASSERT(!function.IsNull());
set_suspend_state_init_sync_star(function);
function = cls.LookupFunctionAllowPrivate(Symbols::_yieldSyncStar());
function = cls.LookupFunctionAllowPrivate(Symbols::_suspendSyncStarAtStart());
ASSERT(!function.IsNull());
set_suspend_state_yield_sync_star(function);
function = cls.LookupFunctionAllowPrivate(Symbols::_returnSyncStar());
ASSERT(!function.IsNull());
set_suspend_state_return_sync_star(function);
set_suspend_state_suspend_sync_star_at_start(function);
function = cls.LookupFunctionAllowPrivate(Symbols::_handleException());
ASSERT(!function.IsNull());
@ -339,11 +335,16 @@ void ObjectStore::InitKnownObjects() {
cls = async_lib.LookupClassAllowPrivate(Symbols::_SyncStarIterator());
ASSERT(!cls.IsNull());
RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null());
set_sync_star_iterator_class(cls);
field = cls.LookupFieldAllowPrivate(Symbols::_current());
ASSERT(!field.IsNull());
set_sync_star_iterator_current(field);
field = cls.LookupFieldAllowPrivate(Symbols::_state());
ASSERT(!field.IsNull());
set_sync_star_iterator_state(field);
field = cls.LookupFieldAllowPrivate(Symbols::_yieldStarIterable());
ASSERT(!field.IsNull());
set_sync_star_iterator_yield_star_iterable(field);

View file

@ -175,13 +175,14 @@ class ObjectPointerVisitor;
RW(Function, suspend_state_yield_async_star) \
RW(Function, suspend_state_return_async_star) \
RW(Function, suspend_state_init_sync_star) \
RW(Function, suspend_state_yield_sync_star) \
RW(Function, suspend_state_return_sync_star) \
RW(Function, suspend_state_suspend_sync_star_at_start) \
RW(Function, suspend_state_handle_exception) \
RW(Class, async_star_stream_controller) \
RW(Class, stream_class) \
RW(Class, sync_star_iterator_class) \
RW(Field, async_star_stream_controller_async_star_body) \
RW(Field, sync_star_iterator_current) \
RW(Field, sync_star_iterator_state) \
RW(Field, sync_star_iterator_yield_star_iterable) \
ARW_RELAXED(Smi, future_timeout_future_index) \
ARW_RELAXED(Smi, future_wait_future_index) \
@ -263,8 +264,8 @@ class ObjectPointerVisitor;
RW(Code, yield_async_star_stub) \
RW(Code, return_async_star_stub) \
RW(Code, init_sync_star_stub) \
RW(Code, yield_sync_star_stub) \
RW(Code, return_sync_star_stub) \
RW(Code, suspend_sync_star_at_start_stub) \
RW(Code, suspend_sync_star_at_yield_stub) \
RW(Array, dispatch_table_code_entries) \
RW(GrowableObjectArray, instructions_tables) \
RW(Array, obfuscation_map) \
@ -351,8 +352,8 @@ class ObjectPointerVisitor;
DO(yield_async_star_stub, YieldAsyncStar) \
DO(return_async_star_stub, ReturnAsyncStar) \
DO(init_sync_star_stub, InitSyncStar) \
DO(yield_sync_star_stub, YieldSyncStar) \
DO(return_sync_star_stub, ReturnSyncStar) \
DO(suspend_sync_star_at_start_stub, SuspendSyncStarAtStart) \
DO(suspend_sync_star_at_yield_stub, SuspendSyncStarAtYield) \
DO(instance_of_stub, InstanceOf)
#define ISOLATE_OBJECT_STORE_FIELD_LIST(R_, RW) \

View file

@ -737,6 +737,13 @@ DEFINE_RUNTIME_ENTRY(AllocateSuspendState, 2) {
}
result = SuspendState::New(frame_size, function_data,
SpaceForRuntimeAllocation());
if (function_data.GetClassId() ==
Class::Handle(zone, object_store->sync_star_iterator_class()).id()) {
// Refresh _SyncStarIterator._state with the new SuspendState object.
function_data.SetField(
Field::Handle(zone, object_store->sync_star_iterator_state()),
result);
}
} else {
result = SuspendState::New(frame_size, Instance::Cast(previous_state),
SpaceForRuntimeAllocation());

View file

@ -159,8 +159,8 @@ namespace dart {
V(YieldAsyncStar) \
V(ReturnAsyncStar) \
V(InitSyncStar) \
V(YieldSyncStar) \
V(ReturnSyncStar) \
V(SuspendSyncStarAtStart) \
V(SuspendSyncStarAtYield) \
V(AsyncExceptionHandler) \
V(CloneSuspendState) \
V(UnknownDartCode)

View file

@ -446,6 +446,7 @@ class ObjectPointerVisitor;
V(_stackTrace, "_stackTrace") \
V(_state, "_state") \
V(_stateData, "_stateData") \
V(_suspendSyncStarAtStart, "_suspendSyncStarAtStart") \
V(_toString, "_toString") \
V(_varData, "_varData") \
V(_wordCharacterMap, "_wordCharacterMap") \

View file

@ -138,8 +138,6 @@ class Thread;
StubCode::ReturnAsyncNotFuture().ptr(), nullptr) \
V(CodePtr, return_async_star_stub_, StubCode::ReturnAsyncStar().ptr(), \
nullptr) \
V(CodePtr, return_sync_star_stub_, StubCode::ReturnSyncStar().ptr(), \
nullptr) \
V(CodePtr, stack_overflow_shared_without_fpu_regs_stub_, \
StubCode::StackOverflowSharedWithoutFPURegs().ptr(), nullptr) \
V(CodePtr, stack_overflow_shared_with_fpu_regs_stub_, \
@ -186,8 +184,7 @@ class Thread;
V(suspend_state_yield_async_star) \
V(suspend_state_return_async_star) \
V(suspend_state_init_sync_star) \
V(suspend_state_yield_sync_star) \
V(suspend_state_return_sync_star) \
V(suspend_state_suspend_sync_star_at_start) \
V(suspend_state_handle_exception)
// This assertion marks places which assume that boolean false immediate

View file

@ -475,24 +475,11 @@ class _SuspendState {
@pragma("vm:entry-point", "call")
@pragma("vm:invisible")
Object? _yieldSyncStar(Object? object) {
if (_trace) print('_yieldSyncStar($object)');
Object? _suspendSyncStarAtStart(Object? object) {
if (_trace) print('_suspendSyncStarAtStart($object)');
final data = _functionData;
if (data is _SyncStarIterable) {
data._stateAtStart = this;
return data;
} else {
// Update state in the iterator in case SuspendState was reallocated.
unsafeCast<_SyncStarIterator>(data)._state = this;
}
return true;
}
@pragma("vm:entry-point", "call")
@pragma("vm:invisible")
static bool _returnSyncStar(Object suspendState, Object? returnValue) {
if (_trace) print('_returnSyncStar');
return false;
unsafeCast<_SyncStarIterable>(data)._stateAtStart = this;
return data;
}
@pragma("vm:recognized", "other")
@ -603,8 +590,8 @@ class _SyncStarIterator<T> implements Iterator<T> {
try {
// Resume current sync* method in order to move to the next value.
final bool hasMore =
_state!._resume(null, pendingException, pendingStackTrace) as bool;
final bool hasMore = unsafeCast<bool>(unsafeCast<_SuspendState>(_state)
._resume(null, pendingException, pendingStackTrace));
pendingException = null;
pendingStackTrace = null;
if (!hasMore) {