Flutter Engine
The Flutter Engine
cpu_arm.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(TARGET_ARCH_ARM)
7
8#include "vm/cpu.h"
9#include "vm/cpu_arm.h"
10
11#include "vm/cpuinfo.h"
12
13#if !defined(TARGET_HOST_MISMATCH)
14#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
15#include <libkern/OSCacheControl.h>
16#elif defined(DART_HOST_OS_WINDOWS)
17#include <processthreadsapi.h>
18#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
19#include <asm/hwcap.h>
20#include <sys/auxv.h>
21#endif
22#endif
23
24// ARM version differences.
25// We support only ARMv7 and variants. We detect the presence of vfp,
26// neon, and integer division instructions. Considering ARMv5TE as the baseline,
27// later versions add the following features/instructions that we use:
28//
29// ARMv6:
30// - PC read offset in store instructions is 8 rather than 12, matching the
31// offset in read instructions,
32// - strex, ldrex, and clrex load/store/clear exclusive instructions,
33// - umaal multiplication instruction,
34// ARMv7:
35// - movw, movt 16-bit immediate load instructions,
36// - mls multiplication instruction,
37// - vmovs, vmovd floating point immediate load instructions.
38//
39// If an aarch64 CPU is detected, we generate ARMv7 code.
40//
41// Where we are missing vfp, we do not unbox doubles, or generate intrinsics for
42// floating point operations. Where we are missing neon, we do not unbox SIMD
43// values, or inline operations on SIMD values. Where we are missing integer
44// division, we do not inline division operations, and we do not generate
45// intrinsics that do division. See the feature tests in flow_graph_optimizer.cc
46// for details.
47
48namespace dart {
49
50DEFINE_FLAG(bool, use_neon, true, "Use neon instructions if supported");
51DEFINE_FLAG(bool,
52 use_integer_division,
53 true,
54 "Use integer division instruction if supported");
55
56#if defined(TARGET_HOST_MISMATCH)
57#if defined(DART_TARGET_OS_ANDROID) || defined(DART_TARGET_OS_MACOS_IOS)
58DEFINE_FLAG(bool, sim_use_hardfp, false, "Use the hardfp ABI.");
59#else
60DEFINE_FLAG(bool, sim_use_hardfp, true, "Use the hardfp ABI.");
61#endif
62#endif
63
64void CPU::FlushICache(uword start, uword size) {
65#if defined(DART_PRECOMPILED_RUNTIME)
67#elif !defined(TARGET_HOST_MISMATCH) && HOST_ARCH_ARM
68 // Nothing to do. Flushing no instructions.
69 if (size == 0) {
70 return;
71 }
72
73// ARM recommends using the gcc intrinsic __clear_cache on Linux, and the
74// library call cacheflush from unistd.h on Android:
75//
76// https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code
77//
78// On iOS we use sys_icache_invalidate from Darwin. See:
79//
80// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
81#if defined(DART_HOST_OS_IOS)
82 sys_icache_invalidate(reinterpret_cast<void*>(start), size);
83#elif defined(DART_HOST_OS_LINUX)
84 char* beg = reinterpret_cast<char*>(start);
85 char* end = reinterpret_cast<char*>(start + size);
86 __builtin___clear_cache(beg, end);
87#elif defined(DART_HOST_OS_ANDROID)
88 cacheflush(start, start + size, 0);
89#elif defined(DART_HOST_OS_WINDOWS)
90 BOOL result = FlushInstructionCache(
91 GetCurrentProcess(), reinterpret_cast<const void*>(start), size);
92 ASSERT(result != 0);
93#else
94#error FlushICache only tested/supported on Linux, Android and iOS
95#endif
96#endif
97}
98
99const char* CPU::Id() {
100 return
101#if defined(TARGET_HOST_MISMATCH)
102 "sim"
103#endif // defined(TARGET_HOST_MISMATCH)
104 "arm";
105}
106
107bool HostCPUFeatures::integer_division_supported_ = false;
108bool HostCPUFeatures::neon_supported_ = false;
109bool HostCPUFeatures::hardfp_supported_ = false;
110const char* HostCPUFeatures::hardware_ = nullptr;
111#if defined(DEBUG)
112bool HostCPUFeatures::initialized_ = false;
113#endif
114
115#if !defined(TARGET_HOST_MISMATCH)
116#if DART_HOST_OS_IOS
118 // TODO(24743): Actually check the CPU features and fail if we're missing
119 // something assumed in a precompiled snapshot.
120 hardware_ = "";
121 // When the VM is targetted to ARMv7, pretend that the CPU is ARMv7 even if
122 // the CPU is actually AArch64.
123 integer_division_supported_ = FLAG_use_integer_division;
124 neon_supported_ = FLAG_use_neon;
125 hardfp_supported_ = false;
126#if defined(DEBUG)
127 initialized_ = true;
128#endif
129}
130#elif DART_HOST_OS_WINDOWS
132 hardware_ = "";
133 integer_division_supported_ = true;
134 neon_supported_ = true;
135 hardfp_supported_ = true;
136#if defined(DEBUG)
137 initialized_ = true;
138#endif
139}
140#else // DART_HOST_OS_IOS
142 // Reading /proc/cpuinfo under QEMU can report the host CPU instead of the
143 // emulated CPU.
144 unsigned long hwcap = getauxval(AT_HWCAP); // NOLINT
145 integer_division_supported_ = (hwcap & HWCAP_IDIVA) != 0;
146 neon_supported_ = (hwcap & HWCAP_NEON) != 0;
147
149 hardware_ = CpuInfo::GetCpuModel();
150
151 // Qualcomm Krait CPUs (QCT APQ8064) in Nexus 4 and 7 incorrectly report that
152 // they lack integer division.
153 if (CpuInfo::FieldContains(kCpuInfoHardware, "QCT APQ8064")) {
154 integer_division_supported_ = true;
155 }
156 // Marvell Armada 370/XP incorrectly reports that it has integer division.
157 if (CpuInfo::FieldContains(kCpuInfoHardware, "Marvell Armada 370/XP")) {
158 integer_division_supported_ = false;
159 }
160 // Some Android ARM emulators claim support for integer division but do not
161 // actually support it.
162 if (CpuInfo::FieldContains(kCpuInfoHardware, "Dummy Virtual Machine")) {
163 integer_division_supported_ = false;
164 }
165
166 // Allow flags to override feature detection.
167 if (!FLAG_use_integer_division) {
168 integer_division_supported_ = false;
169 }
170 if (!FLAG_use_neon) {
171 neon_supported_ = false;
172 }
173
174// Use the cross-compiler's predefined macros to determine whether we should
175// use the hard or soft float ABI.
176#if defined(__ARM_PCS_VFP)
177 hardfp_supported_ = true;
178#else
179 hardfp_supported_ = false;
180#endif
181
182#if defined(DEBUG)
183 initialized_ = true;
184#endif
185}
186#endif // DART_HOST_OS_IOS
187
189 DEBUG_ASSERT(initialized_);
190#if defined(DEBUG)
191 initialized_ = false;
192#endif
193 ASSERT(hardware_ != nullptr);
194 free(const_cast<char*>(hardware_));
195 hardware_ = nullptr;
197}
198
199#else
200
203 hardware_ = CpuInfo::GetCpuModel();
204
205 integer_division_supported_ = FLAG_use_integer_division;
206 neon_supported_ = FLAG_use_neon;
207 hardfp_supported_ = FLAG_sim_use_hardfp;
208#if defined(DEBUG)
209 initialized_ = true;
210#endif
211}
212
214 DEBUG_ASSERT(initialized_);
215#if defined(DEBUG)
216 initialized_ = false;
217#endif
218 ASSERT(hardware_ != nullptr);
219 free(const_cast<char*>(hardware_));
220 hardware_ = nullptr;
222}
223#endif // !defined(TARGET_HOST_MISMATCH)
224
225} // namespace dart
226
227#endif // defined TARGET_ARCH_ARM
#define UNREACHABLE()
Definition: assert.h:248
#define DEBUG_ASSERT(cond)
Definition: assert.h:321
static const char * Id()
static void FlushICache(uword start, uword size)
static void Init()
static const char * GetCpuModel()
Definition: cpuinfo.h:59
static void Cleanup()
static bool FieldContains(CpuInfoIndices idx, const char *search_string)
static void Init()
static void Cleanup()
#define ASSERT(E)
glong glong end
GAsyncResult * result
Definition: dart_vm.cc:33
@ kCpuInfoHardware
Definition: cpuinfo.h:18
uintptr_t uword
Definition: globals.h:501
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
int BOOL
Definition: windows_types.h:37