1 | /* |
2 | * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
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 | #ifndef SHARE_AOT_AOTCODEHEAP_HPP |
25 | #define SHARE_AOT_AOTCODEHEAP_HPP |
26 | |
27 | #include "aot/aotCompiledMethod.hpp" |
28 | #include "classfile/symbolTable.hpp" |
29 | #include "metaprogramming/integralConstant.hpp" |
30 | #include "metaprogramming/isRegisteredEnum.hpp" |
31 | #include "oops/metadata.hpp" |
32 | #include "oops/method.hpp" |
33 | |
34 | enum CodeState { |
35 | not_set = 0, // _aot fields is not set yet |
36 | in_use = 1, // _aot field is set to corresponding AOTCompiledMethod |
37 | invalid = 2 // AOT code is invalidated because dependencies failed |
38 | }; |
39 | |
40 | template<> struct IsRegisteredEnum<CodeState> : public TrueType {}; |
41 | |
42 | typedef struct { |
43 | AOTCompiledMethod* _aot; |
44 | CodeState _state; // State change cases: not_set->in_use, not_set->invalid |
45 | } CodeToAMethod; |
46 | |
47 | class ClassLoaderData; |
48 | |
49 | class AOTClass { |
50 | public: |
51 | ClassLoaderData* _classloader; |
52 | }; |
53 | |
54 | typedef struct { |
55 | int _name_offset; |
56 | int _code_offset; |
57 | int _meta_offset; |
58 | int _metadata_got_offset; |
59 | int _metadata_got_size; |
60 | int _code_id; |
61 | } AOTMethodOffsets; |
62 | |
63 | typedef struct { |
64 | const char* _name; |
65 | address _code; |
66 | aot_metadata* _meta; |
67 | jlong* _state_adr; |
68 | address _metadata_table; |
69 | int _metadata_size; |
70 | } AOTMethodData; |
71 | |
72 | typedef struct { |
73 | int _got_index; |
74 | int _class_id; |
75 | int _compiled_methods_offset; |
76 | int _dependent_methods_offset; |
77 | uint64_t _fingerprint; |
78 | } AOTKlassData; |
79 | |
80 | typedef struct { |
81 | int _version; |
82 | int _class_count; |
83 | int _method_count; |
84 | int _klasses_got_size; |
85 | int _metadata_got_size; |
86 | int _oop_got_size; |
87 | int _jvm_version_offset; |
88 | |
89 | enum { |
90 | AOT_SHARED_VERSION = 1 |
91 | }; |
92 | } ; |
93 | |
94 | typedef struct { |
95 | enum { CONFIG_SIZE = 8 * jintSize + 11 }; |
96 | // 8 int values |
97 | int _config_size; |
98 | int _narrowOopShift; |
99 | int _narrowKlassShift; |
100 | int _contendedPaddingWidth; |
101 | int _fieldsAllocationStyle; |
102 | int _objectAlignment; |
103 | int _codeSegmentSize; |
104 | int _gc; |
105 | // byte[11] array map to boolean values here |
106 | bool _debug_VM; |
107 | bool _useCompressedOops; |
108 | bool _useCompressedClassPointers; |
109 | bool _compactFields; |
110 | bool _useTLAB; |
111 | bool _useBiasedLocking; |
112 | bool _tieredAOT; |
113 | bool _enableContended; |
114 | bool _restrictContended; |
115 | bool _omitAssertions; |
116 | bool _threadLocalHandshakes; |
117 | } AOTConfiguration; |
118 | |
119 | class AOTLib : public CHeapObj<mtCode> { |
120 | static bool _narrow_oop_shift_initialized; |
121 | static int _narrow_oop_shift; |
122 | static int _narrow_klass_shift; |
123 | |
124 | bool _valid; |
125 | void* _dl_handle; |
126 | const int _dso_id; |
127 | const char* _name; |
128 | // VM configuration during AOT compilation |
129 | AOTConfiguration* _config; |
130 | AOTHeader* ; |
131 | |
132 | void handle_config_error(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); |
133 | public: |
134 | AOTLib(void* handle, const char* name, int dso_id); |
135 | virtual ~AOTLib(); |
136 | static int narrow_oop_shift() { return _narrow_oop_shift; } |
137 | static int narrow_klass_shift() { return _narrow_klass_shift; } |
138 | static bool narrow_oop_shift_initialized() { return _narrow_oop_shift_initialized; } |
139 | |
140 | bool is_valid() const { |
141 | return _valid; |
142 | } |
143 | const char* name() const { |
144 | return _name; |
145 | } |
146 | void* dl_handle() const { |
147 | return _dl_handle; |
148 | } |
149 | int id() const { |
150 | return _dso_id; |
151 | } |
152 | AOTHeader* () const { |
153 | return _header; |
154 | } |
155 | AOTConfiguration* config() const { |
156 | return _config; |
157 | } |
158 | void verify_config(); |
159 | void verify_flag(bool aot_flag, bool flag, const char* name); |
160 | void verify_flag(int aot_flag, int flag, const char* name); |
161 | |
162 | address load_symbol(const char *name); |
163 | }; |
164 | |
165 | |
166 | class AOTCodeHeap : public CodeHeap { |
167 | AOTLib* _lib; |
168 | int _aot_id; |
169 | |
170 | int _class_count; |
171 | int _method_count; |
172 | AOTClass* _classes; |
173 | CodeToAMethod* _code_to_aot; |
174 | |
175 | address _code_space; |
176 | address _code_segments; |
177 | jlong* _method_state; |
178 | |
179 | |
180 | // Collect metaspace info: names -> address in .got section |
181 | const char* _metaspace_names; |
182 | address _method_metadata; |
183 | |
184 | address _methods_offsets; |
185 | address _klasses_offsets; |
186 | address _dependencies; |
187 | |
188 | Metadata** _klasses_got; |
189 | Metadata** _metadata_got; |
190 | oop* _oop_got; |
191 | |
192 | int _klasses_got_size; |
193 | int _metadata_got_size; |
194 | int _oop_got_size; |
195 | |
196 | // Collect stubs info |
197 | int* _stubs_offsets; |
198 | |
199 | bool _lib_symbols_initialized; |
200 | |
201 | void adjust_boundaries(AOTCompiledMethod* method) { |
202 | char* low = (char*)method->code_begin(); |
203 | if (low < low_boundary()) { |
204 | _memory.set_low_boundary(low); |
205 | _memory.set_low(low); |
206 | } |
207 | char* high = (char *)method->code_end(); |
208 | if (high > high_boundary()) { |
209 | _memory.set_high_boundary(high); |
210 | _memory.set_high(high); |
211 | } |
212 | assert(_method_count > 0, "methods count should be set already" ); |
213 | } |
214 | |
215 | void register_stubs(); |
216 | |
217 | void link_shared_runtime_symbols(); |
218 | void link_stub_routines_symbols(); |
219 | void link_os_symbols(); |
220 | void link_graal_runtime_symbols(); |
221 | |
222 | void link_global_lib_symbols(); |
223 | void link_primitive_array_klasses(); |
224 | void publish_aot(const methodHandle& mh, AOTMethodData* method_data, int code_id); |
225 | |
226 | |
227 | AOTCompiledMethod* next_in_use_at(int index) const; |
228 | |
229 | // Find klass in SystemDictionary for aot metadata. |
230 | static Klass* lookup_klass(const char* name, int len, const Method* method, Thread* THREAD); |
231 | public: |
232 | AOTCodeHeap(AOTLib* lib); |
233 | virtual ~AOTCodeHeap(); |
234 | |
235 | AOTCompiledMethod* find_aot(address p) const; |
236 | |
237 | virtual void* find_start(void* p) const; |
238 | virtual CodeBlob* find_blob_unsafe(void* start) const; |
239 | virtual void* first() const; |
240 | virtual void* next(void *p) const; |
241 | |
242 | AOTKlassData* find_klass(InstanceKlass* ik); |
243 | bool load_klass_data(InstanceKlass* ik, Thread* thread); |
244 | Klass* get_klass_from_got(const char* klass_name, int klass_len, const Method* method); |
245 | |
246 | bool is_dependent_method(Klass* dependee, AOTCompiledMethod* aot); |
247 | void mark_evol_dependent_methods(InstanceKlass* dependee); |
248 | |
249 | const char* get_name_at(int offset) { |
250 | return _metaspace_names + offset; |
251 | } |
252 | |
253 | |
254 | void oops_do(OopClosure* f); |
255 | void metadata_do(MetadataClosure* f); |
256 | void got_metadata_do(MetadataClosure* f); |
257 | |
258 | #ifdef ASSERT |
259 | bool got_contains(Metadata **p) { |
260 | return (p >= &_metadata_got[0] && p < &_metadata_got[_metadata_got_size]) || |
261 | (p >= &_klasses_got[0] && p < &_klasses_got[_klasses_got_size]); |
262 | } |
263 | #endif |
264 | |
265 | int dso_id() const { return _lib->id(); } |
266 | int aot_id() const { return _aot_id; } |
267 | |
268 | int method_count() { return _method_count; } |
269 | |
270 | AOTCompiledMethod* get_code_desc_at_index(int index) { |
271 | if (index < _method_count && _code_to_aot[index]._state == in_use) { |
272 | AOTCompiledMethod* m = _code_to_aot[index]._aot; |
273 | assert(m != NULL, "AOT method should be set" ); |
274 | if (!m->is_runtime_stub()) { |
275 | return m; |
276 | } |
277 | } |
278 | return NULL; |
279 | } |
280 | |
281 | static Method* find_method(Klass* klass, Thread* thread, const char* method_name); |
282 | |
283 | void cleanup_inline_caches(); |
284 | |
285 | DEBUG_ONLY( int verify_icholder_relocations(); ) |
286 | |
287 | void alive_methods_do(void f(CompiledMethod* nm)); |
288 | |
289 | #ifndef PRODUCT |
290 | static int klasses_seen; |
291 | static int aot_klasses_found; |
292 | static int aot_klasses_fp_miss; |
293 | static int aot_klasses_cl_miss; |
294 | static int aot_methods_found; |
295 | |
296 | static void print_statistics(); |
297 | #endif |
298 | |
299 | bool reconcile_dynamic_invoke(AOTCompiledMethod* caller, InstanceKlass* holder, int index, Method* adapter_method, Klass *appendix_klass); |
300 | |
301 | private: |
302 | AOTKlassData* find_klass(const char* name); |
303 | |
304 | void sweep_dependent_methods(int* indexes, int methods_cnt); |
305 | void sweep_dependent_methods(AOTKlassData* klass_data); |
306 | void sweep_dependent_methods(InstanceKlass* ik); |
307 | void sweep_method(AOTCompiledMethod* aot); |
308 | |
309 | bool reconcile_dynamic_klass(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Klass *dyno, const char *descriptor1, const char *descriptor2 = NULL); |
310 | |
311 | bool reconcile_dynamic_method(AOTCompiledMethod *caller, InstanceKlass* holder, int index, Method *adapter_method); |
312 | |
313 | }; |
314 | |
315 | #endif // SHARE_AOT_AOTCODEHEAP_HPP |
316 | |