v8/test/common/assembler-tester.h
Michael Starzinger 64d373e51e [heap] Fix i-cache flushing operation order.
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}
2018-11-27 12:16:43 +00:00

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_