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 
33 class AOTCodeHeap;
34 
35 class aot_metadata {
36 private:
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;
at_offset(size_t offset) const56   address at_offset(size_t offset) const { return ((address) this) + offset; }
57 public:
code_size() const58   int code_size() const { return _code_size; }
frame_size() const59   int frame_size() const { return _frame_size / HeapWordSize; }
scopes_pcs_begin() const60   PcDesc *scopes_pcs_begin() const { return (PcDesc *) at_offset(_pc_desc_begin); }
scopes_pcs_end() const61   PcDesc *scopes_pcs_end() const { return (PcDesc *) at_offset(_scopes_begin); }
scopes_data_begin() const62   address scopes_data_begin() const { return at_offset(_scopes_begin); }
scopes_data_end() const63   address scopes_data_end() const { return at_offset(_reloc_begin); }
relocation_begin() const64   relocInfo* relocation_begin() const { return (relocInfo*) at_offset(_reloc_begin); }
relocation_end() const65   relocInfo* relocation_end() const { return (relocInfo*) at_offset(_exception_table_begin); }
handler_table_begin() const66   address handler_table_begin   () const { return at_offset(_exception_table_begin); }
handler_table_end() const67   address handler_table_end() const { return at_offset(_nul_chk_table_begin); }
68 
nul_chk_table_begin() const69   address nul_chk_table_begin() const { return at_offset(_nul_chk_table_begin); }
nul_chk_table_end() const70   address nul_chk_table_end() const { return at_offset(_oopmap_begin); }
71 
oopmap_set() const72   ImmutableOopMapSet* oopmap_set() const { return (ImmutableOopMapSet*) at_offset(_oopmap_begin); }
73 
consts_begin() const74   address consts_begin() const { return at_offset(_size); }
consts_end() const75   address consts_end() const { return at_offset(_size); }
stub_offset() const76   int stub_offset() const { return _stubs_offset; }
entry_offset() const77   int entry_offset() const { return _entry; }
verified_entry_offset() const78   int verified_entry_offset() const { return _verified_entry; }
exception_handler_offset() const79   int exception_handler_offset() const { return _exception_handler_offset; }
deopt_handler_offset() const80   int deopt_handler_offset() const { return _deopt_handler_offset; }
orig_pc_offset() const81   int orig_pc_offset() const { return _orig_pc_offset; }
82 
handler_table_size() const83   int handler_table_size() const { return handler_table_end() - handler_table_begin(); }
nul_chk_table_size() const84   int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }
has_unsafe_access() const85   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... */
92 class AOTCompiledMethodLayout : public CodeBlobLayout {
93 public:
AOTCompiledMethodLayout(address code_begin,address code_end,address relocation_begin,address relocation_end)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 
107 class AOTCompiledMethod : public CompiledMethod, public CHeapObj<mtCode> {
108 private:
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 
method_index() const128   int method_index() const { return _method_index; }
set_oop(oop o)129   void set_oop(oop o) { _oop = o; }
130 
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)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 
is_aot() const161   virtual bool is_aot() const { return true; }
is_runtime_stub() const162   virtual bool is_runtime_stub() const { return is_aot_runtime_stub(); }
163 
is_compiled() const164   virtual bool is_compiled() const     { return !is_aot_runtime_stub(); }
165 
is_locked_by_vm() const166   virtual bool is_locked_by_vm() const { return false; }
167 
state() const168   int state() const { return *_state_adr; }
169 
170   // Non-virtual for speed
_is_alive() const171   bool _is_alive() const { return state() < unloaded; }
172 
is_zombie() const173   virtual bool is_zombie() const { return state() == zombie; }
is_unloaded() const174   virtual bool is_unloaded() const { return state() == unloaded; }
is_not_entrant() const175   virtual bool is_not_entrant() const { return state() == not_entrant ||
176                                                  state() == not_used; }
is_alive() const177   virtual bool is_alive() const { return _is_alive(); }
is_in_use() const178   virtual bool is_in_use() const { return state() == in_use; }
179 
is_unloading()180   virtual bool is_unloading() { return false; }
181 
exception_begin() const182   address exception_begin() const { return (address) _code + _meta->exception_handler_offset(); }
183 
name() const184   virtual const char* name() const { return _name; }
185 
compile_id() const186   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;
print_block_comment(outputStream * stream,address block_begin) const193   virtual void print_block_comment(outputStream *stream, address block_begin) const { }
verify()194   virtual void verify() {}
195 
comp_level() const196   virtual int comp_level() const { return CompLevel_aot; }
verified_entry_point() const197   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; });
make_not_entrant()201   virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
make_not_used()202   virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
entry_point() const203   virtual address entry_point() const { return _code + _meta->entry_offset(); }
make_zombie()204   virtual bool make_zombie() { ShouldNotReachHere(); return false; }
is_osr_method() const205   virtual bool is_osr_method() const { return false; }
osr_entry_bci() const206   virtual int osr_entry_bci() const { ShouldNotReachHere(); return -1; }
207   // AOT compiled methods do not get into zombie state
can_convert_to_zombie()208   virtual bool can_convert_to_zombie() { return false; }
209 
is_dependent_on_method(Method * dependee)210   virtual bool is_dependent_on_method(Method* dependee) { return true; }
211 
212   virtual void clear_inline_caches();
213 
print_pcs()214   virtual void print_pcs() {}
215 
scopes_data_end() const216   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 
scopes_pcs_begin() const221   virtual PcDesc* scopes_pcs_begin() const { return _meta->scopes_pcs_begin(); }
scopes_pcs_end() const222   virtual PcDesc* scopes_pcs_end() const { return _meta->scopes_pcs_end(); }
223 
handler_table_begin() const224   virtual address handler_table_begin() const { return _meta->handler_table_begin(); }
handler_table_end() const225   virtual address handler_table_end() const { return _meta->handler_table_end(); }
226 
nul_chk_table_begin() const227   virtual address nul_chk_table_begin() const { return _meta->nul_chk_table_begin(); }
nul_chk_table_end() const228   virtual address nul_chk_table_end() const { return _meta->nul_chk_table_end(); }
229 
consts_begin() const230   virtual address consts_begin() const { return _meta->consts_begin(); }
consts_end() const231   virtual address consts_end() const { return _meta->consts_end(); }
232 
stub_begin() const233   virtual address stub_begin() const { return code_begin() + _meta->stub_offset(); }
stub_end() const234   virtual address stub_end() const { return code_end(); }
235 
oop_addr_at(int index) const236   virtual oop* oop_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
metadata_addr_at(int index) const237   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.
get_original_pc(const frame * fr)240   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
set_original_pc(const frame * fr,address pc)241   void    set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
242 
243   virtual void metadata_do(MetadataClosure* f);
244 
metadata_got_contains(Metadata ** p)245   bool metadata_got_contains(Metadata **p) {
246     return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
247   }
248 
metadata_begin() const249   Metadata** metadata_begin() const { return &_metadata_got[0] ; }
metadata_end() const250   Metadata** metadata_end()   const { return &_metadata_got[_metadata_size] ; }
compile_kind() const251   const char* compile_kind() const { return "AOT"; }
252 
get_state() const253   int get_state() const {
254     return (int) (*_state_adr);
255   }
256 
257   // inlined and non-virtual for AOTCodeHeap::oops_do
do_oops(OopClosure * f)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 
270 protected:
271   // AOT compiled methods are not flushed
flush()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;
281 private:
is_aot_runtime_stub() const282   bool is_aot_runtime_stub() const { return _method == NULL; }
283 };
284 
285 class PltNativeCallWrapper: public NativeCallWrapper {
286 private:
287   NativePltCall* _call;
288 
289 public:
PltNativeCallWrapper(NativePltCall * call)290   PltNativeCallWrapper(NativePltCall* call) : _call(call) {}
291 
destination() const292   virtual address destination() const { return _call->destination(); }
instruction_address() const293   virtual address instruction_address() const { return _call->instruction_address(); }
next_instruction_address() const294   virtual address next_instruction_address() const { return _call->next_instruction_address(); }
return_address() const295   virtual address return_address() const { return _call->return_address(); }
get_resolve_call_stub(bool is_optimized) const296   virtual address get_resolve_call_stub(bool is_optimized) const { return _call->plt_resolve_call(); }
set_destination_mt_safe(address dest)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);
verify() const299   virtual void verify() const { _call->verify(); }
300   virtual void verify_resolve_call(address dest) const;
301 
is_call_to_interpreted(address dest) const302   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.
is_safe_for_patching() const304   virtual bool is_safe_for_patching() const { return true; }
305 
306   virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const;
307 
get_data(NativeInstruction * instruction) const308   virtual void *get_data(NativeInstruction* instruction) const {
309     return (void*)((NativeLoadGot*) instruction)->data();
310   }
311 
set_data(NativeInstruction * instruction,intptr_t data)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