blob: 8885ee881f6d96913000e46159ef4f2e0cc16a95 [file] [log] [blame]
Nicolas Geoffray2a905b22019-06-06 09:04:07 +01001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_JIT_JIT_MEMORY_REGION_H_
18#define ART_RUNTIME_JIT_JIT_MEMORY_REGION_H_
19
20#include <string>
21
Nicolas Geoffray349845a2019-06-19 13:13:10 +010022#include "arch/instruction_set.h"
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010023#include "base/globals.h"
24#include "base/locks.h"
25#include "base/mem_map.h"
26
27namespace art {
28namespace jit {
29
Nicolas Geoffray2411f492019-06-14 08:54:46 +010030class TestZygoteMemory;
31
Orion Hodson521ff982019-06-18 13:56:28 +010032// Number of bytes represented by a bit in the CodeCacheBitmap. Value is reasonable for all
33// architectures.
34static constexpr int kJitCodeAccountingBytes = 16;
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010035
Nicolas Geoffray349845a2019-06-19 13:13:10 +010036size_t inline GetJitCodeAlignment() {
37 if (kRuntimeISA == InstructionSet::kArm || kRuntimeISA == InstructionSet::kThumb2) {
38 // Some devices with 32-bit ARM kernels need additional JIT code alignment when using dual
39 // view JIT (b/132205399). The alignment returned here coincides with the typical ARM d-cache
40 // line (though the value should be probed ideally). Both the method header and code in the
41 // cache are aligned to this size.
42 return 64;
43 }
44 return GetInstructionSetAlignment(kRuntimeISA);
45}
46
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010047// Represents a memory region for the JIT, where code and data are stored. This class
48// provides allocation and deallocation primitives.
49class JitMemoryRegion {
50 public:
51 JitMemoryRegion()
Nicolas Geoffray9c54e182019-06-18 10:42:52 +010052 : initial_capacity_(0),
53 max_capacity_(0),
54 current_capacity_(0),
55 data_end_(0),
56 exec_end_(0),
57 used_memory_for_code_(0),
58 used_memory_for_data_(0),
59 exec_pages_(),
60 non_exec_pages_(),
61 data_mspace_(nullptr),
62 exec_mspace_(nullptr) {}
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010063
Nicolas Geoffray9c54e182019-06-18 10:42:52 +010064 bool Initialize(size_t initial_capacity,
65 size_t max_capacity,
66 bool rwx_memory_allowed,
67 bool is_zygote,
68 std::string* error_msg)
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010069 REQUIRES(Locks::jit_lock_);
70
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010071 // Try to increase the current capacity of the code cache. Return whether we
72 // succeeded at doing so.
73 bool IncreaseCodeCacheCapacity() REQUIRES(Locks::jit_lock_);
74
75 // Set the footprint limit of the code cache.
76 void SetFootprintLimit(size_t new_footprint) REQUIRES(Locks::jit_lock_);
Nicolas Geoffray349845a2019-06-19 13:13:10 +010077
78 // Copy the code into the region, and allocate an OatQuickMethodHeader.
79 // Callers should not write into the returned memory, as it may be read-only.
80 const uint8_t* AllocateCode(const uint8_t* code,
81 size_t code_size,
82 const uint8_t* stack_map,
83 bool has_should_deoptimize_flag)
84 REQUIRES(Locks::jit_lock_);
85 void FreeCode(const uint8_t* code) REQUIRES(Locks::jit_lock_);
Nicolas Geoffray2a905b22019-06-06 09:04:07 +010086 uint8_t* AllocateData(size_t data_size) REQUIRES(Locks::jit_lock_);
87 void FreeData(uint8_t* data) REQUIRES(Locks::jit_lock_);
88
89 bool HasDualCodeMapping() const {
90 return non_exec_pages_.IsValid();
91 }
92
93 bool HasCodeMapping() const {
94 return exec_pages_.IsValid();
95 }
96
97 bool IsInDataSpace(const void* ptr) const {
98 return data_pages_.HasAddress(ptr);
99 }
100
101 bool IsInExecSpace(const void* ptr) const {
102 return exec_pages_.HasAddress(ptr);
103 }
104
Nicolas Geoffray2a905b22019-06-06 09:04:07 +0100105 const MemMap* GetExecPages() const {
106 return &exec_pages_;
107 }
108
Nicolas Geoffray2a905b22019-06-06 09:04:07 +0100109 void* MoreCore(const void* mspace, intptr_t increment);
110
111 bool OwnsSpace(const void* mspace) const NO_THREAD_SAFETY_ANALYSIS {
112 return mspace == data_mspace_ || mspace == exec_mspace_;
113 }
114
115 size_t GetCurrentCapacity() const REQUIRES(Locks::jit_lock_) {
116 return current_capacity_;
117 }
118
119 size_t GetMaxCapacity() const REQUIRES(Locks::jit_lock_) {
120 return max_capacity_;
121 }
122
123 size_t GetUsedMemoryForCode() const REQUIRES(Locks::jit_lock_) {
124 return used_memory_for_code_;
125 }
126
127 size_t GetUsedMemoryForData() const REQUIRES(Locks::jit_lock_) {
128 return used_memory_for_data_;
129 }
130
131 private:
132 template <typename T>
133 T* TranslateAddress(T* src_ptr, const MemMap& src, const MemMap& dst) {
134 if (!HasDualCodeMapping()) {
135 return src_ptr;
136 }
Nicolas Geoffray349845a2019-06-19 13:13:10 +0100137 CHECK(src.HasAddress(src_ptr)) << reinterpret_cast<const void*>(src_ptr);
138 const uint8_t* const raw_src_ptr = reinterpret_cast<const uint8_t*>(src_ptr);
Nicolas Geoffray2a905b22019-06-06 09:04:07 +0100139 return reinterpret_cast<T*>(raw_src_ptr - src.Begin() + dst.Begin());
140 }
141
Nicolas Geoffray349845a2019-06-19 13:13:10 +0100142 const MemMap* GetUpdatableCodeMapping() const {
143 if (HasDualCodeMapping()) {
144 return &non_exec_pages_;
145 } else if (HasCodeMapping()) {
146 return &exec_pages_;
147 } else {
148 return nullptr;
149 }
150 }
151
152 template <typename T> T* GetExecutableAddress(T* src_ptr) {
153 return TranslateAddress(src_ptr, non_exec_pages_, exec_pages_);
154 }
155
156 template <typename T> T* GetNonExecutableAddress(T* src_ptr) {
157 return TranslateAddress(src_ptr, exec_pages_, non_exec_pages_);
158 }
159
Nicolas Geoffray2411f492019-06-14 08:54:46 +0100160 static int CreateZygoteMemory(size_t capacity, std::string* error_msg);
161 static bool ProtectZygoteMemory(int fd, std::string* error_msg);
162
Nicolas Geoffray2a905b22019-06-06 09:04:07 +0100163 // The initial capacity in bytes this code region starts with.
164 size_t initial_capacity_ GUARDED_BY(Locks::jit_lock_);
165
166 // The maximum capacity in bytes this region can go to.
167 size_t max_capacity_ GUARDED_BY(Locks::jit_lock_);
168
169 // The current capacity in bytes of the region.
170 size_t current_capacity_ GUARDED_BY(Locks::jit_lock_);
171
172 // The current footprint in bytes of the data portion of the region.
173 size_t data_end_ GUARDED_BY(Locks::jit_lock_);
174
175 // The current footprint in bytes of the code portion of the region.
176 size_t exec_end_ GUARDED_BY(Locks::jit_lock_);
177
178 // The size in bytes of used memory for the code portion of the region.
179 size_t used_memory_for_code_ GUARDED_BY(Locks::jit_lock_);
180
181 // The size in bytes of used memory for the data portion of the region.
182 size_t used_memory_for_data_ GUARDED_BY(Locks::jit_lock_);
183
184 // Mem map which holds data (stack maps and profiling info).
185 MemMap data_pages_;
186
187 // Mem map which holds code and has executable permission.
188 MemMap exec_pages_;
189
190 // Mem map which holds code with non executable permission. Only valid for dual view JIT when
191 // this is the non-executable view of code used to write updates.
192 MemMap non_exec_pages_;
193
194 // The opaque mspace for allocating data.
195 void* data_mspace_ GUARDED_BY(Locks::jit_lock_);
196
197 // The opaque mspace for allocating code.
198 void* exec_mspace_ GUARDED_BY(Locks::jit_lock_);
Nicolas Geoffray2411f492019-06-14 08:54:46 +0100199
Nicolas Geoffray349845a2019-06-19 13:13:10 +0100200 friend class ScopedCodeCacheWrite; // For GetUpdatableCodeMapping
Nicolas Geoffray2411f492019-06-14 08:54:46 +0100201 friend class TestZygoteMemory;
Nicolas Geoffray2a905b22019-06-06 09:04:07 +0100202};
203
204} // namespace jit
205} // namespace art
206
207#endif // ART_RUNTIME_JIT_JIT_MEMORY_REGION_H_