Skip to content

Commit

Permalink
Merge pull request 'fibers' (dart-lang#10) from fibers into main
Browse files Browse the repository at this point in the history
  • Loading branch information
antonbashir committed Sep 7, 2024
2 parents 57e4644 + 383b321 commit 1c652e1
Show file tree
Hide file tree
Showing 26 changed files with 176 additions and 120 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,7 @@ doc/api/
build/
build-sdk-debug.sh
build-sdk.sh
build-fiber-test.sh
*.exe
*.aot
*.aot
*.S
13 changes: 10 additions & 3 deletions runtime/lib/fiber.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <sys/mman.h>
#include "platform/globals.h"
#include "vm/bootstrap_natives.h"

#include "vm/compiler/runtime_api.h"
#include "vm/native_entry.h"
#include "vm/virtual_memory.h"

namespace dart {
DEFINE_NATIVE_ENTRY(Coroutine_factory, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(Smi, size, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Closure, entry, arguments->NativeArgAt(2));
void* stack = VirtualMemory::Allocate(size.Value() * kWordSize, false, false, "coroutine-stack")->address();
return Coroutine::New((void**)stack + size.Value(), size.Value(), Function::Handle(entry.function()).ptr());
intptr_t stack_size = size.Value();
#if defined(DART_TARGET_OS_WINDOWS)
void** stack_base = (void**)((uintptr_t)VirtualAlloc(nullptr, stack_size * kWordSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
#else
void** stack_base = (void**)((uintptr_t)mmap(nullptr, stack_size * kWordSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
#endif
memset(stack_base, 0, stack_size * kWordSize);
return Coroutine::New(stack_base + stack_size , stack_size, Function::Handle(entry.function()).ptr());
}
} // namespace dart
127 changes: 55 additions & 72 deletions runtime/vm/compiler/backend/il.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8575,29 +8575,23 @@ void CoroutineInitializeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ Drop(1);
__ LeaveFrame();

__ PushRegister(FPREG);
__ PushRegister(PP);
__ PushRegister(CODE_REG);
__ PushRegister(FUNCTION_REG);
__ set_constant_pool_allowed(false);
__ EnterDartFrame(0);

__ EnterFrame(0);
__ LoadFieldFromOffset(SPREG, kCoroutine, Coroutine::stack_base_offset());
__ PushRegister(FPREG);

__ LoadCompressedFieldFromOffset(FUNCTION_REG, kCoroutine, Coroutine::entry_offset());
if (!FLAG_precompiled_mode) {
__ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, Function::code_offset());
__ LoadImmediate(ARGS_DESC_REG, 0);
}
__ Call(compiler::FieldAddress(FUNCTION_REG, Function::entry_point_offset()));
__ PushRegister(kCoroutine);
compiler->EmitCallToStub(StubCode::CoroutineEntry());
__ PopRegister(kCoroutine);

__ PopRegister(FPREG);
__ LeaveFrame();
if (!FLAG_precompiled_mode) __ RestoreCodePointer();
if (FLAG_precompiled_mode) __ movq(PP, compiler::Address(THR, Thread::global_object_pool_offset()));
__ StoreFieldToOffset(SPREG, kCoroutine, Coroutine::stack_base_offset());

__ PopRegister(FUNCTION_REG);
__ PopRegister(CODE_REG);
__ PopRegister(PP);
__ PopRegister(FPREG);
__ LeaveDartFrame();
__ set_constant_pool_allowed(true);

__ EnterFrame(0);
__ PushObject(compiler::NullObject());
Expand All @@ -8606,44 +8600,6 @@ void CoroutineInitializeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ LeaveFrame();
}

LocationSummary* CoroutineTransferInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone) LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(CoroutineTransferABI::kFromCoroutineReg));
locs->set_in(1, Location::RegisterLocation(CoroutineTransferABI::kToCoroutineReg));
return locs;
}

void CoroutineTransferInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register kFromCoroutine = CoroutineTransferABI::kFromCoroutineReg;
const Register kToCoroutine = CoroutineTransferABI::kToCoroutineReg;
const Register kToStackLimit = CoroutineTransferABI::kToStackLimitReg;

#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
SPILLS_LR_TO_FRAME({});
#endif
__ PushRegister(FPREG);
__ PushRegister(PP);
__ PushRegister(CODE_REG);
__ PushRegister(FUNCTION_REG);
__ StoreFieldToOffset(SPREG, kFromCoroutine, Coroutine::stack_base_offset());

__ LoadFieldFromOffset(SPREG, kToCoroutine, Coroutine::stack_base_offset());
__ PopRegister(FUNCTION_REG);
__ PopRegister(CODE_REG);
__ PopRegister(PP);
__ PopRegister(FPREG);

__ LoadFieldFromOffset(kToStackLimit, kToCoroutine, Coroutine::stack_limit_offset());
__ StoreToOffset(kToStackLimit, THR, Thread::stack_limit_offset());
__ StoreToOffset(kToCoroutine, THR, Thread::coroutine_offset());

__ StoreFieldToOffset(kFromCoroutine, kToCoroutine, Coroutine::caller_offset());
}

LocationSummary* CoroutineForkInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
Expand All @@ -8663,41 +8619,68 @@ void CoroutineForkInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
SPILLS_LR_TO_FRAME({});
#endif
__ PushRegister(FPREG);
__ PushRegister(PP);
__ PushRegister(CODE_REG);
__ PushRegister(FUNCTION_REG);
__ StoreFieldToOffset(SPREG, kCallerCoroutine, Coroutine::stack_base_offset());

__ StoreFieldToOffset(kCallerCoroutine, kForkedCoroutine, Coroutine::caller_offset());
__ StoreCompressedIntoObjectNoBarrier(kForkedCoroutine, compiler::FieldAddress(kForkedCoroutine, Coroutine::caller_offset()), kCallerCoroutine);

__ LoadFieldFromOffset(kStackLimit, kForkedCoroutine, Coroutine::stack_limit_offset());
__ StoreToOffset(kStackLimit, THR, Thread::stack_limit_offset());
__ StoreToOffset(kForkedCoroutine, THR, Thread::coroutine_offset());

__ PushRegister(FPREG);
__ StoreFieldToOffset(SPREG, kCallerCoroutine, Coroutine::stack_base_offset());

__ LoadFieldFromOffset(SPREG, kForkedCoroutine, Coroutine::stack_base_offset());

__ PushRegister(kForkedCoroutine);
compiler->EmitCallToStub(StubCode::CoroutineEntry());
__ PopRegister(kForkedCoroutine);

__ LoadCompressedFieldFromOffset(FUNCTION_REG, kForkedCoroutine, Coroutine::entry_offset());
if (!FLAG_precompiled_mode) {
__ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, Function::code_offset());
__ LoadImmediate(ARGS_DESC_REG, 0);
}
__ Call(compiler::FieldAddress(FUNCTION_REG, Function::entry_point_offset()));
__ StoreFieldToOffset(SPREG, kForkedCoroutine, Coroutine::stack_base_offset());
__ LoadCompressedFieldFromOffset(kCallerCoroutine, kForkedCoroutine, Coroutine::caller_offset());

__ PopRegister(kForkedCoroutine);
__ LoadFieldFromOffset(kCallerCoroutine, kForkedCoroutine, Coroutine::caller_offset());
__ LoadFieldFromOffset(SPREG, kCallerCoroutine, Coroutine::stack_base_offset());
__ PopRegister(FUNCTION_REG);
__ PopRegister(CODE_REG);
__ PopRegister(PP);
__ PopRegister(FPREG);
if (!FLAG_precompiled_mode) __ RestoreCodePointer();
if (FLAG_precompiled_mode) __ movq(PP, compiler::Address(THR, Thread::global_object_pool_offset()));

