8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_CODE_AOTCODECACHE_HPP
26 #define SHARE_CODE_AOTCODECACHE_HPP
27
28 #include "runtime/stubInfo.hpp"
29
30 /*
31 * AOT Code Cache collects code from Code Cache and corresponding metadata
32 * during application training run.
33 * In following "production" runs this code and data can be loaded into
34 * Code Cache skipping its generation.
35 */
36
37 class CodeBuffer;
38 class RelocIterator;
39 class AOTCodeCache;
40 class AdapterBlob;
41 class ExceptionBlob;
42 class ImmutableOopMapSet;
43 class AsmRemarks;
44 class DbgStrings;
45
46 enum class vmIntrinsicID : int;
47 enum CompLevel : signed char;
48
49 #define DO_AOTCODEENTRY_KIND(Fn) \
50 Fn(None) \
51 Fn(Adapter) \
52 Fn(SharedBlob) \
53 Fn(C1Blob) \
54 Fn(C2Blob) \
55
56 // Descriptor of AOT Code Cache's entry
57 class AOTCodeEntry {
58 public:
59 enum Kind : s1 {
60 #define DECL_KIND_ENUM(kind) kind,
61 DO_AOTCODEENTRY_KIND(DECL_KIND_ENUM)
62 #undef DECL_KIND_ENUM
63 Kind_count
64 };
65
66 private:
67 AOTCodeEntry* _next;
68 Kind _kind;
69 uint _id; // Adapter's id, vmIntrinsic::ID for stub or name's hash for nmethod
70 uint _offset; // Offset to entry
71 uint _size; // Entry size
72 uint _name_offset; // Code blob name
73 uint _name_size;
74 uint _blob_offset; // Start of code in cache
75 bool _has_oop_maps;
76 address _dumptime_content_start_addr; // CodeBlob::content_begin() at dump time; used for applying relocations
77
78 public:
79 AOTCodeEntry(Kind kind, uint id,
80 uint offset, uint size,
81 uint name_offset, uint name_size,
82 uint blob_offset, bool has_oop_maps,
83 address dumptime_content_start_addr) {
84 _next = nullptr;
85 _kind = kind;
86 _id = id;
87 _offset = offset;
88 _size = size;
89 _name_offset = name_offset;
90 _name_size = name_size;
91 _blob_offset = blob_offset;
92 _has_oop_maps = has_oop_maps;
93 _dumptime_content_start_addr = dumptime_content_start_addr;
94 }
95 void* operator new(size_t x, AOTCodeCache* cache);
96 // Delete is a NOP
97 void operator delete( void *ptr ) {}
98
99 AOTCodeEntry* next() const { return _next; }
100 void set_next(AOTCodeEntry* next) { _next = next; }
101
102 Kind kind() const { return _kind; }
103 uint id() const { return _id; }
104
105 uint offset() const { return _offset; }
106 void set_offset(uint off) { _offset = off; }
107
108 uint size() const { return _size; }
109 uint name_offset() const { return _name_offset; }
110 uint name_size() const { return _name_size; }
111 uint blob_offset() const { return _blob_offset; }
112 bool has_oop_maps() const { return _has_oop_maps; }
113 address dumptime_content_start_addr() const { return _dumptime_content_start_addr; }
114
115 static bool is_valid_entry_kind(Kind kind) { return kind > None && kind < Kind_count; }
116 static bool is_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob; }
117 static bool is_adapter(Kind kind) { return kind == Adapter; }
118 };
119
120 // Addresses of stubs, blobs and runtime finctions called from compiled code.
121 class AOTCodeAddressTable : public CHeapObj<mtCode> {
122 private:
123 address* _extrs_addr;
124 address* _stubs_addr;
125 address* _shared_blobs_addr;
126 address* _C1_blobs_addr;
127 uint _extrs_length;
128 uint _stubs_length;
129 uint _shared_blobs_length;
130 uint _C1_blobs_length;
131
132 bool _extrs_complete;
133 bool _early_stubs_complete;
134 bool _shared_blobs_complete;
135 bool _early_c1_complete;
136 bool _complete;
137
138 public:
139 AOTCodeAddressTable() :
140 _extrs_addr(nullptr),
141 _stubs_addr(nullptr),
142 _shared_blobs_addr(nullptr),
143 _C1_blobs_addr(nullptr),
144 _extrs_length(0),
145 _stubs_length(0),
146 _shared_blobs_length(0),
147 _C1_blobs_length(0),
148 _extrs_complete(false),
149 _early_stubs_complete(false),
150 _shared_blobs_complete(false),
151 _early_c1_complete(false),
152 _complete(false)
153 { }
154 ~AOTCodeAddressTable();
155 void init_extrs();
156 void init_early_stubs();
157 void init_shared_blobs();
158 void init_early_c1();
159 const char* add_C_string(const char* str);
160 int id_for_C_string(address str);
161 address address_for_C_string(int idx);
162 int id_for_address(address addr, RelocIterator iter, CodeBlob* code_blob);
163 address address_for_id(int id);
164 };
165
166 class AOTCodeCache : public CHeapObj<mtCode> {
167
168 // Classes used to describe AOT code cache.
169 protected:
170 class Config {
171 address _compressedOopBase;
172 uint _compressedOopShift;
173 uint _compressedKlassShift;
174 uint _contendedPaddingWidth;
175 uint _gc;
176 enum Flags {
177 none = 0,
178 debugVM = 1,
179 compressedOops = 2,
180 compressedClassPointers = 4,
181 useTLAB = 8,
182 systemClassAssertions = 16,
183 userClassAssertions = 32,
184 enableContendedPadding = 64,
185 restrictContendedPadding = 128
186 };
187 uint _flags;
188
189 public:
190 void record();
191 bool verify() const;
192 };
193
194 class Header : public CHeapObj<mtCode> {
195 private:
196 enum {
197 AOT_CODE_VERSION = 1
198 };
199 uint _version; // AOT code version (should match when reading code cache)
200 uint _cache_size; // cache size in bytes
201 uint _strings_count; // number of recorded C strings
202 uint _strings_offset; // offset to recorded C strings
203 uint _entries_count; // number of recorded entries
204 uint _entries_offset; // offset of AOTCodeEntry array describing entries
205 uint _adapters_count;
206 uint _shared_blobs_count;
207 uint _C1_blobs_count;
208 uint _C2_blobs_count;
209 Config _config;
210
211 public:
212 void init(uint cache_size,
213 uint strings_count, uint strings_offset,
214 uint entries_count, uint entries_offset,
215 uint adapters_count, uint shared_blobs_count,
216 uint C1_blobs_count, uint C2_blobs_count) {
217 _version = AOT_CODE_VERSION;
218 _cache_size = cache_size;
219 _strings_count = strings_count;
220 _strings_offset = strings_offset;
221 _entries_count = entries_count;
222 _entries_offset = entries_offset;
223 _adapters_count = adapters_count;
224 _shared_blobs_count = shared_blobs_count;
225 _C1_blobs_count = C1_blobs_count;
226 _C2_blobs_count = C2_blobs_count;
227 _config.record();
228 }
229
230
231 uint cache_size() const { return _cache_size; }
232 uint strings_count() const { return _strings_count; }
233 uint strings_offset() const { return _strings_offset; }
234 uint entries_count() const { return _entries_count; }
235 uint entries_offset() const { return _entries_offset; }
236 uint adapters_count() const { return _adapters_count; }
237 uint shared_blobs_count() const { return _shared_blobs_count; }
238 uint C1_blobs_count() const { return _C1_blobs_count; }
239 uint C2_blobs_count() const { return _C2_blobs_count; }
240
241 bool verify(uint load_size) const;
242 bool verify_config() const { // Called after Universe initialized
243 return _config.verify();
244 }
245 };
246
247 // Continue with AOTCodeCache class definition.
248 private:
249 Header* _load_header;
250 char* _load_buffer; // Aligned buffer for loading cached code
251 char* _store_buffer; // Aligned buffer for storing cached code
252 char* _C_store_buffer; // Original unaligned buffer
253
254 uint _write_position; // Position in _store_buffer
255 uint _load_size; // Used when reading cache
256 uint _store_size; // Used when writing cache
257 bool _for_use; // AOT cache is open for using AOT code
258 bool _for_dump; // AOT cache is open for dumping AOT code
259 bool _closing; // Closing cache file
260 bool _failed; // Failed read/write to/from cache (cache is broken?)
261 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
262
263 AOTCodeAddressTable* _table;
264
265 AOTCodeEntry* _load_entries; // Used when reading cache
266 uint* _search_entries; // sorted by ID table [id, index]
267 AOTCodeEntry* _store_entries; // Used when writing cache
268 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table
269 uint _store_entries_cnt;
270
271 static AOTCodeCache* open_for_use();
272 static AOTCodeCache* open_for_dump();
273
274 bool set_write_position(uint pos);
275 bool align_write();
276 address reserve_bytes(uint nbytes);
277 uint write_bytes(const void* buffer, uint nbytes);
278 const char* addr(uint offset) const { return _load_buffer + offset; }
279 static AOTCodeAddressTable* addr_table() {
280 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr;
281 }
282
283 void set_lookup_failed() { _lookup_failed = true; }
284 void clear_lookup_failed() { _lookup_failed = false; }
285 bool lookup_failed() const { return _lookup_failed; }
286
287 public:
288 AOTCodeCache(bool is_dumping, bool is_using);
289 ~AOTCodeCache();
290
291 const char* cache_buffer() const { return _load_buffer; }
292 bool failed() const { return _failed; }
293 void set_failed() { _failed = true; }
294
295 static uint max_aot_code_size();
296
297 uint load_size() const { return _load_size; }
298 uint write_position() const { return _write_position; }
299
300 void load_strings();
301 int store_strings();
302
303 static void init_early_stubs_table() NOT_CDS_RETURN;
304 static void init_shared_blobs_table() NOT_CDS_RETURN;
305 static void init_early_c1_table() NOT_CDS_RETURN;
306
307 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); }
308 address address_for_id(int id) const { return _table->address_for_id(id); }
309
310 bool for_use() const { return _for_use && !_failed; }
311 bool for_dump() const { return _for_dump && !_failed; }
312
313 bool closing() const { return _closing; }
314
315 AOTCodeEntry* add_entry() {
316 _store_entries_cnt++;
317 _store_entries -= 1;
318 return _store_entries;
319 }
320
321 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id);
322
323 bool finish_write();
324
325 bool write_relocations(CodeBlob& code_blob);
326 bool write_oop_map_set(CodeBlob& cb);
327 #ifndef PRODUCT
328 bool write_asm_remarks(CodeBlob& cb);
329 bool write_dbg_strings(CodeBlob& cb);
330 #endif // PRODUCT
331
332 // save and restore API for non-enumerable code blobs
333 static bool store_code_blob(CodeBlob& blob,
334 AOTCodeEntry::Kind entry_kind,
335 uint id, const char* name) NOT_CDS_RETURN_(false);
336
337 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
338 uint id, const char* name) NOT_CDS_RETURN_(nullptr);
339
340 // save and restore API for enumerable code blobs
341 static bool store_code_blob(CodeBlob& blob,
342 AOTCodeEntry::Kind entry_kind,
343 BlobId id) NOT_CDS_RETURN_(false);
344
345 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
346 BlobId id) NOT_CDS_RETURN_(nullptr);
347
348 static uint store_entries_cnt() {
349 if (is_on_for_dump()) {
350 return cache()->_store_entries_cnt;
351 }
352 return -1;
353 }
354
355 // Static access
356
357 private:
358 static AOTCodeCache* _cache;
359 DEBUG_ONLY( static bool _passed_init2; )
360
361 static bool open_cache(bool is_dumping, bool is_using);
362 bool verify_config() {
363 if (for_use()) {
364 return _load_header->verify_config();
365 }
366 return true;
367 }
368 public:
369 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; }
370 static void initialize() NOT_CDS_RETURN;
371 static void init2() NOT_CDS_RETURN;
372 static void close() NOT_CDS_RETURN;
373 static bool is_on() CDS_ONLY({ return cache() != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false);
374 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false);
375 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false);
376 static bool is_dumping_stub() NOT_CDS_RETURN_(false);
377 static bool is_dumping_adapter() NOT_CDS_RETURN_(false);
378 static bool is_using_stub() NOT_CDS_RETURN_(false);
379 static bool is_using_adapter() NOT_CDS_RETURN_(false);
380 static void enable_caching() NOT_CDS_RETURN;
381 static void disable_caching() NOT_CDS_RETURN;
382 static bool is_caching_enabled() NOT_CDS_RETURN_(false);
383
384 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str);
385
386 static void print_on(outputStream* st) NOT_CDS_RETURN;
387 };
388
389 // Concurent AOT code reader
390 class AOTCodeReader {
391 private:
392 const AOTCodeCache* _cache;
393 const AOTCodeEntry* _entry;
394 const char* _load_buffer; // Loaded cached code buffer
395 uint _read_position; // Position in _load_buffer
396 uint read_position() const { return _read_position; }
397 void set_read_position(uint pos);
398 const char* addr(uint offset) const { return _load_buffer + offset; }
399
400 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
401 void set_lookup_failed() { _lookup_failed = true; }
402 void clear_lookup_failed() { _lookup_failed = false; }
403 bool lookup_failed() const { return _lookup_failed; }
404
405 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; }
406 public:
407 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry);
408
409 CodeBlob* compile_code_blob(const char* name);
410
411 ImmutableOopMapSet* read_oop_map_set();
412
413 void fix_relocations(CodeBlob* code_blob);
414 #ifndef PRODUCT
415 void read_asm_remarks(AsmRemarks& asm_remarks);
416 void read_dbg_strings(DbgStrings& dbg_strings);
417 #endif // PRODUCT
418 };
419
420 #endif // SHARE_CODE_AOTCODECACHE_HPP
|
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_CODE_AOTCODECACHE_HPP
26 #define SHARE_CODE_AOTCODECACHE_HPP
27
28 #include "compiler/compilerDefinitions.hpp"
29 #include "memory/allocation.hpp"
30 #include "nmt/memTag.hpp"
31 #include "oops/oopsHierarchy.hpp"
32 #include "runtime/stubInfo.hpp"
33 #include "runtime/vm_version.hpp"
34 #include "utilities/exceptions.hpp"
35 #include "utilities/sizes.hpp"
36
37 /*
38 * AOT Code Cache collects code from Code Cache and corresponding metadata
39 * during application training run.
40 * In following "production" runs this code and data can be loaded into
41 * Code Cache skipping its generation.
42 * Additionaly special compiled code "preload" is generated with class initialization
43 * barriers which can be called on first Java method invocation.
44 */
45
46 class AbstractCompiler;
47 class AOTCodeCache;
48 class AsmRemarks;
49 class ciConstant;
50 class ciEnv;
51 class ciMethod;
52 class CodeBlob;
53 class CodeOffsets;
54 class CompileTask;
55 class DbgStrings;
56 class DebugInformationRecorder;
57 class Dependencies;
58 class ExceptionTable;
59 class ExceptionHandlerTable;
60 template<typename E>
61 class GrowableArray;
62 class ImmutableOopMapSet;
63 class ImplicitExceptionTable;
64 class JavaThread;
65 class Klass;
66 class methodHandle;
67 class Metadata;
68 class Method;
69 class nmethod;
70 class OopMapSet;
71 class OopRecorder;
72 class outputStream;
73 class RelocIterator;
74 class StubCodeGenerator;
75
76 enum class vmIntrinsicID : int;
77
78 #define DO_AOTCODEENTRY_KIND(Fn) \
79 Fn(None) \
80 Fn(Adapter) \
81 Fn(Stub) \
82 Fn(SharedBlob) \
83 Fn(C1Blob) \
84 Fn(C2Blob) \
85 Fn(Nmethod) \
86
87 // Descriptor of AOT Code Cache's entry
88 class AOTCodeEntry {
89 friend class VMStructs;
90 public:
91 enum Kind : s1 {
92 #define DECL_KIND_ENUM(kind) kind,
93 DO_AOTCODEENTRY_KIND(DECL_KIND_ENUM)
94 #undef DECL_KIND_ENUM
95 Kind_count
96 };
97
98 private:
99 Kind _kind;
100 uint _id; // Adapter's id, vmIntrinsic::ID for stub or Method's offset in AOTCache for nmethod
101 uint _offset; // Offset to entry
102 uint _size; // Entry size
103 uint _name_offset; // Method's or intrinsic name
104 uint _name_size;
105 uint _num_inlined_bytecodes;
106 uint _code_offset; // Start of code in cache
107 uint _code_size; // Total size of all code sections
108
109 uint _comp_level; // compilation level
110 uint _comp_id; // compilation id
111 bool _has_oop_maps;
112 bool _has_clinit_barriers; // Generated code has class init checks
113 bool _for_preload; // Code can be used for preload
114 bool _loaded; // Code was loaded
115 bool _not_entrant; // Deoptimized
116 bool _load_fail; // Failed to load due to some klass state
117 address _dumptime_content_start_addr; // CodeBlob::content_begin() at dump time; used for applying relocations
118
119 public:
120 // this constructor is used only by AOTCodeEntry::Stub
121 AOTCodeEntry(uint offset, uint size, uint name_offset, uint name_size,
122 uint code_offset, uint code_size,
123 Kind kind, uint id) {
124 assert(kind == AOTCodeEntry::Stub, "sanity check");
125 _kind = kind;
126 _id = id;
127 _offset = offset;
128 _size = size;
129 _name_offset = name_offset;
130 _name_size = name_size;
131 _code_offset = code_offset;
132 _code_size = code_size;
133
134 _dumptime_content_start_addr = nullptr;
135 _num_inlined_bytecodes = 0;
136 _comp_level = 0;
137 _comp_id = 0;
138 _has_oop_maps = false; // unused here
139 _has_clinit_barriers = false;
140 _for_preload = false;
141 _loaded = false;
142 _not_entrant = false;
143 _load_fail = false;
144 }
145
146 AOTCodeEntry(Kind kind, uint id,
147 uint offset, uint size,
148 uint name_offset, uint name_size,
149 uint blob_offset, bool has_oop_maps,
150 address dumptime_content_start_addr,
151 uint comp_level = 0,
152 uint comp_id = 0,
153 bool has_clinit_barriers = false,
154 bool for_preload = false) {
155 _kind = kind;
156 _id = id;
157 _offset = offset;
158 _size = size;
159 _name_offset = name_offset;
160 _name_size = name_size;
161 _code_offset = blob_offset;
162 _code_size = 0; // unused
163
164 _dumptime_content_start_addr = dumptime_content_start_addr;
165 _num_inlined_bytecodes = 0;
166
167 _comp_level = comp_level;
168 _comp_id = comp_id;
169 _has_oop_maps = has_oop_maps;
170 _has_clinit_barriers = has_clinit_barriers;
171 _for_preload = for_preload;
172 _loaded = false;
173 _not_entrant = false;
174 _load_fail = false;
175
176 _loaded = false;
177 _not_entrant = false;
178 _load_fail = false;
179 }
180
181 void* operator new(size_t x, AOTCodeCache* cache);
182 // Delete is a NOP
183 void operator delete( void *ptr ) {}
184
185 Method* method();
186
187 Kind kind() const { return _kind; }
188 uint id() const { return _id; }
189
190 uint offset() const { return _offset; }
191 void set_offset(uint off) { _offset = off; }
192
193 uint size() const { return _size; }
194 uint name_offset() const { return _name_offset; }
195 uint name_size() const { return _name_size; }
196 uint code_offset() const { return _code_offset; }
197 uint code_size() const { return _code_size; }
198
199 bool has_oop_maps() const { return _has_oop_maps; }
200 address dumptime_content_start_addr() const { return _dumptime_content_start_addr; }
201 uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; }
202 void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; }
203
204 uint comp_level() const { return _comp_level; }
205 uint comp_id() const { return _comp_id; }
206
207 bool has_clinit_barriers() const { return _has_clinit_barriers; }
208 bool for_preload() const { return _for_preload; }
209 bool is_loaded() const { return _loaded; }
210 void set_loaded() { _loaded = true; }
211
212 bool not_entrant() const { return _not_entrant; }
213 void set_not_entrant() { _not_entrant = true; }
214 void set_entrant() { _not_entrant = false; }
215
216 bool load_fail() const { return _load_fail; }
217 void set_load_fail() { _load_fail = true; }
218
219 void print(outputStream* st) const NOT_CDS_RETURN;
220
221 static bool is_valid_entry_kind(Kind kind) { return kind > None && kind < Kind_count; }
222 static bool is_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob; }
223 static bool is_adapter(Kind kind) { return kind == Adapter; }
224 bool is_nmethod() { return _kind == Nmethod; }
225 };
226
227 // Addresses of stubs, blobs and runtime finctions called from compiled code.
228 class AOTCodeAddressTable : public CHeapObj<mtCode> {
229 private:
230 address* _extrs_addr;
231 address* _stubs_addr;
232 address* _shared_blobs_addr;
233 address* _C1_blobs_addr;
234 address* _C2_blobs_addr;
235 uint _extrs_length;
236 uint _stubs_length;
237 uint _shared_blobs_length;
238 uint _C1_blobs_length;
239 uint _C2_blobs_length;
240
241 bool _extrs_complete;
242 bool _early_stubs_complete;
243 bool _shared_blobs_complete;
244 bool _early_c1_complete;
245 bool _c1_complete;
246 bool _c2_complete;
247 bool _complete;
248
249 public:
250 AOTCodeAddressTable() :
251 _extrs_addr(nullptr),
252 _stubs_addr(nullptr),
253 _shared_blobs_addr(nullptr),
254 _C1_blobs_addr(nullptr),
255 _C2_blobs_addr(nullptr),
256 _extrs_length(0),
257 _stubs_length(0),
258 _shared_blobs_length(0),
259 _C1_blobs_length(0),
260 _C2_blobs_length(0),
261 _extrs_complete(false),
262 _early_stubs_complete(false),
263 _shared_blobs_complete(false),
264 _early_c1_complete(false),
265 _c1_complete(false),
266 _c2_complete(false),
267 _complete(false)
268 { }
269 ~AOTCodeAddressTable();
270 void init_extrs();
271 void init_early_stubs();
272 void init_shared_blobs();
273 void init_stubs();
274 void init_early_c1();
275 void init_c1();
276 void init_c2();
277 const char* add_C_string(const char* str);
278 int id_for_C_string(address str);
279 address address_for_C_string(int idx);
280 int id_for_address(address addr, RelocIterator iter, CodeBlob* blob);
281 address address_for_id(int id);
282 bool c2_complete() const { return _c2_complete; }
283 bool c1_complete() const { return _c1_complete; }
284 };
285
286 struct AOTCodeSection {
287 public:
288 address _origin_address;
289 uint _size;
290 uint _offset;
291 };
292
293 enum class DataKind: int {
294 No_Data = -1,
295 Null = 0,
296 Klass = 1,
297 Method = 2,
298 String = 3,
299 MH_Oop = 4,
300 Primitive = 5, // primitive Class object
301 SysLoader = 6, // java_system_loader
302 PlaLoader = 7, // java_platform_loader
303 MethodCnts= 8
304 };
305
306 struct AOTCodeStats;
307
308 class AOTCodeCache : public CHeapObj<mtCode> {
309
310 // Classes used to describe AOT code cache.
311 protected:
312 class Config {
313 size_t _codeCacheSize;
314 address _compressedOopBase;
315 address _compressedKlassBase;
316 uint _compressedOopShift;
317 uint _compressedKlassShift;
318 uint _contendedPaddingWidth;
319 uint _objectAlignment;
320 uint _gcCardSize;
321 uint _gc;
322 enum Flags {
323 none = 0,
324 debugVM = 2,
325 compressedOops = 4,
326 compressedClassPointers = 8,
327 useTLAB = 16,
328 systemClassAssertions = 32,
329 userClassAssertions = 64,
330 enableContendedPadding = 128,
331 restrictContendedPadding = 256,
332 preserveFramePointer = 512
333 };
334 uint _flags;
335 uint _cpu_features_offset; // offset in the cache where cpu features are stored
336
337 public:
338 void record(uint cpu_features_offset);
339 bool verify(AOTCodeCache* cache) const;
340 };
341
342 class Header : public CHeapObj<mtCode> {
343 private:
344 // Here should be version and other verification fields
345 enum {
346 AOT_CODE_VERSION = 1
347 };
348 uint _version; // AOT code version (should match when reading code cache)
349 uint _cache_size; // cache size in bytes
350 uint _strings_count; // number of recorded C strings
351 uint _strings_offset; // offset to recorded C strings
352 uint _entries_count; // number of recorded entries
353 uint _search_table_offset; // offset of table for looking up an AOTCodeEntry
354 uint _entries_offset; // offset of AOTCodeEntry array describing entries
355 uint _preload_entries_count; // entries for pre-loading code
356 uint _preload_entries_offset;
357 uint _adapters_count;
358 uint _shared_blobs_count;
359 uint _C1_blobs_count;
360 uint _C2_blobs_count;
361 uint _stubs_count;
362 Config _config; // must be the last element as there is trailing data stored immediately after Config
363
364 public:
365 void init(uint cache_size,
366 uint strings_count, uint strings_offset,
367 uint entries_count, uint search_table_offset, uint entries_offset,
368 uint preload_entries_count, uint preload_entries_offset,
369 uint adapters_count, uint shared_blobs_count,
370 uint C1_blobs_count, uint C2_blobs_count,
371 uint stubs_count, uint cpu_features_offset) {
372 _version = AOT_CODE_VERSION;
373 _cache_size = cache_size;
374 _strings_count = strings_count;
375 _strings_offset = strings_offset;
376 _entries_count = entries_count;
377 _search_table_offset = search_table_offset;
378 _entries_offset = entries_offset;
379 _preload_entries_count = preload_entries_count;
380 _preload_entries_offset = preload_entries_offset;
381 _adapters_count = adapters_count;
382 _shared_blobs_count = shared_blobs_count;
383 _C1_blobs_count = C1_blobs_count;
384 _C2_blobs_count = C2_blobs_count;
385 _stubs_count = stubs_count;
386
387 _config.record(cpu_features_offset);
388 }
389
390 uint cache_size() const { return _cache_size; }
391 uint strings_count() const { return _strings_count; }
392 uint strings_offset() const { return _strings_offset; }
393 uint entries_count() const { return _entries_count; }
394 uint search_table_offset() const { return _search_table_offset; }
395 uint entries_offset() const { return _entries_offset; }
396 uint preload_entries_count() const { return _preload_entries_count; }
397 uint preload_entries_offset() const { return _preload_entries_offset; }
398 uint adapters_count() const { return _adapters_count; }
399 uint shared_blobs_count() const { return _shared_blobs_count; }
400 uint C1_blobs_count() const { return _C1_blobs_count; }
401 uint C2_blobs_count() const { return _C2_blobs_count; }
402 uint stubs_count() const { return _stubs_count; }
403 uint nmethods_count() const { return _preload_entries_count
404 + _entries_count
405 - _stubs_count
406 - _shared_blobs_count
407 - _C1_blobs_count
408 - _C2_blobs_count
409 - _adapters_count; }
410
411 bool verify(uint load_size) const;
412 bool verify_config(AOTCodeCache* cache) const { // Called after Universe initialized
413 return _config.verify(cache);
414 }
415 };
416
417 // Continue with AOTCodeCache class definition.
418 private:
419 Header* _load_header;
420 char* _load_buffer; // Aligned buffer for loading AOT code
421 char* _store_buffer; // Aligned buffer for storing AOT code
422 char* _C_store_buffer; // Original unaligned buffer
423
424 uint _write_position; // Position in _store_buffer
425 uint _load_size; // Used when reading cache
426 uint _store_size; // Used when writing cache
427 bool _for_use; // AOT cache is open for using AOT code
428 bool _for_dump; // AOT cache is open for dumping AOT code
429 bool _closing; // Closing cache file
430 bool _failed; // Failed read/write to/from cache (cache is broken?)
431 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
432
433 bool _for_preload; // Code for preload
434 bool _has_clinit_barriers; // Code with clinit barriers
435
436 AOTCodeAddressTable* _table;
437
438 AOTCodeEntry* _load_entries; // Used when reading cache
439 uint* _search_entries; // sorted by ID table [id, index]
440 AOTCodeEntry* _store_entries; // Used when writing cache
441 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table
442 uint _store_entries_cnt;
443
444 uint _compile_id;
445 uint _comp_level;
446 uint compile_id() const { return _compile_id; }
447 uint comp_level() const { return _comp_level; }
448
449 static AOTCodeCache* open_for_use();
450 static AOTCodeCache* open_for_dump();
451
452 bool set_write_position(uint pos);
453 bool align_write();
454
455 address reserve_bytes(uint nbytes);
456 uint write_bytes(const void* buffer, uint nbytes);
457 const char* addr(uint offset) const { return _load_buffer + offset; }
458 static AOTCodeAddressTable* addr_table() {
459 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr;
460 }
461
462 void set_lookup_failed() { _lookup_failed = true; }
463 void clear_lookup_failed() { _lookup_failed = false; }
464 bool lookup_failed() const { return _lookup_failed; }
465
466 AOTCodeEntry* write_nmethod(nmethod* nm, bool for_preload);
467
468 // States:
469 // S >= 0: allow new readers, S readers are currently active
470 // S < 0: no new readers are allowed; (-S-1) readers are currently active
471 // (special case: S = -1 means no readers are active, and would never be active again)
472 static volatile int _nmethod_readers;
473
474 static void wait_for_no_nmethod_readers();
475
476 class ReadingMark {
477 private:
478 bool _failed;
479 public:
480 ReadingMark();
481 ~ReadingMark();
482 bool failed() {
483 return _failed;
484 }
485 };
486
487 public:
488 AOTCodeCache(bool is_dumping, bool is_using);
489 ~AOTCodeCache();
490
491 const char* cache_buffer() const { return _load_buffer; }
492 bool failed() const { return _failed; }
493 void set_failed() { _failed = true; }
494
495 static bool is_address_in_aot_cache(address p) NOT_CDS_RETURN_(false);
496 static uint max_aot_code_size();
497
498 uint load_size() const { return _load_size; }
499 uint write_position() const { return _write_position; }
500
501 void load_strings();
502 int store_strings();
503
504 static void init_early_stubs_table() NOT_CDS_RETURN;
505 static void init_shared_blobs_table() NOT_CDS_RETURN;
506 static void init_stubs_table() NOT_CDS_RETURN;
507 static void init_early_c1_table() NOT_CDS_RETURN;
508 static void init_c1_table() NOT_CDS_RETURN;
509 static void init_c2_table() NOT_CDS_RETURN;
510
511 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); }
512 address address_for_id(int id) const { return _table->address_for_id(id); }
513
514 bool for_use() const { return _for_use && !_failed; }
515 bool for_dump() const { return _for_dump && !_failed; }
516
517 bool closing() const { return _closing; }
518
519 AOTCodeEntry* add_entry() {
520 _store_entries_cnt++;
521 _store_entries -= 1;
522 return _store_entries;
523 }
524 void preload_aot_code(TRAPS);
525
526 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id, uint comp_level = 0);
527 void invalidate_entry(AOTCodeEntry* entry);
528
529 void store_cpu_features(char*& buffer, uint buffer_size);
530
531 bool finish_write();
532
533 void log_stats_on_exit(AOTCodeStats& stats);
534
535 static bool load_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start) NOT_CDS_RETURN_(false);
536 static bool store_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start) NOT_CDS_RETURN_(false);
537
538 bool write_klass(Klass* klass);
539 bool write_method(Method* method);
540
541 bool write_relocations(CodeBlob& code_blob, GrowableArray<Handle>* oop_list = nullptr, GrowableArray<Metadata*>* metadata_list = nullptr);
542
543 bool write_oop_map_set(CodeBlob& cb);
544 bool write_nmethod_reloc_immediates(GrowableArray<Handle>& oop_list, GrowableArray<Metadata*>& metadata_list);
545
546 jobject read_oop(JavaThread* thread, const methodHandle& comp_method);
547 Metadata* read_metadata(const methodHandle& comp_method);
548
549 bool write_oop(jobject& jo);
550 bool write_oop(oop obj);
551 bool write_metadata(Metadata* m);
552 bool write_oops(nmethod* nm);
553 bool write_metadata(nmethod* nm);
554
555 #ifndef PRODUCT
556 bool write_asm_remarks(AsmRemarks& asm_remarks, bool use_string_table);
557 bool write_dbg_strings(DbgStrings& dbg_strings, bool use_string_table);
558 #endif // PRODUCT
559
560 // save and restore API for non-enumerable code blobs
561 static bool store_code_blob(CodeBlob& blob,
562 AOTCodeEntry::Kind entry_kind,
563 uint id, const char* name) NOT_CDS_RETURN_(false);
564
565 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
566 uint id, const char* name) NOT_CDS_RETURN_(nullptr);
567
568 static bool load_nmethod(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler, CompLevel comp_level) NOT_CDS_RETURN_(false);
569 static AOTCodeEntry* store_nmethod(nmethod* nm, AbstractCompiler* compiler, bool for_preload) NOT_CDS_RETURN_(nullptr);
570
571 // save and restore API for enumerable code blobs
572 static bool store_code_blob(CodeBlob& blob,
573 AOTCodeEntry::Kind entry_kind,
574 BlobId id) NOT_CDS_RETURN_(false);
575
576 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
577 BlobId id) NOT_CDS_RETURN_(nullptr);
578
579 static uint store_entries_cnt() {
580 if (is_on_for_dump()) {
581 return cache()->_store_entries_cnt;
582 }
583 return -1;
584 }
585
586 // Static access
587
588 private:
589 static AOTCodeCache* _cache;
590 DEBUG_ONLY( static bool _passed_init2; )
591
592 static bool open_cache(bool is_dumping, bool is_using);
593
594 bool verify_config_on_use() {
595 if (for_use()) {
596 return _load_header->verify_config(this);
597 }
598 return true;
599 }
600 public:
601 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; }
602 static void initialize() NOT_CDS_RETURN;
603 static void init2() NOT_CDS_RETURN;
604 static void close() NOT_CDS_RETURN;
605 static bool is_on() CDS_ONLY({ return cache() != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false);
606 static bool is_code_load_thread_on() NOT_CDS_RETURN_(false);
607 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false);
608 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false);
609 static bool is_dumping_code() NOT_CDS_RETURN_(false);
610 static bool is_dumping_stub() NOT_CDS_RETURN_(false);
611 static bool is_dumping_adapter() NOT_CDS_RETURN_(false);
612 static bool is_using_code() NOT_CDS_RETURN_(false);
613 static bool is_using_stub() NOT_CDS_RETURN_(false);
614 static bool is_using_adapter() NOT_CDS_RETURN_(false);
615 static void enable_caching() NOT_CDS_RETURN;
616 static void disable_caching() NOT_CDS_RETURN;
617 static bool is_caching_enabled() NOT_CDS_RETURN_(false);
618
619 // It is used before AOTCodeCache is initialized.
620 static bool maybe_dumping_code() NOT_CDS_RETURN_(false);
621
622 static bool allow_const_field(ciConstant& value) NOT_CDS_RETURN_(false);
623 static void invalidate(AOTCodeEntry* entry) NOT_CDS_RETURN;
624 static AOTCodeEntry* find_code_entry(const methodHandle& method, uint comp_level) NOT_CDS_RETURN_(nullptr);
625 static void preload_code(JavaThread* thread) NOT_CDS_RETURN;
626
627 template<typename Function>
628 static void iterate(Function function) { // lambda enabled API
629 AOTCodeCache* cache = open_for_use();
630 if (cache != nullptr) {
631 ReadingMark rdmk;
632 if (rdmk.failed()) {
633 // Cache is closed, cannot touch anything.
634 return;
635 }
636
637 uint count = cache->_load_header->entries_count();
638 uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index]
639 AOTCodeEntry* load_entries = (AOTCodeEntry*)(search_entries + 2 * count);
640
641 for (uint i = 0; i < count; i++) {
642 int index = search_entries[2*i + 1];
643 AOTCodeEntry* entry = &(load_entries[index]);
644 function(entry);
645 }
646 }
647 }
648
649 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str);
650
651 static void print_on(outputStream* st) NOT_CDS_RETURN;
652 static void print_statistics_on(outputStream* st) NOT_CDS_RETURN;
653 static void print_timers_on(outputStream* st) NOT_CDS_RETURN;
654 static void print_unused_entries_on(outputStream* st) NOT_CDS_RETURN;
655 };
656
657 // Concurent AOT code reader
658 class AOTCodeReader {
659 private:
660 const AOTCodeCache* _cache;
661 const AOTCodeEntry* _entry;
662 const char* _load_buffer; // Loaded AOT code buffer
663 uint _read_position; // Position in _load_buffer
664 uint read_position() const { return _read_position; }
665 void set_read_position(uint pos);
666 const char* addr(uint offset) const { return _load_buffer + offset; }
667
668 uint _compile_id;
669 uint _comp_level;
670 uint compile_id() const { return _compile_id; }
671 uint comp_level() const { return _comp_level; }
672
673 bool _preload; // Preloading code before method execution
674 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
675 void set_lookup_failed() { _lookup_failed = true; }
676 void clear_lookup_failed() { _lookup_failed = false; }
677 bool lookup_failed() const { return _lookup_failed; }
678
679 public:
680 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry, CompileTask* task);
681
682 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; }
683
684 // convenience method to convert offset in AOTCodeEntry data to its address
685 bool compile_nmethod(ciEnv* env, ciMethod* target, AbstractCompiler* compiler);
686
687 CodeBlob* compile_code_blob(const char* name);
688
689 Klass* read_klass(const methodHandle& comp_method);
690 Method* read_method(const methodHandle& comp_method);
691
692 oop read_oop(JavaThread* thread, const methodHandle& comp_method);
693 Metadata* read_metadata(const methodHandle& comp_method);
694 bool read_oops(OopRecorder* oop_recorder, ciMethod* target);
695 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target);
696
697 bool read_oop_metadata_list(JavaThread* thread, ciMethod* target, GrowableArray<Handle> &oop_list, GrowableArray<Metadata*> &metadata_list, OopRecorder* oop_recorder);
698 void apply_relocations(nmethod* nm, GrowableArray<Handle> &oop_list, GrowableArray<Metadata*> &metadata_list) NOT_CDS_RETURN;
699
700 ImmutableOopMapSet* read_oop_map_set();
701
702 void fix_relocations(CodeBlob* code_blob, GrowableArray<Handle>* oop_list = nullptr, GrowableArray<Metadata*>* metadata_list = nullptr) NOT_CDS_RETURN;
703 #ifndef PRODUCT
704 void read_asm_remarks(AsmRemarks& asm_remarks, bool use_string_table) NOT_CDS_RETURN;
705 void read_dbg_strings(DbgStrings& dbg_strings, bool use_string_table) NOT_CDS_RETURN;
706 #endif // PRODUCT
707
708 void print_on(outputStream* st);
709 };
710
711 // +1 for preload code
712 const int AOTCompLevel_count = CompLevel_count + 1; // 6 levels indexed from 0 to 5
713
714 struct AOTCodeStats {
715 private:
716 struct {
717 uint _kind_cnt[AOTCodeEntry::Kind_count];
718 uint _nmethod_cnt[AOTCompLevel_count];
719 uint _clinit_barriers_cnt;
720 } ccstats; // AOT code stats
721
722 void check_kind(uint kind) { assert(kind >= AOTCodeEntry::None && kind < AOTCodeEntry::Kind_count, "Invalid AOTCodeEntry kind %d", kind); }
723 void check_complevel(uint lvl) { assert(lvl >= CompLevel_none && lvl < AOTCompLevel_count, "Invalid compilation level %d", lvl); }
724
725 public:
726 void inc_entry_cnt(uint kind) { check_kind(kind); ccstats._kind_cnt[kind] += 1; }
727 void inc_nmethod_cnt(uint lvl) { check_complevel(lvl); ccstats._nmethod_cnt[lvl] += 1; }
728 void inc_preload_cnt() { ccstats._nmethod_cnt[AOTCompLevel_count-1] += 1; }
729 void inc_clinit_barriers_cnt() { ccstats._clinit_barriers_cnt += 1; }
730
731 void collect_entry_stats(AOTCodeEntry* entry) {
732 inc_entry_cnt(entry->kind());
733 if (entry->is_nmethod()) {
734 entry->for_preload() ? inc_nmethod_cnt(AOTCompLevel_count-1)
735 : inc_nmethod_cnt(entry->comp_level());
736 if (entry->has_clinit_barriers()) {
737 inc_clinit_barriers_cnt();
738 }
739 }
740 }
741
742 uint entry_count(uint kind) { check_kind(kind); return ccstats._kind_cnt[kind]; }
743 uint nmethod_count(uint lvl) { check_complevel(lvl); return ccstats._nmethod_cnt[lvl]; }
744 uint preload_count() { return ccstats._nmethod_cnt[AOTCompLevel_count-1]; }
745 uint clinit_barriers_count() { return ccstats._clinit_barriers_cnt; }
746
747 uint total_count() {
748 uint total = 0;
749 for (int kind = AOTCodeEntry::None; kind < AOTCodeEntry::Kind_count; kind++) {
750 total += ccstats._kind_cnt[kind];
751 }
752 return total;
753 }
754
755 static AOTCodeStats add_aot_code_stats(AOTCodeStats stats1, AOTCodeStats stats2);
756
757 // Runtime stats of the AOT code
758 private:
759 struct {
760 struct {
761 uint _loaded_cnt;
762 uint _invalidated_cnt;
763 uint _load_failed_cnt;
764 } _entry_kinds[AOTCodeEntry::Kind_count],
765 _nmethods[AOTCompLevel_count];
766 } rs; // rs = runtime stats
767
768 public:
769 void inc_entry_loaded_cnt(uint kind) { check_kind(kind); rs._entry_kinds[kind]._loaded_cnt += 1; }
770 void inc_entry_invalidated_cnt(uint kind) { check_kind(kind); rs._entry_kinds[kind]._invalidated_cnt += 1; }
771 void inc_entry_load_failed_cnt(uint kind) { check_kind(kind); rs._entry_kinds[kind]._load_failed_cnt += 1; }
772
773 void inc_nmethod_loaded_cnt(uint lvl) { check_complevel(lvl); rs._nmethods[lvl]._loaded_cnt += 1; }
774 void inc_nmethod_invalidated_cnt(uint lvl) { check_complevel(lvl); rs._nmethods[lvl]._invalidated_cnt += 1; }
775 void inc_nmethod_load_failed_cnt(uint lvl) { check_complevel(lvl); rs._nmethods[lvl]._load_failed_cnt += 1; }
776
777 uint entry_loaded_count(uint kind) { check_kind(kind); return rs._entry_kinds[kind]._loaded_cnt; }
778 uint entry_invalidated_count(uint kind) { check_kind(kind); return rs._entry_kinds[kind]._invalidated_cnt; }
779 uint entry_load_failed_count(uint kind) { check_kind(kind); return rs._entry_kinds[kind]._load_failed_cnt; }
780
781 uint nmethod_loaded_count(uint lvl) { check_complevel(lvl); return rs._nmethods[lvl]._loaded_cnt; }
782 uint nmethod_invalidated_count(uint lvl) { check_complevel(lvl); return rs._nmethods[lvl]._invalidated_cnt; }
783 uint nmethod_load_failed_count(uint lvl) { check_complevel(lvl); return rs._nmethods[lvl]._load_failed_cnt; }
784
785 void inc_loaded_cnt(AOTCodeEntry* entry) {
786 inc_entry_loaded_cnt(entry->kind());
787 if (entry->is_nmethod()) {
788 entry->for_preload() ? inc_nmethod_loaded_cnt(AOTCompLevel_count-1)
789 : inc_nmethod_loaded_cnt(entry->comp_level());
790 }
791 }
792
793 void inc_invalidated_cnt(AOTCodeEntry* entry) {
794 inc_entry_invalidated_cnt(entry->kind());
795 if (entry->is_nmethod()) {
796 entry->for_preload() ? inc_nmethod_invalidated_cnt(AOTCompLevel_count-1)
797 : inc_nmethod_invalidated_cnt(entry->comp_level());
798 }
799 }
800
801 void inc_load_failed_cnt(AOTCodeEntry* entry) {
802 inc_entry_load_failed_cnt(entry->kind());
803 if (entry->is_nmethod()) {
804 entry->for_preload() ? inc_nmethod_load_failed_cnt(AOTCompLevel_count-1)
805 : inc_nmethod_load_failed_cnt(entry->comp_level());
806 }
807 }
808
809 void collect_entry_runtime_stats(AOTCodeEntry* entry) {
810 if (entry->is_loaded()) {
811 inc_loaded_cnt(entry);
812 }
813 if (entry->not_entrant()) {
814 inc_invalidated_cnt(entry);
815 }
816 if (entry->load_fail()) {
817 inc_load_failed_cnt(entry);
818 }
819 }
820
821 void collect_all_stats(AOTCodeEntry* entry) {
822 collect_entry_stats(entry);
823 collect_entry_runtime_stats(entry);
824 }
825
826 AOTCodeStats() {
827 memset(this, 0, sizeof(AOTCodeStats));
828 }
829 };
830
831 // code cache internal runtime constants area used by AOT code
832 class AOTRuntimeConstants {
833 friend class AOTCodeCache;
834 private:
835 address _card_table_address;
836 uint _grain_shift;
837 static address _field_addresses_list[];
838 static AOTRuntimeConstants _aot_runtime_constants;
839 // private constructor for unique singleton
840 AOTRuntimeConstants() { }
841 // private for use by friend class AOTCodeCache
842 static void initialize_from_runtime();
843 public:
844 #if INCLUDE_CDS
845 static bool contains(address adr) {
846 address base = (address)&_aot_runtime_constants;
847 address hi = base + sizeof(AOTRuntimeConstants);
848 return (base <= adr && adr < hi);
849 }
850 static address card_table_address() { return (address)&_aot_runtime_constants._card_table_address; }
851 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; }
852 static address* field_addresses_list() {
853 return _field_addresses_list;
854 }
855 #else
856 static bool contains(address adr) { return false; }
857 static address card_table_address() { return nullptr; }
858 static address grain_shift_address() { return nullptr; }
859 static address* field_addresses_list() { return nullptr; }
860 #endif
861 };
862
863 #endif // SHARE_CODE_AOTCODECACHE_HPP
|