1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/wasm/code-space-access.h"
6
7#include "src/wasm/wasm-code-manager.h"
8#include "src/wasm/wasm-engine.h"
9
10namespace v8 {
11namespace internal {
12namespace wasm {
13
14thread_local NativeModule* CodeSpaceWriteScope::current_native_module_ =
15    nullptr;
16
17// TODO(jkummerow): Background threads could permanently stay in
18// writable mode; only the main thread has to switch back and forth.
19CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module)
20    : previous_native_module_(current_native_module_) {
21  DCHECK_NOT_NULL(native_module);
22  if (previous_native_module_ == native_module) return;
23  current_native_module_ = native_module;
24  if (previous_native_module_ == nullptr || SwitchingPerNativeModule()) {
25    SetWritable();
26  }
27}
28
29CodeSpaceWriteScope::~CodeSpaceWriteScope() {
30  if (previous_native_module_ == current_native_module_) return;
31  if (previous_native_module_ == nullptr || SwitchingPerNativeModule()) {
32    SetExecutable();
33  }
34  current_native_module_ = previous_native_module_;
35}
36
37#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT
38
39// Ignoring this warning is considered better than relying on
40// __builtin_available.
41#pragma clang diagnostic push
42#pragma clang diagnostic ignored "-Wunguarded-availability-new"
43// static
44void CodeSpaceWriteScope::SetWritable() {
45  pthread_jit_write_protect_np(0);
46}
47
48// static
49void CodeSpaceWriteScope::SetExecutable() {
50  pthread_jit_write_protect_np(1);
51}
52#pragma clang diagnostic pop
53
54// static
55bool CodeSpaceWriteScope::SwitchingPerNativeModule() { return false; }
56
57#else  // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT
58
59// static
60void CodeSpaceWriteScope::SetWritable() {
61  auto* code_manager = GetWasmCodeManager();
62  if (code_manager->MemoryProtectionKeysEnabled()) {
63    code_manager->SetThreadWritable(true);
64  } else if (FLAG_wasm_write_protect_code_memory) {
65    current_native_module_->AddWriter();
66  }
67}
68
69// static
70void CodeSpaceWriteScope::SetExecutable() {
71  auto* code_manager = GetWasmCodeManager();
72  if (code_manager->MemoryProtectionKeysEnabled()) {
73    DCHECK(FLAG_wasm_memory_protection_keys);
74    code_manager->SetThreadWritable(false);
75  } else if (FLAG_wasm_write_protect_code_memory) {
76    current_native_module_->RemoveWriter();
77  }
78}
79
80// static
81bool CodeSpaceWriteScope::SwitchingPerNativeModule() {
82  return !GetWasmCodeManager()->MemoryProtectionKeysEnabled() &&
83         FLAG_wasm_write_protect_code_memory;
84}
85
86#endif  // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT
87
88}  // namespace wasm
89}  // namespace internal
90}  // namespace v8
91