64d373e51e
This unifies the order of i-cache flushing and permission changing throughout V8. According to cctest/test-icache flushing after the permission change is not robust on some ARM32 and ARM64 devices. There have been observed failures of {TestFlushICacheOfExecutable} on some devices. So far there haven't been any observed failures of the corresponding {TestFlushICacheOfWritable} test. Also the order of flushing before the permission change is the natural order in which the GC currently performs operations. Until we see concrete data substantiating the opposite, the following is the supported and intended order throughout V8: exec -> perm(RW) -> patch -> flush -> perm(RX) -> exec This CL tries to establish said order throughout the codebase. R=ulan@chromium.org TEST=cctest/test-icache BUG=v8:8507,chromium:845877 Change-Id: Ic945082e643aa2d142d222a7913a99816aff4644 Reviewed-on: https://chromium-review.googlesource.com/c/1351025 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#57869}
59 lines
2.3 KiB
C++
59 lines
2.3 KiB
C++
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef V8_TEST_COMMON_ASSEMBLER_TESTER_H_
|
|
#define V8_TEST_COMMON_ASSEMBLER_TESTER_H_
|
|
|
|
#include "src/assembler.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
static inline uint8_t* AllocateAssemblerBuffer(
|
|
size_t* allocated,
|
|
size_t requested = v8::internal::AssemblerBase::kMinimalBufferSize,
|
|
void* address = nullptr) {
|
|
size_t page_size = v8::internal::AllocatePageSize();
|
|
size_t alloc_size = RoundUp(requested, page_size);
|
|
void* result = AllocatePages(GetPlatformPageAllocator(), address, alloc_size,
|
|
page_size, v8::PageAllocator::kReadWrite);
|
|
CHECK(result);
|
|
*allocated = alloc_size;
|
|
return static_cast<uint8_t*>(result);
|
|
}
|
|
|
|
static inline void MakeAssemblerBufferExecutable(uint8_t* buffer,
|
|
size_t allocated) {
|
|
// Flush the instruction cache as part of making the buffer executable.
|
|
// Note: we do this before setting permissions to ReadExecute because on
|
|
// some older ARM kernels there is a bug which causes an access error on
|
|
// cache flush instructions to trigger access error on non-writable memory.
|
|
// See https://bugs.chromium.org/p/v8/issues/detail?id=8157
|
|
Assembler::FlushICache(buffer, allocated);
|
|
|
|
bool result = SetPermissions(GetPlatformPageAllocator(), buffer, allocated,
|
|
v8::PageAllocator::kReadExecute);
|
|
CHECK(result);
|
|
}
|
|
|
|
static inline void MakeAssemblerBufferWritable(uint8_t* buffer,
|
|
size_t allocated) {
|
|
bool result = SetPermissions(GetPlatformPageAllocator(), buffer, allocated,
|
|
v8::PageAllocator::kReadWrite);
|
|
CHECK(result);
|
|
}
|
|
|
|
// TODO(wasm): Only needed for the "test-jump-table-assembler.cc" tests.
|
|
static inline void MakeAssemblerBufferWritableAndExecutable(uint8_t* buffer,
|
|
size_t allocated) {
|
|
bool result = SetPermissions(GetPlatformPageAllocator(), buffer, allocated,
|
|
v8::PageAllocator::kReadWriteExecute);
|
|
CHECK(result);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_TEST_COMMON_ASSEMBLER_TESTER_H_
|