__ LoadFieldFromOffset(kStackLimit, kCallerCoroutine, Coroutine::stack_limit_offset());
__ StoreToOffset(kStackLimit, THR, Thread::stack_limit_offset());
__ StoreToOffset(kCallerCoroutine, THR, Thread::coroutine_offset());
}

LocationSummary* CoroutineTransferInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone) LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(CoroutineTransferABI::kFromCoroutineReg));
locs->set_in(1, Location::RegisterLocation(CoroutineTransferABI::kToCoroutineReg));
return locs;
}

void CoroutineTransferInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register kFromCoroutine = CoroutineTransferABI::kFromCoroutineReg;
const Register kToCoroutine = CoroutineTransferABI::kToCoroutineReg;
const Register kToStackLimit = CoroutineTransferABI::kToStackLimitReg;

#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
SPILLS_LR_TO_FRAME({});
#endif
__ PushRegister(FPREG);
__ StoreFieldToOffset(SPREG, kFromCoroutine, Coroutine::stack_base_offset());

__ LoadFieldFromOffset(SPREG, kToCoroutine, Coroutine::stack_base_offset());
__ PopRegister(FPREG);
if (!FLAG_precompiled_mode) __ RestoreCodePointer();
if (FLAG_precompiled_mode) __ movq(PP, compiler::Address(THR, Thread::global_object_pool_offset()));

__ LoadFieldFromOffset(kToStackLimit, kToCoroutine, Coroutine::stack_limit_offset());
__ StoreToOffset(kToStackLimit, THR, Thread::stack_limit_offset());
__ StoreToOffset(kToCoroutine, THR, Thread::coroutine_offset());

__ StoreCompressedIntoObjectNoBarrier(kToCoroutine, compiler::FieldAddress(kToCoroutine, Coroutine::caller_offset()), kFromCoroutine);
}

