[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:
committed by
Commit Bot
parent
61caeca47a
commit
fb7b291886
@@ -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,
|
||||
|
||||
@@ -9620,7 +9620,8 @@ class SuspendInstr : public TemplateDefinition<1, Throws> {
|
||||
enum class StubId {
|
||||
kAwait,
|
||||
kYieldAsyncStar,
|
||||
kYieldSyncStar,
|
||||
kSuspendSyncStarAtStart,
|
||||
kSuspendSyncStarAtYield,
|
||||
};
|
||||
|
||||
SuspendInstr(const InstructionSource& source,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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") \
|
||||
|
||||
+1
-4
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user