From: Roland Levillain Date: Mon, 1 Feb 2016 15:23:20 +0000 (+0000) Subject: Ensure instruction cache is flushed in compiler tests with Clang. X-Git-Tag: android-x86-7.1-r1~424^2~74^2^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=324302696c0a93511fef1310d309a54ebfb25a46;p=android-x86%2Fart.git Ensure instruction cache is flushed in compiler tests with Clang. Invoke __builtin___clear_cache with Clang in art::CommonCompilerTest::MakeExecutable. This fixes "Illegal instruction" failures in codegen_test on angler. Factor this logic in a function and use it in art::jit::JitCodeCache::CommitCodeInternal too. Bug: 26786447 Change-Id: I81fa056c8d7c6bf2168c9340deeab82231cb1084 --- diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index afc846387..e4bfac9ee 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -122,16 +122,7 @@ void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_leng int result = mprotect(reinterpret_cast(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); CHECK_EQ(result, 0); - // Flush instruction cache - // Only uses __builtin___clear_cache if GCC >= 4.3.3 -#if GCC_VERSION >= 40303 - __builtin___clear_cache(reinterpret_cast(base), reinterpret_cast(base + len)); -#else - // Only warn if not Intel as Intel doesn't have cache flush instructions. -#if !defined(__i386__) && !defined(__x86_64__) - UNIMPLEMENTED(WARNING) << "cache flush"; -#endif -#endif + FlushInstructionCache(reinterpret_cast(base), reinterpret_cast(base + len)); } void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) { diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index b0e5fdeeb..f325949c6 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -321,8 +321,8 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, code_size); } - __builtin___clear_cache(reinterpret_cast(code_ptr), - reinterpret_cast(code_ptr + code_size)); + FlushInstructionCache(reinterpret_cast(code_ptr), + reinterpret_cast(code_ptr + code_size)); number_of_compilations_++; } // We need to update the entry point in the runnable state for the instrumentation. diff --git a/runtime/utils.h b/runtime/utils.h index 153749eff..c00db11c1 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -388,6 +388,24 @@ int64_t GetFileSizeBytes(const std::string& filename); // Sleep forever and never come back. NO_RETURN void SleepForever(); +inline void FlushInstructionCache(char* begin, char* end) { + // Only use __builtin___clear_cache with Clang or with GCC >= 4.3.0 + // (__builtin___clear_cache was introduced in GCC 4.3.0). +#if defined(__clang__) || GCC_VERSION >= 40300 + __builtin___clear_cache(begin, end); +#else + // Only warn on non-Intel platforms, as x86 and x86-64 do not need + // cache flush instructions, as long as the "code uses the same + // linear address for modifying and fetching the instruction". See + // "Intel(R) 64 and IA-32 Architectures Software Developer's Manual + // Volume 3A: System Programming Guide, Part 1", section 11.6 + // "Self-Modifying Code". +#if !defined(__i386__) && !defined(__x86_64__) + UNIMPLEMENTED(WARNING) << "cache flush"; +#endif +#endif +} + } // namespace art #endif // ART_RUNTIME_UTILS_H_