From b80e682cbf313691650cc9c45302811deb710aa0 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Thu, 16 Dec 2021 21:33:49 +0000 Subject: [PATCH] [vm] Introduce --target-unknown-cpu option and use it for app-jit snapshots App-jit and core-jit snapshots generated on one machine can be copied to another machine with different CPU family/model, so it is incorrect to use CPU features of the host machine to generate code for snapshots. This change adds --target-unknown-cpu option and enables it when generating app-jit and core-jit snapshots in standalone Dart VM and gen_snapshot. Currently, this flag disables SSE4.1, popcnt and ABM on ia32 and x64, and integer division instruction on ARM. Also, new flag enables testing of roundsd instruction availability at run time on x64 (similarly to AOT). TEST=ci Fixes https://github.com/dart-lang/sdk/issues/47907 Fixes https://github.com/flutter/flutter/issues/94181 Change-Id: Id28448052a21df4bae30b39e62b8532e55d4c901 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/223960 Reviewed-by: Ryan Macnak Commit-Queue: Alexander Markov --- runtime/bin/gen_snapshot.cc | 4 ++++ runtime/bin/main.cc | 6 ++++++ .../vm/compiler/backend/flow_graph_compiler.cc | 16 +++++++--------- runtime/vm/compiler/backend/il_x64.cc | 11 ++++++----- runtime/vm/compiler/frontend/kernel_to_il.cc | 2 +- runtime/vm/cpu_arm.h | 3 ++- runtime/vm/cpu_arm64.h | 1 + runtime/vm/cpu_ia32.h | 6 +++--- runtime/vm/cpu_x64.h | 6 +++--- runtime/vm/flag_list.h | 2 ++ 10 files changed, 35 insertions(+), 22 deletions(-) diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 00cf48285d4..6a2413919c0 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -879,6 +879,10 @@ int main(int argc, char** argv) { if (IsSnapshottingForPrecompilation()) { vm_options.AddArgument("--precompilation"); } else if ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT)) { + // Core-jit and app-jit snapshot can be deployed to another machine, + // so generated code should not depend on the CPU features + // of the system where snapshot was generated. + vm_options.AddArgument("--target-unknown-cpu"); #if !defined(TARGET_ARCH_IA32) vm_options.AddArgument("--link_natives_lazily"); #endif diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 88e7c9e9bc6..d03555a9531 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -1242,6 +1242,12 @@ void main(int argc, char** argv) { #if defined(DART_PRECOMPILED_RUNTIME) vm_options.AddArgument("--precompilation"); #endif + if (Options::gen_snapshot_kind() == kAppJIT) { + // App-jit snapshot can be deployed to another machine, + // so generated code should not depend on the CPU features + // of the system where snapshot was generated. + vm_options.AddArgument("--target-unknown-cpu"); + } // If we need to write an app-jit snapshot or a depfile, then add an exit // hook that writes the snapshot and/or depfile as appropriate. if ((Options::gen_snapshot_kind() == kAppJIT) || diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index 9e560490794..a6d54180856 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -223,16 +223,14 @@ void FlowGraphCompiler::InitCompiler() { BlockEntryInstr* entry = block_order_[i]; for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { Instruction* current = it.Current(); - if (current->IsBranch()) { - current = current->AsBranch()->comparison(); + if (auto* branch = current->AsBranch()) { + current = branch->comparison(); } - // In optimized code, ICData is always set in the instructions. - const ICData* ic_data = NULL; - if (current->IsInstanceCall()) { - ic_data = current->AsInstanceCall()->ic_data(); - } - if ((ic_data != NULL) && (ic_data->NumberOfUsedChecks() == 0)) { - may_reoptimize_ = true; + if (auto* instance_call = current->AsInstanceCall()) { + const ICData* ic_data = instance_call->ic_data(); + if ((ic_data == nullptr) || (ic_data->NumberOfUsedChecks() == 0)) { + may_reoptimize_ = true; + } } } } diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 1e568f2793b..378537a351c 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -5241,11 +5241,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { compiler->AddSlowPathCode(slow_path); if (recognized_kind() != MethodRecognizer::kDoubleToInteger) { - // In JIT mode VM knows target CPU features at compile time - // and can pick more optimal representation for DoubleToDouble - // conversion. In AOT mode we test if roundsd instruction is - // available at run time and fall back to stub if it isn't. - ASSERT(CompilerState::Current().is_aot()); + // In JIT mode without --target-unknown-cpu VM knows target CPU features + // at compile time and can pick more optimal representation + // for DoubleToDouble conversion. In AOT mode and with + // --target-unknown-cpu we test if roundsd instruction is available + // at run time and fall back to stub if it isn't. + ASSERT(CompilerState::Current().is_aot() || FLAG_target_unknown_cpu); if (FLAG_use_slow_path) { __ jmp(slow_path->entry_label()); __ Bind(slow_path->exit_label()); diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 2b7346a014e..07a2898984e 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -940,7 +940,7 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph( case MethodRecognizer::kDoubleFloorToInt: if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; #if defined(TARGET_ARCH_X64) - return CompilerState::Current().is_aot(); + return CompilerState::Current().is_aot() || FLAG_target_unknown_cpu; #elif defined(TARGET_ARCH_ARM64) return true; #else diff --git a/runtime/vm/cpu_arm.h b/runtime/vm/cpu_arm.h index 0729a028309..a6cb9d7675d 100644 --- a/runtime/vm/cpu_arm.h +++ b/runtime/vm/cpu_arm.h @@ -10,6 +10,7 @@ #endif #include "vm/allocation.h" +#include "vm/flags.h" #include "vm/simulator.h" namespace dart { @@ -32,7 +33,7 @@ class HostCPUFeatures : public AllStatic { } static bool integer_division_supported() { DEBUG_ASSERT(initialized_); - return integer_division_supported_; + return integer_division_supported_ && !FLAG_target_unknown_cpu; } static bool neon_supported() { DEBUG_ASSERT(initialized_); diff --git a/runtime/vm/cpu_arm64.h b/runtime/vm/cpu_arm64.h index 5fa7b2e5e89..3e793ef6471 100644 --- a/runtime/vm/cpu_arm64.h +++ b/runtime/vm/cpu_arm64.h @@ -10,6 +10,7 @@ #endif #include "vm/allocation.h" +#include "vm/flags.h" #include "vm/simulator.h" namespace dart { diff --git a/runtime/vm/cpu_ia32.h b/runtime/vm/cpu_ia32.h index f622c1f5e97..0fe8ba02e1c 100644 --- a/runtime/vm/cpu_ia32.h +++ b/runtime/vm/cpu_ia32.h @@ -30,15 +30,15 @@ class HostCPUFeatures : public AllStatic { } static bool sse4_1_supported() { DEBUG_ASSERT(initialized_); - return sse4_1_supported_ && FLAG_use_sse41; + return sse4_1_supported_ && FLAG_use_sse41 && !FLAG_target_unknown_cpu; } static bool popcnt_supported() { DEBUG_ASSERT(initialized_); - return popcnt_supported_; + return popcnt_supported_ && !FLAG_target_unknown_cpu; } static bool abm_supported() { DEBUG_ASSERT(initialized_); - return abm_supported_; + return abm_supported_ && !FLAG_target_unknown_cpu; } private: diff --git a/runtime/vm/cpu_x64.h b/runtime/vm/cpu_x64.h index d0d1a14bbf2..c444be87c2f 100644 --- a/runtime/vm/cpu_x64.h +++ b/runtime/vm/cpu_x64.h @@ -30,15 +30,15 @@ class HostCPUFeatures : public AllStatic { } static bool sse4_1_supported() { DEBUG_ASSERT(initialized_); - return sse4_1_supported_ && FLAG_use_sse41; + return sse4_1_supported_ && FLAG_use_sse41 && !FLAG_target_unknown_cpu; } static bool popcnt_supported() { DEBUG_ASSERT(initialized_); - return popcnt_supported_; + return popcnt_supported_ && !FLAG_target_unknown_cpu; } static bool abm_supported() { DEBUG_ASSERT(initialized_); - return abm_supported_; + return abm_supported_ && !FLAG_target_unknown_cpu; } private: diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h index 8af317ada07..cccfdfb40b8 100644 --- a/runtime/vm/flag_list.h +++ b/runtime/vm/flag_list.h @@ -193,6 +193,8 @@ constexpr bool FLAG_support_il_printer = false; "needed in the precompiled runtime.") \ P(show_invisible_frames, bool, false, \ "Show invisible frames in stack traces.") \ + P(target_unknown_cpu, bool, false, \ + "Generate code for a generic CPU, unknown at compile time") \ D(trace_cha, bool, false, "Trace CHA operations") \ R(trace_field_guards, false, bool, false, "Trace changes in field's cids.") \ D(trace_ic, bool, false, "Trace IC handling") \