Commit 566a885d authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nojit] Don't allocate executable memory in jitless mode

This CL disables RX (read and execute) permissions for Code memory
when in jitless mode. All memory that was previously allocated RX
is now read-only.

Bug: v8:7777
Cq-Include-Trybots: luci.v8.try:v8_linux_arm_lite_rel_ng
Change-Id: I52d6ed785d244ec33168a02293c5506d26f36fe8
Reviewed-on: https://chromium-review.googlesource.com/c/1390122
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58692}
parent d31bbfe7
...@@ -1088,14 +1088,6 @@ DEFINE_BOOL(serialization_statistics, false, ...@@ -1088,14 +1088,6 @@ DEFINE_BOOL(serialization_statistics, false,
DEFINE_UINT(serialization_chunk_size, 4096, DEFINE_UINT(serialization_chunk_size, 4096,
"Custom size for serialization chunks") "Custom size for serialization chunks")
// JIT-less V8. Design doc: goo.gl/kRnhVe
#ifdef V8_JITLESS_MODE
DEFINE_BOOL(jitless, false, "Disable runtime allocation of executable memory.")
#else
DEFINE_BOOL_READONLY(jitless, false,
"Disable runtime allocation of executable memory.")
#endif
// Regexp // Regexp
DEFINE_BOOL(regexp_optimization, true, "generate optimized regexp code") DEFINE_BOOL(regexp_optimization, true, "generate optimized regexp code")
DEFINE_BOOL(regexp_mode_modifiers, false, "enable inline flags in regexp.") DEFINE_BOOL(regexp_mode_modifiers, false, "enable inline flags in regexp.")
...@@ -1157,6 +1149,9 @@ DEFINE_SIZE_T(mock_arraybuffer_allocator_limit, 0, ...@@ -1157,6 +1149,9 @@ DEFINE_SIZE_T(mock_arraybuffer_allocator_limit, 0,
#define FLAG FLAG_FULL #define FLAG FLAG_FULL
#endif #endif
DEFINE_BOOL(jitless, V8_LITE_BOOL,
"Disable runtime allocation of executable memory.")
// Enable recompilation of function with optimized code. // Enable recompilation of function with optimized code.
DEFINE_BOOL(opt, !V8_LITE_BOOL, "use adaptive optimizations") DEFINE_BOOL(opt, !V8_LITE_BOOL, "use adaptive optimizations")
......
...@@ -656,12 +656,12 @@ CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* heap) ...@@ -656,12 +656,12 @@ CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* heap)
CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() { CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() {
if (heap_->write_protect_code_memory()) { if (heap_->write_protect_code_memory()) {
heap_->decrement_code_space_memory_modification_scope_depth(); heap_->decrement_code_space_memory_modification_scope_depth();
heap_->code_space()->SetReadAndExecutable(); heap_->code_space()->SetDefaultCodePermissions();
LargePage* page = heap_->code_lo_space()->first_page(); LargePage* page = heap_->code_lo_space()->first_page();
while (page != nullptr) { while (page != nullptr) {
DCHECK(page->IsFlagSet(MemoryChunk::IS_EXECUTABLE)); DCHECK(page->IsFlagSet(MemoryChunk::IS_EXECUTABLE));
CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page)); CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadAndExecutable(); page->SetDefaultCodePermissions();
page = page->next_page(); page = page->next_page();
} }
} }
...@@ -699,7 +699,7 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope( ...@@ -699,7 +699,7 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope(
CodePageMemoryModificationScope::~CodePageMemoryModificationScope() { CodePageMemoryModificationScope::~CodePageMemoryModificationScope() {
if (scope_active_) { if (scope_active_) {
chunk_->SetReadAndExecutable(); chunk_->SetDefaultCodePermissions();
} }
} }
......
...@@ -2042,7 +2042,7 @@ void Heap::ProtectUnprotectedMemoryChunks() { ...@@ -2042,7 +2042,7 @@ void Heap::ProtectUnprotectedMemoryChunks() {
for (auto chunk = unprotected_memory_chunks_.begin(); for (auto chunk = unprotected_memory_chunks_.begin();
chunk != unprotected_memory_chunks_.end(); chunk++) { chunk != unprotected_memory_chunks_.end(); chunk++) {
CHECK(memory_allocator()->IsMemoryChunkExecutable(*chunk)); CHECK(memory_allocator()->IsMemoryChunkExecutable(*chunk));
(*chunk)->SetReadAndExecutable(); (*chunk)->SetDefaultCodePermissions();
} }
unprotected_memory_chunks_.clear(); unprotected_memory_chunks_.clear();
} }
......
...@@ -544,7 +544,10 @@ void MemoryChunk::InitializationMemoryFence() { ...@@ -544,7 +544,10 @@ void MemoryChunk::InitializationMemoryFence() {
#endif #endif
} }
void MemoryChunk::SetReadAndExecutable() { void MemoryChunk::DecrementWriteUnprotectCounterAndMaybeSetPermissions(
PageAllocator::Permission permission) {
DCHECK(permission == PageAllocator::kRead ||
permission == PageAllocator::kReadExecute);
DCHECK(IsFlagSet(MemoryChunk::IS_EXECUTABLE)); DCHECK(IsFlagSet(MemoryChunk::IS_EXECUTABLE));
DCHECK(owner()->identity() == CODE_SPACE || DCHECK(owner()->identity() == CODE_SPACE ||
owner()->identity() == CODE_LO_SPACE); owner()->identity() == CODE_LO_SPACE);
...@@ -565,11 +568,20 @@ void MemoryChunk::SetReadAndExecutable() { ...@@ -565,11 +568,20 @@ void MemoryChunk::SetReadAndExecutable() {
size_t page_size = MemoryAllocator::GetCommitPageSize(); size_t page_size = MemoryAllocator::GetCommitPageSize();
DCHECK(IsAligned(protect_start, page_size)); DCHECK(IsAligned(protect_start, page_size));
size_t protect_size = RoundUp(area_size(), page_size); size_t protect_size = RoundUp(area_size(), page_size);
CHECK(reservation_.SetPermissions(protect_start, protect_size, CHECK(reservation_.SetPermissions(protect_start, protect_size, permission));
PageAllocator::kReadExecute));
} }
} }
void MemoryChunk::SetReadable() {
DecrementWriteUnprotectCounterAndMaybeSetPermissions(PageAllocator::kRead);
}
void MemoryChunk::SetReadAndExecutable() {
DCHECK(!FLAG_jitless);
DecrementWriteUnprotectCounterAndMaybeSetPermissions(
PageAllocator::kReadExecute);
}
void MemoryChunk::SetReadAndWritable() { void MemoryChunk::SetReadAndWritable() {
DCHECK(IsFlagSet(MemoryChunk::IS_EXECUTABLE)); DCHECK(IsFlagSet(MemoryChunk::IS_EXECUTABLE));
DCHECK(owner()->identity() == CODE_SPACE || DCHECK(owner()->identity() == CODE_SPACE ||
...@@ -590,6 +602,15 @@ void MemoryChunk::SetReadAndWritable() { ...@@ -590,6 +602,15 @@ void MemoryChunk::SetReadAndWritable() {
} }
} }
namespace {
PageAllocator::Permission DefaultWritableCodePermissions() {
return FLAG_jitless ? PageAllocator::kReadWrite
: PageAllocator::kReadWriteExecute;
}
} // namespace
MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size, MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
Address area_start, Address area_end, Address area_start, Address area_end,
Executability executable, Space* owner, Executability executable, Space* owner,
...@@ -657,7 +678,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size, ...@@ -657,7 +678,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
DCHECK(IsAligned(area_start, page_size)); DCHECK(IsAligned(area_start, page_size));
size_t area_size = RoundUp(area_end - area_start, page_size); size_t area_size = RoundUp(area_end - area_start, page_size);
CHECK(reservation.SetPermissions(area_start, area_size, CHECK(reservation.SetPermissions(area_start, area_size,
PageAllocator::kReadWriteExecute)); DefaultWritableCodePermissions()));
} }
} }
...@@ -1832,6 +1853,14 @@ void PagedSpace::ReleasePage(Page* page) { ...@@ -1832,6 +1853,14 @@ void PagedSpace::ReleasePage(Page* page) {
heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
} }
void PagedSpace::SetReadable() {
DCHECK(identity() == CODE_SPACE);
for (Page* page : *this) {
CHECK(heap()->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadable();
}
}
void PagedSpace::SetReadAndExecutable() { void PagedSpace::SetReadAndExecutable() {
DCHECK(identity() == CODE_SPACE); DCHECK(identity() == CODE_SPACE);
for (Page* page : *this) { for (Page* page : *this) {
......
...@@ -646,9 +646,18 @@ class MemoryChunk { ...@@ -646,9 +646,18 @@ class MemoryChunk {
// MemoryChunk::synchronized_heap() to simulate the barrier. // MemoryChunk::synchronized_heap() to simulate the barrier.
void InitializationMemoryFence(); void InitializationMemoryFence();
void SetReadable();
void SetReadAndExecutable(); void SetReadAndExecutable();
void SetReadAndWritable(); void SetReadAndWritable();
void SetDefaultCodePermissions() {
if (FLAG_jitless) {
SetReadable();
} else {
SetReadAndExecutable();
}
}
base::ListNode<MemoryChunk>& list_node() { return list_node_; } base::ListNode<MemoryChunk>& list_node() { return list_node_; }
protected: protected:
...@@ -660,6 +669,11 @@ class MemoryChunk { ...@@ -660,6 +669,11 @@ class MemoryChunk {
// Should be called when memory chunk is about to be freed. // Should be called when memory chunk is about to be freed.
void ReleaseAllocatedMemory(); void ReleaseAllocatedMemory();
// Sets the requested page permissions only if the write unprotect counter
// has reached 0.
void DecrementWriteUnprotectCounterAndMaybeSetPermissions(
PageAllocator::Permission permission);
VirtualMemory* reserved_memory() { return &reservation_; } VirtualMemory* reserved_memory() { return &reservation_; }
size_t size_; size_t size_;
...@@ -2208,9 +2222,18 @@ class V8_EXPORT_PRIVATE PagedSpace ...@@ -2208,9 +2222,18 @@ class V8_EXPORT_PRIVATE PagedSpace
// be used for allocation. // be used for allocation.
Page* RemovePageSafe(int size_in_bytes); Page* RemovePageSafe(int size_in_bytes);
void SetReadable();
void SetReadAndExecutable(); void SetReadAndExecutable();
void SetReadAndWritable(); void SetReadAndWritable();
void SetDefaultCodePermissions() {
if (FLAG_jitless) {
SetReadable();
} else {
SetReadAndExecutable();
}
}
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
// Verify integrity of this space. // Verify integrity of this space.
virtual void Verify(Isolate* isolate, ObjectVisitor* visitor); virtual void Verify(Isolate* isolate, ObjectVisitor* visitor);
......
...@@ -14,6 +14,7 @@ namespace internal { ...@@ -14,6 +14,7 @@ namespace internal {
#define __ masm. #define __ masm.
UnaryMathFunction CreateSqrtFunction() { UnaryMathFunction CreateSqrtFunction() {
DCHECK(!FLAG_jitless);
v8::PageAllocator* page_allocator = GetPlatformPageAllocator(); v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0; size_t allocated = 0;
byte* buffer = AllocatePage(page_allocator, byte* buffer = AllocatePage(page_allocator,
......
...@@ -465,7 +465,7 @@ ...@@ -465,7 +465,7 @@
}], }],
############################################################################## ##############################################################################
['lite_mode == True', { ['lite_mode', {
# TODO(8394): First execution events don't work in lite_mode. Enable this after # TODO(8394): First execution events don't work in lite_mode. Enable this after
# we fix the lite mode to track the first execution. # we fix the lite mode to track the first execution.
...@@ -510,6 +510,38 @@ ...@@ -510,6 +510,38 @@
# Slow tests # Slow tests
'test-heap/IncrementalMarkingStepMakesBigProgressWithLargeObjects': [SKIP], 'test-heap/IncrementalMarkingStepMakesBigProgressWithLargeObjects': [SKIP],
}],
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'test-c-wasm-entry/*': [SKIP],
'test-jump-table-assembler/*': [SKIP],
'test-run-wasm-64/*': [SKIP],
'test-run-wasm-asmjs/*': [SKIP],
'test-run-wasm-atomics64/*': [SKIP],
'test-run-wasm-atomics/*': [SKIP],
'test-run-wasm/*': [SKIP],
'test-run-wasm-interpreter/*': [SKIP],
'test-run-wasm-js/*': [SKIP],
'test-run-wasm-module/*': [SKIP],
'test-run-wasm-sign-extension/*': [SKIP],
'test-run-wasm-simd/*': [SKIP],
'test-streaming-compilation/*': [SKIP],
'test-wasm-breakpoints/*': [SKIP],
'test-wasm-codegen/*': [SKIP],
'test-wasm-import-wrapper-cache/*': [SKIP],
'test-wasm-interpreter-entry/*': [SKIP],
'test-wasm-serialization/*': [SKIP],
'test-wasm-shared-engine/*': [SKIP],
'test-wasm-stack/*': [SKIP],
'test-wasm-trap-position/*': [SKIP],
'wasm-run-utils/*': [SKIP],
# Tests that generate code at runtime.
'codegen-tester/*': [SKIP],
'test-assembler-*': [SKIP],
'test-basic-block-profiler/*': [SKIP],
'test-branch-combine/*': [SKIP],
'test-multiple-return/*': [SKIP],
'test-run-calls-to-external-references/*': [SKIP],
}], # lite_mode
] ]
...@@ -123,4 +123,12 @@ ...@@ -123,4 +123,12 @@
'debug/debug-liveedit-restart-frame': [SKIP], 'debug/debug-liveedit-restart-frame': [SKIP],
}], # 'arch == s390 or arch == s390x' }], # 'arch == s390 or arch == s390x'
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'asm-*': [SKIP],
'debug/wasm/*': [SKIP],
'wasm-*': [SKIP],
}], # lite_mode
] ]
...@@ -4,4 +4,11 @@ ...@@ -4,4 +4,11 @@
[ [
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'multi_return/*': [SKIP],
'wasm_compile/*': [SKIP],
}], # lite_mode
] ]
...@@ -34,15 +34,19 @@ ...@@ -34,15 +34,19 @@
'debugger/evaluate-on-call-frame-in-module': [PASS, FAIL], 'debugger/evaluate-on-call-frame-in-module': [PASS, FAIL],
}], # variant != default }], # variant != default
['lite_mode == True', { ##############################################################################
['lite_mode', {
# Lite mode does not allocate feedback vector. # Lite mode does not allocate feedback vector.
'type-profiler/type-profile-start-stop': [SKIP], 'type-profiler/type-profile-start-stop': [SKIP],
'type-profiler/type-profile': [SKIP], 'type-profiler/type-profile': [SKIP],
'type-profiler/type-profile-with-to-string-tag': [SKIP], 'type-profiler/type-profile-with-to-string-tag': [SKIP],
'type-profiler/type-profile-with-classes': [SKIP], 'type-profiler/type-profile-with-classes': [SKIP],
'type-profiler/type-profile-disable': [SKIP] 'type-profiler/type-profile-disable': [SKIP],
}], # 'lite_mode == True'
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'debugger/asm-*': [SKIP],
'debugger/wasm-*': [SKIP],
}], # 'lite_mode'
############################################################################## ##############################################################################
['(arch == arm or arch == arm64) and simulator_run', { ['(arch == arm or arch == arm64) and simulator_run', {
......
...@@ -53,4 +53,11 @@ ...@@ -53,4 +53,11 @@
'fail/list-format*': [SKIP], 'fail/list-format*': [SKIP],
}], # no_i18n == True }], # no_i18n == True
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'fail/wasm-*': [SKIP],
'wasm-*': [SKIP],
}], # lite_mode
] ]
...@@ -326,7 +326,7 @@ ...@@ -326,7 +326,7 @@
}], # 'gc_stress == True' }], # 'gc_stress == True'
############################################################################## ##############################################################################
['lite_mode == True', { ['lite_mode', {
# Skip tests not suitable for lite_mode. # Skip tests not suitable for lite_mode.
# TODO(8596): We cache the templates in the feedback vector. In lite mode # TODO(8596): We cache the templates in the feedback vector. In lite mode
...@@ -352,7 +352,38 @@ ...@@ -352,7 +352,38 @@
'spread-large-string': [SKIP], 'spread-large-string': [SKIP],
'spread-large-array': [SKIP], 'spread-large-array': [SKIP],
}], # 'lite_mode == True' # TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'asm/*': [SKIP],
'regress/wasm/*': [SKIP],
'tools/compiler-trace-flags': [SKIP],
'wasm/*': [SKIP],
# Other tests that use asm / wasm / optimized code.
'compiler/regress-439743': [SKIP],
'regress/regress-599719': [SKIP],
'regress/regress-6196': [SKIP],
'regress/regress-6700': [SKIP],
'regress/regress-670808': [SKIP],
'regress/regress-677685': [SKIP],
'regress/regress-6838-2': [SKIP],
'regress/regress-6838-3': [SKIP],
'regress/regress-799690': [SKIP],
# Tests that generate code at runtime.
'code-comments': [SKIP],
'regress/regress-441099': [SKIP],
'regress/regress-617526': [SKIP],
'regress/regress-618608': [SKIP],
'regress/regress-673241': [SKIP],
'regress/regress-673297': [SKIP],
'regress/regress-7893': [SKIP],
'regress/regress-8377': [SKIP],
'regress/regress-863810': [SKIP],
'regress/regress-crbug-721835': [SKIP],
'regress/regress-crbug-759327': [SKIP],
'regress/regress-crbug-762472': [SKIP],
'regress/regress-crbug-898974': [SKIP],
}], # 'lite_mode'
############################################################################## ##############################################################################
['byteorder == big', { ['byteorder == big', {
...@@ -974,4 +1005,5 @@ ...@@ -974,4 +1005,5 @@
# Unwinding info writer is only supported on x64, arm, and arm64 Linux # Unwinding info writer is only supported on x64, arm, and arm64 Linux
'regress/regress-913844': [SKIP], 'regress/regress-913844': [SKIP],
}], }],
] ]
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
# found in the LICENSE file. # found in the LICENSE file.
[ [
# Only test for default mode x64. # Only test for default mode x64.
['variant != default or arch != x64', { ['variant != default or arch != x64 or lite_mode', {
'*': [SKIP], '*': [SKIP],
}], # variant != default or arch != x64 }], # variant != default or arch != x64 or lite_mode
] ]
...@@ -20,4 +20,11 @@ ...@@ -20,4 +20,11 @@
# Uses too much memory. # Uses too much memory.
'Parameterized/WasmCodeManagerTest.GrowingVsFixedModule/Fixed': [SKIP] 'Parameterized/WasmCodeManagerTest.GrowingVsFixedModule/Fixed': [SKIP]
}], # '(arch == arm or arch == mips) and not simulator_run' }], # '(arch == arm or arch == mips) and not simulator_run'
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'ValueSerializerTestWithWasm.*': [SKIP],
}], # lite_mode
] ]
...@@ -22,4 +22,10 @@ ...@@ -22,4 +22,10 @@
'instance/constructor': [SKIP], 'instance/constructor': [SKIP],
}], # 'arch == s390 or arch == s390x or system == aix' }], # 'arch == s390 or arch == s390x or system == aix'
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'*': [SKIP],
}], # lite_mode
] ]
...@@ -43,4 +43,11 @@ ...@@ -43,4 +43,11 @@
'tests/f64': [SKIP], 'tests/f64': [SKIP],
}], # 'arch == s390 or arch == s390x' }], # 'arch == s390 or arch == s390x'
##############################################################################
['lite_mode', {
# TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
'*': [SKIP],
}], # lite_mode
] ]
...@@ -512,7 +512,7 @@ class SourceProcessor(SourceFileProcessor): ...@@ -512,7 +512,7 @@ class SourceProcessor(SourceFileProcessor):
print "%s does not end with a single new line." % name print "%s does not end with a single new line." % name
result = False result = False
# Sanitize flags for fuzzer. # Sanitize flags for fuzzer.
if "mjsunit" in name or "debugger" in name: if ".js" in name and ("mjsunit" in name or "debugger" in name):
match = FLAGS_LINE.search(contents) match = FLAGS_LINE.search(contents)
if match: if match:
print "%s Flags should use '-' (not '_')" % name print "%s Flags should use '-' (not '_')" % name
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment