7579b1e3c8
This adds initial support for concurrently patching jump table slots. It is needed once different Isolates share code (for the --wasm-shared-code feature). We need to ensure that instructions holding the target address within a jump table slot do not cross cache-line boundaries. To do this, the jump table has been split into consecutive pages. Note that this also adds a stress test for multiple threads hammering at a single slot concurrently. The test is currently limited to the ia32 and the x64 architecture, but will be extended to cover others. The test reliably triggers tearing of the target address on almost every run of the test and hence serves to prevent regressions. R=clemensh@chromium.org TEST=cctest/test-jump-table-assembler BUG=v8:8018 Change-Id: Ife56bbb61ffcae5d8906ca7b8c604b195603707c Reviewed-on: https://chromium-review.googlesource.com/1163664 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#54942}
47 lines
1.6 KiB
C++
47 lines
1.6 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 = v8::internal::AllocatePages(
|
|
address, alloc_size, page_size, v8::PageAllocator::kReadWriteExecute);
|
|
CHECK(result);
|
|
*allocated = alloc_size;
|
|
return static_cast<uint8_t*>(result);
|
|
}
|
|
|
|
static inline void MakeAssemblerBufferExecutable(uint8_t* buffer,
|
|
size_t allocated) {
|
|
bool result = v8::internal::SetPermissions(buffer, allocated,
|
|
v8::PageAllocator::kReadExecute);
|
|
CHECK(result);
|
|
|
|
// Flush the instruction cache as part of making the buffer executable.
|
|
Assembler::FlushICache(buffer, allocated);
|
|
}
|
|
|
|
static inline void MakeAssemblerBufferWritable(uint8_t* buffer,
|
|
size_t allocated) {
|
|
bool result = v8::internal::SetPermissions(buffer, allocated,
|
|
v8::PageAllocator::kReadWrite);
|
|
CHECK(result);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_TEST_COMMON_ASSEMBLER_TESTER_H_
|