| // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 
 | // 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 "vm/globals.h" | 
 | #if defined(TARGET_ARCH_ARM64) | 
 |  | 
 | #include "vm/cpu.h" | 
 | #include "vm/cpu_arm64.h" | 
 |  | 
 | #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) | 
 | #include <libkern/OSCacheControl.h> | 
 | #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) | 
 |   // Nothing to do. Flushing no instructions. | 
 |   if (size == 0) { | 
 |     return; | 
 |   } | 
 |  | 
 | // ARM recommends using the gcc intrinsic __clear_cache on Linux and Android. | 
 | // | 
 | // https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code | 
 | // | 
 | // On iOS we use sys_icache_invalidate from Darwin. See: | 
 | // | 
 | // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html | 
 | #if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS) | 
 |   sys_icache_invalidate(reinterpret_cast<void*>(start), size); | 
 | #elif defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX) | 
 |   char* beg = reinterpret_cast<char*>(start); | 
 |   char* end = reinterpret_cast<char*>(start + size); | 
 |   __builtin___clear_cache(beg, end); | 
 | #elif defined(DART_HOST_OS_FUCHSIA) | 
 |   zx_status_t result = zx_cache_flush(reinterpret_cast<const void*>(start), | 
 |                                       size, ZX_CACHE_FLUSH_INSN); | 
 |   ASSERT(result == ZX_OK); | 
 | #elif defined(DART_HOST_OS_WINDOWS) | 
 |   BOOL result = FlushInstructionCache( | 
 |       GetCurrentProcess(), reinterpret_cast<const void*>(start), size); | 
 |   ASSERT(result != 0); | 
 | #else | 
 | #error FlushICache not implemented for this OS | 
 | #endif | 
 |  | 
 | #endif | 
 | } | 
 |  | 
 | const char* CPU::Id() { | 
 |   return | 
 | #if defined(USING_SIMULATOR) | 
 |       "sim" | 
 | #endif  // !defined(USING_SIMULATOR) | 
 |       "arm64"; | 
 | } | 
 |  | 
 | const char* HostCPUFeatures::hardware_ = nullptr; | 
 | #if defined(DEBUG) | 
 | bool HostCPUFeatures::initialized_ = false; | 
 | #endif | 
 |  | 
 | #if !defined(USING_SIMULATOR) | 
 | void HostCPUFeatures::Init() { | 
 |   CpuInfo::Init(); | 
 |   hardware_ = CpuInfo::GetCpuModel(); | 
 | #if defined(DEBUG) | 
 |   initialized_ = true; | 
 | #endif | 
 | } | 
 |  | 
 | void HostCPUFeatures::Cleanup() { | 
 |   DEBUG_ASSERT(initialized_); | 
 | #if defined(DEBUG) | 
 |   initialized_ = false; | 
 | #endif | 
 |   ASSERT(hardware_ != nullptr); | 
 |   free(const_cast<char*>(hardware_)); | 
 |   hardware_ = nullptr; | 
 |   CpuInfo::Cleanup(); | 
 | } | 
 |  | 
 | #else  // !defined(USING_SIMULATOR) | 
 |  | 
 | void HostCPUFeatures::Init() { | 
 |   CpuInfo::Init(); | 
 |   hardware_ = CpuInfo::GetCpuModel(); | 
 | #if defined(DEBUG) | 
 |   initialized_ = true; | 
 | #endif | 
 | } | 
 |  | 
 | void HostCPUFeatures::Cleanup() { | 
 |   DEBUG_ASSERT(initialized_); | 
 | #if defined(DEBUG) | 
 |   initialized_ = false; | 
 | #endif | 
 |   ASSERT(hardware_ != nullptr); | 
 |   free(const_cast<char*>(hardware_)); | 
 |   hardware_ = nullptr; | 
 |   CpuInfo::Cleanup(); | 
 | } | 
 | #endif  // !defined(USING_SIMULATOR) | 
 |  | 
 | }  // namespace dart | 
 |  | 
 | #endif  // defined TARGET_ARCH_ARM64 |