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_AOTCOMPILEDMETHOD_HPP
25#define SHARE_AOT_AOTCOMPILEDMETHOD_HPP
26
27#include "code/codeCache.hpp"
28#include "code/compiledIC.hpp"
29#include "code/compiledMethod.hpp"
30#include "code/pcDesc.hpp"
31#include "code/relocInfo.hpp"
32
33class AOTCodeHeap;
34
35class aot_metadata {
36private:
37 int _size;
38 int _code_size;
39 int _entry;
40 int _verified_entry;
41 int _exception_handler_offset;
42 int _deopt_handler_offset;
43 int _stubs_offset;
44 int _frame_size;
45 // location in frame (offset for sp) that deopt can store the original
46 // pc during a deopt.
47 int _orig_pc_offset;
48 int _unsafe_access;
49
50 int _pc_desc_begin;
51 int _scopes_begin;
52 int _reloc_begin;
53 int _exception_table_begin;
54 int _nul_chk_table_begin;
55 int _oopmap_begin;
56 address at_offset(size_t offset) const { return ((address) this) + offset; }
57public:
58 int code_size() const { return _code_size; }
59 int frame_size() const { return _frame_size / HeapWordSize; }
60 PcDesc *scopes_pcs_begin() const { return (PcDesc *) at_offset(_pc_desc_begin); }
61 PcDesc *scopes_pcs_end() const { return (PcDesc *) at_offset(_scopes_begin); }
62 address scopes_data_begin() const { return at_offset(_scopes_begin); }
63 address scopes_data_end() const { return at_offset(_reloc_begin); }
64 relocInfo* relocation_begin() const { return (relocInfo*) at_offset(_reloc_begin); }
65 relocInfo* relocation_end() const { return (relocInfo*) at_offset(_exception_table_begin); }
66 address handler_table_begin () const { return at_offset(_exception_table_begin); }
67 address handler_table_end() const { return at_offset(_nul_chk_table_begin); }
68
69 address nul_chk_table_begin() const { return at_offset(_nul_chk_table_begin); }
70 address nul_chk_table_end() const { return at_offset(_oopmap_begin); }
71
72 ImmutableOopMapSet* oopmap_set() const { return (ImmutableOopMapSet*) at_offset(_oopmap_begin); }
73
74 address consts_begin() const { return at_offset(_size); }
75 address consts_end() const { return at_offset(_size); }
76 int stub_offset() const { return _stubs_offset; }
77 int entry_offset() const { return _entry; }
78 int verified_entry_offset() const { return _verified_entry; }
79 int exception_handler_offset() const { return _exception_handler_offset; }
80 int deopt_handler_offset() const { return _deopt_handler_offset; }
81 int orig_pc_offset() const { return _orig_pc_offset; }
82
83 int handler_table_size() const { return handler_table_end() - handler_table_begin(); }
84 int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }
85 bool has_unsafe_access() const { return _unsafe_access != 0; }
86
87};
88
89/*
90 * Use this for AOTCompiledMethods since a lot of the fields in CodeBlob gets the same
91 * value when they come from AOT. code_begin == content_begin, etc... */
92class AOTCompiledMethodLayout : public CodeBlobLayout {
93public:
94 AOTCompiledMethodLayout(address code_begin, address code_end, address relocation_begin, address relocation_end) :
95 CodeBlobLayout(
96 code_begin, // code_begin
97 code_end, // code_end
98 code_begin, // content_begin
99 code_end, // content_end
100 code_end, // data_end
101 relocation_begin, // relocation_begin
102 relocation_end
103 ) {
104 }
105};
106
107class AOTCompiledMethod : public CompiledMethod, public CHeapObj<mtCode> {
108private:
109 address _code;
110 aot_metadata* _meta;
111 Metadata** _metadata_got;
112 jlong* _state_adr; // Address of cell to indicate aot method state (in_use or not_entrant)
113 AOTCodeHeap* _heap; // code heap which has this method
114 const char* _name; // For stub: "AOT Stub<name>" for stub,
115 // For nmethod: "<u2_size>Ljava/lang/ThreadGroup;<u2_size>addUnstarted<u2_size>()V"
116 const int _metadata_size; // size of _metadata_got
117 const int _aot_id;
118 const int _method_index;
119 oop _oop; // method()->method_holder()->klass_holder()
120
121 address* orig_pc_addr(const frame* fr);
122 bool make_not_entrant_helper(int new_state);
123
124 public:
125 using CHeapObj<mtCode>::operator new;
126 using CHeapObj<mtCode>::operator delete;
127
128 int method_index() const { return _method_index; }
129 void set_oop(oop o) { _oop = o; }
130
131 AOTCompiledMethod(address code, Method* method, aot_metadata* meta, address metadata_got, int metadata_size, jlong* state_adr, AOTCodeHeap* heap, const char* name, int method_index, int aot_id) :
132 CompiledMethod(method, name, compiler_jvmci, // AOT code is generated by JVMCI compiler
133 AOTCompiledMethodLayout(code, code + meta->code_size(), (address) meta->relocation_begin(), (address) meta->relocation_end()),
134 0 /* frame_complete_offset */, meta->frame_size() /* frame_size */, meta->oopmap_set(), false /* caller_must_gc_arguments */),
135 _code(code),
136 _meta(meta),
137 _metadata_got((Metadata**) metadata_got),
138 _state_adr(state_adr),
139 _heap(heap),
140 _name(name),
141 _metadata_size(metadata_size),
142 _aot_id(aot_id),
143 _method_index(method_index) {
144
145 _is_far_code = CodeCache::is_far_target(code) ||
146 CodeCache::is_far_target(code + meta->code_size());
147 _exception_cache = NULL;
148
149 _scopes_data_begin = (address) _meta->scopes_data_begin();
150 _deopt_handler_begin = (address) _code + _meta->deopt_handler_offset();
151 _deopt_mh_handler_begin = (address) this;
152
153 _pc_desc_container.reset_to(scopes_pcs_begin());
154
155 // Mark the AOTCompiledMethod as in_use
156 *_state_adr = nmethod::in_use;
157 set_has_unsafe_access(_meta->has_unsafe_access());
158 _oop = NULL;
159 }
160
161 virtual bool is_aot() const { return true; }
162 virtual bool is_runtime_stub() const { return is_aot_runtime_stub(); }
163
164 virtual bool is_compiled() const { return !is_aot_runtime_stub(); }
165
166 virtual bool is_locked_by_vm() const { return false; }
167
168 int state() const { return *_state_adr; }
169
170 // Non-virtual for speed
171 bool _is_alive() const { return state() < zombie; }
172
173 virtual bool is_zombie() const { return state() == zombie; }
174 virtual bool is_unloaded() const { return state() == unloaded; }
175 virtual bool is_not_entrant() const { return state() == not_entrant ||
176 state() == not_used; }
177 virtual bool is_alive() const { return _is_alive(); }
178 virtual bool is_in_use() const { return state() == in_use; }
179
180 virtual bool is_unloading() { return false; }
181
182 address exception_begin() const { return (address) _code + _meta->exception_handler_offset(); }
183
184 virtual const char* name() const { return _name; }
185
186 virtual int compile_id() const { return _aot_id; }
187
188 void print_on(outputStream* st) const;
189 void print_on(outputStream* st, const char* msg) const;
190 void print() const;
191
192 virtual void print_value_on(outputStream *stream) const;
193 virtual void print_block_comment(outputStream *stream, address block_begin) const { }
194 virtual void verify() {}
195
196 virtual int comp_level() const { return CompLevel_aot; }
197 virtual address verified_entry_point() const { return _code + _meta->verified_entry_offset(); }
198 virtual void log_identity(xmlStream* stream) const;
199 virtual void log_state_change() const;
200 virtual bool make_entrant() NOT_TIERED({ ShouldNotReachHere(); return false; });
201 virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
202 virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
203 virtual address entry_point() const { return _code + _meta->entry_offset(); }
204 virtual bool make_zombie() { ShouldNotReachHere(); return false; }
205 virtual bool is_osr_method() const { return false; }
206 virtual int osr_entry_bci() const { ShouldNotReachHere(); return -1; }
207 // AOT compiled methods do not get into zombie state
208 virtual bool can_convert_to_zombie() { return false; }
209
210 virtual bool is_dependent_on_method(Method* dependee) { return true; }
211
212 virtual void clear_inline_caches();
213
214 virtual void print_pcs() {}
215
216 virtual address scopes_data_end() const { return _meta->scopes_data_end(); }
217
218 virtual oop oop_at(int index) const;
219 virtual Metadata* metadata_at(int index) const;
220
221 virtual PcDesc* scopes_pcs_begin() const { return _meta->scopes_pcs_begin(); }
222 virtual PcDesc* scopes_pcs_end() const { return _meta->scopes_pcs_end(); }
223
224 virtual address handler_table_begin() const { return _meta->handler_table_begin(); }
225 virtual address handler_table_end() const { return _meta->handler_table_end(); }
226
227 virtual address nul_chk_table_begin() const { return _meta->nul_chk_table_begin(); }
228 virtual address nul_chk_table_end() const { return _meta->nul_chk_table_end(); }
229
230 virtual address consts_begin() const { return _meta->consts_begin(); }
231 virtual address consts_end() const { return _meta->consts_end(); }
232
233 virtual address stub_begin() const { return code_begin() + _meta->stub_offset(); }
234 virtual address stub_end() const { return code_end(); }
235
236 virtual oop* oop_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
237 virtual Metadata** metadata_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
238
239 // Accessor/mutator for the original pc of a frame before a frame was deopted.
240 address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
241 void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
242
243 virtual void metadata_do(MetadataClosure* f);
244
245 bool metadata_got_contains(Metadata **p) {
246 return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
247 }
248
249 Metadata** metadata_begin() const { return &_metadata_got[0] ; }
250 Metadata** metadata_end() const { return &_metadata_got[_metadata_size] ; }
251 const char* compile_kind() const { return "AOT"; }
252
253 int get_state() const {
254 return (int) (*_state_adr);
255 }
256
257 // inlined and non-virtual for AOTCodeHeap::oops_do
258 void do_oops(OopClosure* f) {
259 assert(_is_alive(), "");
260 if (_oop != NULL) {
261 f->do_oop(&_oop);
262 }
263#if 0
264 metadata_oops_do(metadata_begin(), metadata_end(), f);
265#endif
266 }
267
268 virtual void do_unloading(bool unloading_occurred);
269
270protected:
271 // AOT compiled methods are not flushed
272 void flush() {};
273
274 NativeCallWrapper* call_wrapper_at(address call) const;
275 NativeCallWrapper* call_wrapper_before(address return_pc) const;
276 address call_instruction_address(address pc) const;
277
278 CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const;
279 CompiledStaticCall* compiledStaticCall_at(address addr) const;
280 CompiledStaticCall* compiledStaticCall_before(address addr) const;
281private:
282 bool is_aot_runtime_stub() const { return _method == NULL; }
283};
284
285class PltNativeCallWrapper: public NativeCallWrapper {
286private:
287 NativePltCall* _call;
288
289public:
290 PltNativeCallWrapper(NativePltCall* call) : _call(call) {}
291
292 virtual address destination() const { return _call->destination(); }
293 virtual address instruction_address() const { return _call->instruction_address(); }
294 virtual address next_instruction_address() const { return _call->next_instruction_address(); }
295 virtual address return_address() const { return _call->return_address(); }
296 virtual address get_resolve_call_stub(bool is_optimized) const { return _call->plt_resolve_call(); }
297 virtual void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
298 virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info);
299 virtual void verify() const { _call->verify(); }
300 virtual void verify_resolve_call(address dest) const;
301
302 virtual bool is_call_to_interpreted(address dest) const { return (dest == _call->plt_c2i_stub()); }
303 // TODO: assume for now that patching of aot code (got cell) is safe.
304 virtual bool is_safe_for_patching() const { return true; }
305
306 virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const;
307
308 virtual void *get_data(NativeInstruction* instruction) const {
309 return (void*)((NativeLoadGot*) instruction)->data();
310 }
311
312 virtual void set_data(NativeInstruction* instruction, intptr_t data) {
313 ((NativeLoadGot*) instruction)->set_data(data);
314 }
315};
316
317#endif // SHARE_AOT_AOTCOMPILEDMETHOD_HPP
318