Definition* SuspendInstr::Canonicalize(FlowGraph* flow_graph) {
if (stub_id() == StubId::kAwaitWithTypeCheck &&
!operand()->Type()->CanBeFuture()) {
Expand Down
12 changes: 6 additions & 6 deletions runtime/vm/compiler/backend/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -11476,7 +11476,7 @@ class Call1ArgStubInstr : public TemplateDefinition<1, Throws> {
DISALLOW_COPY_AND_ASSIGN(Call1ArgStubInstr);
};

class CoroutineInitializeInstr : public TemplateInstruction<1, NoThrow> {
class CoroutineInitializeInstr : public TemplateInstruction<1, Throws> {
public:
CoroutineInitializeInstr(Value* root, intptr_t deopt_id)
: TemplateInstruction(InstructionSource(TokenPosition::kNoSource),
Expand All @@ -11487,7 +11487,7 @@ class CoroutineInitializeInstr : public TemplateInstruction<1, NoThrow> {
Value* root() const { return inputs_[0]; }
virtual bool CanCallDart() const { return true; }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return true; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return !CompilerState::Current().is_aot(); }
virtual bool HasUnknownSideEffects() const { return true; }
virtual intptr_t NumberOfInputsConsumedBeforeCall() const {
return InputCount();
Expand All @@ -11501,7 +11501,7 @@ class CoroutineInitializeInstr : public TemplateInstruction<1, NoThrow> {
DISALLOW_COPY_AND_ASSIGN(CoroutineInitializeInstr);
};

class CoroutineTransferInstr : public TemplateInstruction<2, NoThrow> {
class CoroutineTransferInstr : public TemplateInstruction<2, Throws> {
public:
CoroutineTransferInstr(Value* from, Value* to, intptr_t deopt_id)
: TemplateInstruction(InstructionSource(TokenPosition::kNoSource),
Expand All @@ -11515,7 +11515,7 @@ class CoroutineTransferInstr : public TemplateInstruction<2, NoThrow> {

virtual bool CanCallDart() const { return true; }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return true; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return !CompilerState::Current().is_aot(); }
virtual bool HasUnknownSideEffects() const { return true; }
virtual intptr_t NumberOfInputsConsumedBeforeCall() const {
return InputCount();
Expand All @@ -11529,7 +11529,7 @@ class CoroutineTransferInstr : public TemplateInstruction<2, NoThrow> {
DISALLOW_COPY_AND_ASSIGN(CoroutineTransferInstr);
};

class CoroutineForkInstr : public TemplateInstruction<2, NoThrow> {
class CoroutineForkInstr : public TemplateInstruction<2, Throws> {
public:
CoroutineForkInstr(Value* from, Value* to, intptr_t deopt_id)
: TemplateInstruction(InstructionSource(TokenPosition::kNoSource),
Expand All @@ -11543,7 +11543,7 @@ class CoroutineForkInstr : public TemplateInstruction<2, NoThrow> {

virtual bool CanCallDart() const { return true; }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return true; }
virtual bool ComputeCanDeoptimizeAfterCall() const { return !CompilerState::Current().is_aot(); }
virtual bool HasUnknownSideEffects() const { return true; }
virtual intptr_t NumberOfInputsConsumedBeforeCall() const {
return InputCount();
Expand Down
20 changes: 10 additions & 10 deletions runtime/vm/compiler/frontend/kernel_to_il.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1921,17 +1921,17 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
body += NullConstant();
break;
}
case MethodRecognizer::kCoroutineTransfer: {
case MethodRecognizer::kCoroutineFork: {
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += LoadLocal(parsed_function_->RawParameterVariable(1));
body += CoroutineTransfer();
body += CoroutineFork();
body += NullConstant();
break;
}
case MethodRecognizer::kCoroutineFork: {
case MethodRecognizer::kCoroutineTransfer: {
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += LoadLocal(parsed_function_->RawParameterVariable(1));
body += CoroutineFork();
body += CoroutineTransfer();
body += NullConstant();
break;
}
Expand Down Expand Up @@ -4771,18 +4771,18 @@ Fragment FlowGraphBuilder::CoroutineInitialize() {
return Fragment(instr);
}

Fragment FlowGraphBuilder::CoroutineTransfer() {
CoroutineTransferInstr* instr =
new (Z) CoroutineTransferInstr(Pop(), Pop(), GetNextDeoptId());
return Fragment(instr);
}

Fragment FlowGraphBuilder::CoroutineFork() {
CoroutineForkInstr* instr =
new (Z) CoroutineForkInstr(Pop(), Pop(), GetNextDeoptId());
return Fragment(instr);
}

Fragment FlowGraphBuilder::CoroutineTransfer() {
CoroutineTransferInstr* instr =
new (Z) CoroutineTransferInstr(Pop(), Pop(), GetNextDeoptId());
return Fragment(instr);
}

Fragment FlowGraphBuilder::Suspend(TokenPosition position,
SuspendInstr::StubId stub_id) {
Value* type_args =
Expand Down
13 changes: 13 additions & 0 deletions runtime/vm/compiler/stub_code_compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3232,6 +3232,19 @@ void StubCodeCompiler::GenerateSubtypeTestCacheSearch(
}
#endif

void StubCodeCompiler::GenerateCoroutineEntryStub() {
const Register kCoroutine = CoroutineEntryABI::kCoroutineReg;
__ EnterStubFrame();
__ LoadCompressedFieldFromOffset(FUNCTION_REG, kCoroutine, Coroutine::entry_offset());
if (!FLAG_precompiled_mode) {
__ LoadCompressedFieldFromOffset(CODE_REG, FUNCTION_REG, Function::code_offset());
__ LoadImmediate(ARGS_DESC_REG, 0);
}
__ Call(compiler::FieldAddress(FUNCTION_REG, Function::entry_point_offset()));
__ LeaveStubFrame();
__ Ret();
}

// See comment on [GenerateSubtypeNTestCacheStub].
void StubCodeCompiler::GenerateSubtype1TestCacheStub() {
GenerateSubtypeNTestCacheStub(assembler, 1);
Expand Down
16 changes: 11 additions & 5 deletions runtime/vm/constants_x64.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,16 +388,22 @@ struct SuspendStubABI {
static constexpr intptr_t kResumePcDistance = 5;
};

struct CoroutineInitializeABI {
struct CoroutineEntryABI {
static constexpr Register kCoroutineReg = RDI;
static constexpr Register kEntryReg = RCX;
};

struct CoroutineInitializeABI {
static constexpr Register kCoroutineReg = CoroutineEntryABI::kCoroutineReg;
static constexpr Register kSourceFrameReg = RBX;
static constexpr Register kStoreFrameReg = RCX;
static constexpr Register kSourceFrameSizeReg = RDX;
static constexpr Register kTempReg = TMP;
};

struct CoroutineForkABI {
static constexpr Register kCallerCoroutineReg = RDI;
static constexpr Register kForkedCoroutineReg = RSI;
static constexpr Register kCallerCoroutineReg = RSI;
static constexpr Register kForkedCoroutineReg = CoroutineEntryABI::kCoroutineReg;
static constexpr Register kStackLimitReg = RDX;
static constexpr Register kForkedEntryReg = RCX;
};

struct CoroutineTransferABI {
Expand Down
2 changes: 2 additions & 0 deletions runtime/vm/exceptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static void BuildStackTrace(StackTraceBuilder* builder) {
if (!frame->IsDartFrame()) {
continue;
}
OS::Print("BuildStackTrace\n");
code = frame->LookupDartCode();
ASSERT(code.ContainsInstructionAt(frame->pc()));
const uword pc_offset = frame->pc() - code.PayloadStart();
Expand Down Expand Up @@ -153,6 +154,7 @@ class ExceptionHandlerFinder : public StackResource {
(handler_pc !=
StubCode::AsyncExceptionHandler().EntryPoint())) {
pc_ = frame->pc();
OS::Print("ExceptionHandlerFinder::find\n");
code_ = &Code::Handle(frame->LookupDartCode());
CatchEntryMovesRefPtr* cached_catch_entry_moves =
catch_entry_moves_cache_->Lookup(pc_);
Expand Down
4 changes: 1 addition & 3 deletions runtime/vm/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2784,7 +2784,6 @@ ObjectPtr Object::Allocate(intptr_t cls_id,
ASSERT(thread->no_safepoint_scope_depth() == 0);
ASSERT(thread->no_callback_scope_depth() == 0);
Heap* heap = thread->heap();

uword address = heap->Allocate(thread, size, space);
if (UNLIKELY(address == 0)) {
// SuspendLongJumpScope during Dart entry ensures that if a longjmp base is
Expand Down Expand Up @@ -26632,8 +26631,6 @@ CodePtr SuspendState::GetCodeObject() const {

CoroutinePtr Coroutine::New(void** stack_base, uintptr_t stack_size, FunctionPtr entry) {
const auto& coroutine = Coroutine::Handle(Object::Allocate<Coroutine>(Heap::kOld));
*(stack_base--) = 0;
NoSafepointScope no_safepoint;
coroutine.StoreNonPointer(&coroutine.untag()->stack_base_, (uword)stack_base);
coroutine.StoreNonPointer(&coroutine.untag()->stack_limit_, (uword)stack_base - stack_size);
coroutine.StoreCompressedPointer(&coroutine.untag()->entry_, entry);
Expand Down Expand Up @@ -28029,3 +28026,4 @@ ArrayPtr RecordShape::GetFieldNames(Thread* thread) const {
}

} // namespace dart

Loading

0 comments on commit 1c652e1

Please sign in to comment.