[vm] Runtime option to not use the simulator for simarm64_arm64. TEST=ci Cq-Include-Trybots: luci.dart.try:vm-ffi-mac-debug-simarm64_arm64-try,vm-ffi-mac-release-simarm64_arm64-try Change-Id: Id98d337ce16ba4b434b5c69016f01eec9b85f9d2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/434982 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index e90b911..f7dea8a 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1429,8 +1429,10 @@ __ mov(CSP, SP); #if defined(SIMULATOR_FFI) - __ Emit(Instr::kSimulatorFfiRedirectInstruction); - ASSERT(branch == R9); + if (FLAG_use_simulator) { + __ Emit(Instr::kSimulatorFfiRedirectInstruction); + ASSERT(branch == R9); + } #endif __ blr(branch);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc index 1ee528d..bed546c 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm64.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -417,7 +417,9 @@ #endif #if defined(SIMULATOR_FFI) - __ Emit(Instr::kSimulatorFfiRedirectInstruction); + if (FLAG_use_simulator) { + __ Emit(Instr::kSimulatorFfiRedirectInstruction); + } #endif __ blr(R9); @@ -469,11 +471,6 @@ } void StubCodeCompiler::GenerateFfiCallbackTrampolineStub() { -#if defined(USING_SIMULATOR) && !defined(DART_PRECOMPILER) - // TODO(37299): FFI is not supported in SIMARM64. - // See Simulator::DoDirectedFfiCallback. - __ Breakpoint(); -#else Label body; // R9 is volatile and not used for passing any arguments. @@ -705,7 +702,6 @@ __ Breakpoint(); } #endif -#endif // !defined(HOST_ARCH_ARM64) } void StubCodeCompiler::GenerateDispatchTableNullErrorStub() {
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc index b64a2ee..d435bf1 100644 --- a/runtime/vm/cpu_arm64.cc +++ b/runtime/vm/cpu_arm64.cc
@@ -10,7 +10,6 @@ #include "vm/cpuinfo.h" -#if !defined(USING_SIMULATOR) #if defined(DART_HOST_OS_FUCHSIA) #include <zircon/syscalls.h> #elif defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS) @@ -18,14 +17,19 @@ #elif defined(DART_HOST_OS_WINDOWS) #include <processthreadsapi.h> #endif -#endif namespace dart { void CPU::FlushICache(uword start, uword size) { #if defined(DART_PRECOMPILED_RUNTIME) UNREACHABLE(); -#elif !defined(USING_SIMULATOR) +#else +#if defined(USING_SIMULATOR) + if (FLAG_use_simulator) { + return; + } +#endif + // Nothing to do. Flushing no instructions. if (size == 0) { return;
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc index 17d236c..9be9ccc 100644 --- a/runtime/vm/dart_entry.cc +++ b/runtime/vm/dart_entry.cc
@@ -104,15 +104,20 @@ const uword stub = StubCode::InvokeDartCode().EntryPoint(); #if defined(USING_SIMULATOR) - auto invoke = [&](uword entry_point, uword arguments_descriptor, - uword arguments, Thread* thread) -> uword { - return Simulator::Current()->Call(stub, entry_point, arguments_descriptor, - arguments, - reinterpret_cast<int64_t>(thread)); - }; -#else - auto invoke = reinterpret_cast<invokestub>(stub); + if (FLAG_use_simulator) { + auto invoke = [&](uword entry_point, uword arguments_descriptor, + uword arguments, Thread* thread) -> uword { + return Simulator::Current()->Call(stub, entry_point, arguments_descriptor, + arguments, + reinterpret_cast<int64_t>(thread)); + }; + uword result = + invoke(entry_point, static_cast<uword>(arguments_descriptor.ptr()), + static_cast<uword>(arguments.ptr()), thread); + return static_cast<ObjectPtr>(result); + } #endif + auto invoke = reinterpret_cast<invokestub>(stub); uword result = invoke(entry_point, static_cast<uword>(arguments_descriptor.ptr()), static_cast<uword>(arguments.ptr()), thread);
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index d4ee65c..667fcdd 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc
@@ -627,9 +627,12 @@ // exception object in the kExceptionObjectReg register and the stacktrace // object (may be raw null) in the kStackTraceObjectReg register. - Simulator::Current()->JumpToFrame(program_counter, stack_pointer, - frame_pointer, thread); -#else + if (FLAG_use_simulator) { + Simulator::Current()->JumpToFrame(program_counter, stack_pointer, + frame_pointer, thread); + UNREACHABLE(); + } +#endif // Zero out HWASAN tags from the current stack pointer to the destination. // @@ -677,7 +680,6 @@ } func(program_counter, stack_pointer, frame_pointer, thread); -#endif UNREACHABLE(); }
diff --git a/runtime/vm/ffi_callback_metadata.cc b/runtime/vm/ffi_callback_metadata.cc index 879c967..4e78cd7 100644 --- a/runtime/vm/ffi_callback_metadata.cc +++ b/runtime/vm/ffi_callback_metadata.cc
@@ -29,11 +29,19 @@ ASSERT_LESS_OR_EQUAL(VirtualMemory::PageSize(), kPageSize); #if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64) - const uword code_start = - reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline); - const uword code_end = - reinterpret_cast<uword>(SimulatorFfiCallbackTrampolineEnd); - const uword page_start = code_start & ~(VirtualMemory::PageSize() - 1); + uword code_start, code_end, page_start; + if (FLAG_use_simulator) { + code_start = reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline); + code_end = reinterpret_cast<uword>(SimulatorFfiCallbackTrampolineEnd); + page_start = code_start & ~(VirtualMemory::PageSize() - 1); + } else { + const Code& trampoline_code = StubCode::FfiCallbackTrampoline(); + code_start = trampoline_code.EntryPoint(); + code_end = code_start + trampoline_code.Size(); + page_start = code_start & ~(VirtualMemory::PageSize() - 1); + ASSERT_LESS_OR_EQUAL((code_start - page_start) + trampoline_code.Size(), + RXMappingSize()); + } #else const Code& trampoline_code = StubCode::FfiCallbackTrampoline(); const uword code_start = trampoline_code.EntryPoint(); @@ -50,8 +58,7 @@ offset_of_first_trampoline_in_page_ = code_start - page_start; -#if defined(DART_TARGET_OS_FUCHSIA) || \ - (defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)) +#if defined(DART_TARGET_OS_FUCHSIA) // On Fuchsia we can't currently duplicate pages, so use the first page of // trampolines. Store the stub page's metadata in a separately allocated RW // page. @@ -64,6 +71,17 @@ for (intptr_t i = 0; i < NumCallbackTrampolinesPerPage(); ++i) { AddToFreeListLocked(&metadata_entry[i]); } +#elif defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64) + if (FLAG_use_simulator) { + original_metadata_page_ = VirtualMemory::AllocateAligned( + MappingSize(), MappingAlignment(), /*is_executable=*/false, + /*is_compressed=*/false, "FfiCallbackMetadata::TrampolinePage"); + MetadataEntry* metadata_entry = reinterpret_cast<MetadataEntry*>( + original_metadata_page_->start() + MetadataOffset()); + for (intptr_t i = 0; i < NumCallbackTrampolinesPerPage(); ++i) { + AddToFreeListLocked(&metadata_entry[i]); + } + } #endif // defined(DART_TARGET_OS_FUCHSIA) } @@ -112,12 +130,17 @@ } VirtualMemory* FfiCallbackMetadata::AllocateTrampolinePage() { -#if defined(DART_TARGET_OS_FUCHSIA) || \ - (defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)) +#if defined(DART_TARGET_OS_FUCHSIA) // TODO(https://dartbug.com/52579): Remove. UNREACHABLE(); return nullptr; #else +#if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64) + if (FLAG_use_simulator) { + UNREACHABLE(); + return nullptr; + } +#endif #if defined(DART_HOST_OS_MACOS) && defined(DART_PRECOMPILED_RUNTIME) const bool should_remap_stub_page = true; @@ -413,8 +436,13 @@ reinterpret_cast<MetadataEntry*>(start + MetadataOffset()); const uword index = metadata_entry - metadata_entries; #if defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64) - return reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline) + - index * kNativeCallbackTrampolineSize; + if (FLAG_use_simulator) { + return reinterpret_cast<uword>(SimulatorFfiCallbackTrampoline) + + index * kNativeCallbackTrampolineSize; + } else { + return start + offset_of_first_trampoline_in_page_ + + index * kNativeCallbackTrampolineSize; + } #elif defined(DART_TARGET_OS_FUCHSIA) return StubCode::FfiCallbackTrampoline().EntryPoint() + index * kNativeCallbackTrampolineSize; @@ -426,8 +454,7 @@ FfiCallbackMetadata::MetadataEntry* FfiCallbackMetadata::MetadataEntryOfTrampoline(Trampoline trampoline) const { -#if defined(DART_TARGET_OS_FUCHSIA) || \ - (defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64)) +#if defined(DART_TARGET_OS_FUCHSIA) // On Fuchsia the metadata page is separate to the trampoline page. // TODO(https://dartbug.com/52579): Remove. const uword page_start = @@ -440,6 +467,27 @@ MetadataEntry* metadata_etnry_table = reinterpret_cast<MetadataEntry*>( original_metadata_page_->start() + MetadataOffset()); return metadata_etnry_table + index; +#elif defined(SIMULATOR_FFI) && defined(HOST_ARCH_ARM64) + if (FLAG_use_simulator) { + const uword page_start = + Utils::RoundDown(trampoline - offset_of_first_trampoline_in_page_, + VirtualMemory::PageSize()); + const uword index = + (trampoline - offset_of_first_trampoline_in_page_ - page_start) / + kNativeCallbackTrampolineSize; + ASSERT(index < NumCallbackTrampolinesPerPage()); + MetadataEntry* metadata_etnry_table = reinterpret_cast<MetadataEntry*>( + original_metadata_page_->start() + MetadataOffset()); + return metadata_etnry_table + index; + } else { + const uword start = MappingStart(trampoline); + MetadataEntry* metadata_entries = + reinterpret_cast<MetadataEntry*>(start + MetadataOffset()); + const uword index = + (trampoline - start - offset_of_first_trampoline_in_page_) / + kNativeCallbackTrampolineSize; + return &metadata_entries[index]; + } #else const uword start = MappingStart(trampoline); MetadataEntry* metadata_entries =
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h index d560266..b90b3e1 100644 --- a/runtime/vm/flag_list.h +++ b/runtime/vm/flag_list.h
@@ -249,6 +249,7 @@ "Throw API error on invalid member access through native API. See " \ "entry_point_pragma.md") \ C(branch_coverage, false, false, bool, false, "Enable branch coverage") \ - C(coverage, false, false, bool, true, "Enable coverage") + C(coverage, false, false, bool, true, "Enable coverage") \ + P(use_simulator, bool, true, "Use simulator if available") #endif // RUNTIME_VM_FLAG_LIST_H_
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc index eba30df..ff78062 100644 --- a/runtime/vm/native_entry.cc +++ b/runtime/vm/native_entry.cc
@@ -120,9 +120,11 @@ uword NativeEntry::BootstrapNativeCallWrapperEntry() { uword entry = reinterpret_cast<uword>(DRT_BootstrapNativeCall); #if defined(USING_SIMULATOR) - entry = Simulator::RedirectExternalReference( - entry, Simulator::kNativeCallWrapper, - NativeEntry::kNumCallWrapperArguments); + if (FLAG_use_simulator) { + entry = Simulator::RedirectExternalReference( + entry, Simulator::kNativeCallWrapper, + NativeEntry::kNumCallWrapperArguments); + } #endif return entry; } @@ -164,9 +166,11 @@ uword NativeEntry::NoScopeNativeCallWrapperEntry() { uword entry = reinterpret_cast<uword>(DRT_NoScopeNativeCall); #if defined(USING_SIMULATOR) - entry = Simulator::RedirectExternalReference( - entry, Simulator::kNativeCallWrapper, - NativeEntry::kNumCallWrapperArguments); + if (FLAG_use_simulator) { + entry = Simulator::RedirectExternalReference( + entry, Simulator::kNativeCallWrapper, + NativeEntry::kNumCallWrapperArguments); + } #endif return entry; } @@ -195,9 +199,11 @@ uword NativeEntry::AutoScopeNativeCallWrapperEntry() { uword entry = reinterpret_cast<uword>(DRT_AutoScopeNativeCall); #if defined(USING_SIMULATOR) - entry = Simulator::RedirectExternalReference( - entry, Simulator::kNativeCallWrapper, - NativeEntry::kNumCallWrapperArguments); + if (FLAG_use_simulator) { + entry = Simulator::RedirectExternalReference( + entry, Simulator::kNativeCallWrapper, + NativeEntry::kNumCallWrapperArguments); + } #endif return entry; }
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index 2961c45..cc9c00b 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc
@@ -365,7 +365,7 @@ #if defined(USING_SIMULATOR) const bool use_simulator_stack_bounds = - thread != nullptr && thread->IsExecutingDartCode(); + FLAG_use_simulator && thread != nullptr && thread->IsExecutingDartCode(); if (use_simulator_stack_bounds) { Isolate* isolate = thread->isolate(); ASSERT(isolate != nullptr); @@ -1253,9 +1253,11 @@ // When running in the simulator, the runtime entry function address // (stored as the vm tag) is the address of a redirect function. // Attempt to find the real runtime entry function address and use that. - uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); - if (redirect_vm_tag != 0) { - vm_tag = redirect_vm_tag; + if (FLAG_use_simulator) { + uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); + if (redirect_vm_tag != 0) { + vm_tag = redirect_vm_tag; + } } #endif sample->set_vm_tag(vm_tag); @@ -1388,18 +1390,19 @@ uintptr_t fp = state.fp; uintptr_t pc = state.pc; uintptr_t lr = state.lr; -#if defined(USING_SIMULATOR) - Simulator* simulator = nullptr; -#endif if (in_dart_code) { -// If we're in Dart code, use the Dart stack pointer. + // If we're in Dart code, use the Dart stack pointer. #if defined(USING_SIMULATOR) - simulator = isolate->simulator(); - sp = simulator->get_register(SPREG); - fp = simulator->get_register(FPREG); - pc = simulator->get_pc(); - lr = simulator->get_lr(); + if (FLAG_use_simulator) { + Simulator* simulator = isolate->simulator(); + sp = simulator->get_register(SPREG); + fp = simulator->get_register(FPREG); + pc = simulator->get_pc(); + lr = simulator->get_lr(); + } else { + sp = state.dsp; + } #else sp = state.dsp; #endif
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 306f0e3..88cf909 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc
@@ -124,17 +124,20 @@ // into the runtime system. uword entry = reinterpret_cast<uword>(function()); #if defined(USING_SIMULATOR) - // Redirection to leaf runtime calls supports a maximum of 4 arguments passed - // in registers (maximum 2 double arguments for leaf float runtime calls). - ASSERT(argument_count() >= 0); - ASSERT(!is_leaf() || (!is_float() && (argument_count() <= 4)) || - (argument_count() <= 2)); - Simulator::CallKind call_kind = - is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall - : Simulator::kLeafRuntimeCall) - : Simulator::kRuntimeCall; - entry = - Simulator::RedirectExternalReference(entry, call_kind, argument_count()); + if (FLAG_use_simulator) { + // Redirection to leaf runtime calls supports a maximum of 4 arguments + // passed in registers (maximum 2 double arguments for leaf float runtime + // calls). + ASSERT(argument_count() >= 0); + ASSERT(!is_leaf() || (!is_float() && (argument_count() <= 4)) || + (argument_count() <= 2)); + Simulator::CallKind call_kind = + is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall + : Simulator::kLeafRuntimeCall) + : Simulator::kRuntimeCall; + entry = Simulator::RedirectExternalReference(entry, call_kind, + argument_count()); + } #endif return entry; } @@ -152,7 +155,7 @@ #if defined(USING_SIMULATOR) #define CHECK_SIMULATOR_STACK_OVERFLOW() \ - if (!OSThread::Current()->HasStackHeadroom()) { \ + if (FLAG_use_simulator && !OSThread::Current()->HasStackHeadroom()) { \ Exceptions::ThrowStackOverflow(); \ } #else @@ -3486,16 +3489,17 @@ #endif // !defined(DART_PRECOMPILED_RUNTIME) DEFINE_RUNTIME_ENTRY(InterruptOrStackOverflow, 0) { -#if defined(USING_SIMULATOR) - uword stack_pos = Simulator::Current()->get_sp(); - // If simulator was never called it may return 0 as a value of SPREG. - if (stack_pos == 0) { - // Use any reasonable value which would not be treated - // as stack overflow. - stack_pos = thread->saved_stack_limit(); - } -#else uword stack_pos = OSThread::GetCurrentStackPointer(); +#if defined(USING_SIMULATOR) + if (FLAG_use_simulator) { + stack_pos = Simulator::Current()->get_sp(); + // If simulator was never called it may return 0 as a value of SPREG. + if (stack_pos == 0) { + // Use any reasonable value which would not be treated + // as stack overflow. + stack_pos = thread->saved_stack_limit(); + } + } #endif // Always clear the stack overflow flags. They are meant for this // particular stack overflow runtime call and are not meant to @@ -4381,8 +4385,10 @@ #if defined(DART_DYNAMIC_MODULES) uword entry = reinterpret_cast<uword>(InterpretCall); #if defined(USING_SIMULATOR) - entry = Simulator::RedirectExternalReference(entry, - Simulator::kLeafRuntimeCall, 5); + if (FLAG_use_simulator) { + entry = Simulator::RedirectExternalReference( + entry, Simulator::kLeafRuntimeCall, 5); + } #endif return entry; #else
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 1178afa..07c5646 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc
@@ -533,7 +533,11 @@ ResumeThreadInternal(thread); #if defined(USING_SIMULATOR) - thread->SetStackLimit(Simulator::Current()->overflow_stack_limit()); + if (FLAG_use_simulator) { + thread->SetStackLimit(Simulator::Current()->overflow_stack_limit()); + } else { + thread->SetStackLimit(OSThread::Current()->overflow_stack_limit()); + } #else thread->SetStackLimit(OSThread::Current()->overflow_stack_limit()); #endif @@ -583,7 +587,11 @@ if (Dart::vm_isolate() != nullptr && thread->isolate() != Dart::vm_isolate()) { #if defined(USING_SIMULATOR) - thread->SetStackLimit(Simulator::Current()->overflow_stack_limit()); + if (FLAG_use_simulator) { + thread->SetStackLimit(Simulator::Current()->overflow_stack_limit()); + } else { + thread->SetStackLimit(OSThread::Current()->overflow_stack_limit()); + } #else thread->SetStackLimit(OSThread::Current()->overflow_stack_limit()); #endif
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index b8a6afe..431dbff 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json
@@ -297,7 +297,7 @@ "builder-tag": "ffi" } }, - "vm-(linux|mac|win|android|fuchsia)-(debug|product|release)-(ia32|x64|x64c|arm|arm64|arm64c|simarm|simarm64|simarm64_arm64|simriscv32|simriscv64)": { + "vm-(linux|mac|win|android|fuchsia)-(debug|product|release)-(ia32|x64|x64c|arm|arm64|arm64c|simarm|simarm64|simriscv32|simriscv64)": { "options": {} }, "vm-checked-(linux|mac|win|fuchsia)-(debug|product|release)-(ia32|x64|x64c|arm64|arm64c|simarm|simarm64|simriscv32|simriscv64)": { @@ -348,6 +348,26 @@ "gen-snapshot-format" : "elf" } }, + "vm-linux-(debug|product|release)-simarm64_arm64": { + "options": { + "vm-options": ["--use_simulator=true"], "use-qemu": true + } + }, + "vm-linux-(debug|product|release)-simarm64_arm64-nosim": { + "options": { + "vm-options": ["--use_simulator=false"], "use-qemu": true + } + }, + "vm-mac-(debug|product|release)-simarm64_arm64": { + "options": { + "vm-options": ["--use_simulator=true"] + } + }, + "vm-mac-(debug|product|release)-simarm64_arm64-nosim": { + "options": { + "vm-options": ["--use_simulator=false"] + } + }, "dart2js-(linux|win)-chrome": { "options": { "use-sdk": true @@ -814,6 +834,13 @@ "-nvm-${system}-${mode}-${arch}", "ffi" ] + }, + { + "name": "vm ffi tests", + "arguments": [ + "-nvm-${system}-${mode}-${arch}-nosim", + "ffi" + ] } ] },