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;
  56   address at_offset(size_t offset) const { return ((address) this) + offset; }
  57 public:
  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... */
  92 class AOTCompiledMethodLayout : public CodeBlobLayout {
  93 public:
  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   bool make_not_entrant_helper(int new_state);
 122 
 123  public:
 124   using CHeapObj<mtCode>::operator new;
 125   using CHeapObj<mtCode>::operator delete;
 126 
 127   int method_index() const { return _method_index; }
 128   void set_oop(oop o) { _oop = o; }
 129 
 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     CompiledMethod(method, name, compiler_jvmci, // AOT code is generated by JVMCI compiler
 132         AOTCompiledMethodLayout(code, code + meta->code_size(), (address) meta->relocation_begin(), (address) meta->relocation_end()),
 133         0 /* frame_complete_offset */, meta->frame_size() /* frame_size */, meta->oopmap_set(), false /* caller_must_gc_arguments */,
 134         method != NULL /* compiled */),
 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_locked_by_vm() const { return false; }
 165 
 166   int state() const { return *_state_adr; }
 167 
 168   // Non-virtual for speed
 169   bool _is_alive() const { return state() < unloaded; }
 170 
 171   virtual bool is_zombie() const { return state() == zombie; }
 172   virtual bool is_unloaded() const { return state() == unloaded; }
 173   virtual bool is_not_entrant() const { return state() == not_entrant ||
 174                                                  state() == not_used; }
 175   virtual bool is_alive() const { return _is_alive(); }
 176   virtual bool is_in_use() const { return state() == in_use; }
 177 
 178   virtual bool is_unloading() { return false; }
 179 
 180   address exception_begin() const { return (address) _code + _meta->exception_handler_offset(); }
 181 
 182   virtual const char* name() const { return _name; }
 183 
 184   virtual int compile_id() const { return _aot_id; }
 185 
 186   void print_on(outputStream* st) const;
 187   void print_on(outputStream* st, const char* msg) const;
 188   void print() const;
 189 
 190   virtual void print_value_on(outputStream *stream) const;
 191   virtual void print_block_comment(outputStream *stream, address block_begin) const { }
 192   virtual void verify() {}
 193 
 194   virtual int comp_level() const { return CompLevel_aot; }
 195   virtual address verified_entry_point() const { return _code + _meta->verified_entry_offset(); }
 196   virtual void log_identity(xmlStream* stream) const;
 197   virtual void log_state_change() const;
 198   virtual bool make_entrant() NOT_TIERED({ ShouldNotReachHere(); return false; });
 199   virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
 200   virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
 201   virtual address entry_point() const { return _code + _meta->entry_offset(); }
 202   virtual bool make_zombie() { ShouldNotReachHere(); return false; }
 203   virtual bool is_osr_method() const { return false; }
 204   virtual int osr_entry_bci() const { ShouldNotReachHere(); return -1; }
 205   // AOT compiled methods do not get into zombie state
 206   virtual bool can_convert_to_zombie() { return false; }
 207 
 208   virtual bool is_dependent_on_method(Method* dependee) { return true; }
 209 
 210   virtual void clear_inline_caches();
 211 
 212   virtual void print_pcs() {}
 213 
 214   virtual address scopes_data_end() const { return _meta->scopes_data_end(); }
 215 
 216   virtual oop oop_at(int index) const;
 217   virtual Metadata* metadata_at(int index) const;
 218 
 219   virtual PcDesc* scopes_pcs_begin() const { return _meta->scopes_pcs_begin(); }
 220   virtual PcDesc* scopes_pcs_end() const { return _meta->scopes_pcs_end(); }
 221 
 222   virtual address handler_table_begin() const { return _meta->handler_table_begin(); }
 223   virtual address handler_table_end() const { return _meta->handler_table_end(); }
 224 
 225   virtual address nul_chk_table_begin() const { return _meta->nul_chk_table_begin(); }
 226   virtual address nul_chk_table_end() const { return _meta->nul_chk_table_end(); }
 227 
 228   virtual address consts_begin() const { return _meta->consts_begin(); }
 229   virtual address consts_end() const { return _meta->consts_end(); }
 230 
 231   virtual address stub_begin() const { return code_begin() + _meta->stub_offset(); }
 232   virtual address stub_end() const { return code_end(); }
 233 
 234   virtual oop* oop_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
 235   virtual Metadata** metadata_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
 236 
 237   virtual void metadata_do(MetadataClosure* f);
 238 
 239   int orig_pc_offset() { return _meta->orig_pc_offset(); }
 240   
 241   bool metadata_got_contains(Metadata **p) {
 242     return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
 243   }
 244 
 245   Metadata** metadata_begin() const { return &_metadata_got[0] ; }
 246   Metadata** metadata_end()   const { return &_metadata_got[_metadata_size] ; }
 247   const char* compile_kind() const { return "AOT"; }
 248 
 249   int get_state() const {
 250     return (int) (*_state_adr);
 251   }
 252 
 253   // inlined and non-virtual for AOTCodeHeap::oops_do
 254   void do_oops(OopClosure* f) {
 255     assert(_is_alive(), "");
 256     if (_oop != NULL) {
 257       f->do_oop(&_oop);
 258     }
 259 #if 0
 260     metadata_oops_do(metadata_begin(), metadata_end(), f);
 261 #endif
 262   }
 263 
 264   virtual void do_unloading(bool unloading_occurred);
 265 
 266 protected:
 267   // AOT compiled methods are not flushed
 268   void flush() {};
 269 
 270   NativeCallWrapper* call_wrapper_at(address call) const;
 271   NativeCallWrapper* call_wrapper_before(address return_pc) const;
 272   address call_instruction_address(address pc) const;
 273 
 274   CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const;
 275   CompiledStaticCall* compiledStaticCall_at(address addr) const;
 276   CompiledStaticCall* compiledStaticCall_before(address addr) const;
 277 private:
 278   bool is_aot_runtime_stub() const { return _method == NULL; }
 279 };
 280 
 281 class PltNativeCallWrapper: public NativeCallWrapper {
 282 private:
 283   NativePltCall* _call;
 284 
 285 public:
 286   PltNativeCallWrapper(NativePltCall* call) : _call(call) {}
 287 
 288   virtual address destination() const { return _call->destination(); }
 289   virtual address instruction_address() const { return _call->instruction_address(); }
 290   virtual address next_instruction_address() const { return _call->next_instruction_address(); }
 291   virtual address return_address() const { return _call->return_address(); }
 292   virtual address get_resolve_call_stub(bool is_optimized) const { return _call->plt_resolve_call(); }
 293   virtual void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
 294   virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info);
 295   virtual void verify() const { _call->verify(); }
 296   virtual void verify_resolve_call(address dest) const;
 297 
 298   virtual bool is_call_to_interpreted(address dest) const { return (dest == _call->plt_c2i_stub()); }
 299   // TODO: assume for now that patching of aot code (got cell) is safe.
 300   virtual bool is_safe_for_patching() const { return true; }
 301 
 302   virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const;
 303 
 304   virtual void *get_data(NativeInstruction* instruction) const {
 305     return (void*)((NativeLoadGot*) instruction)->data();
 306   }
 307 
 308   virtual void set_data(NativeInstruction* instruction, intptr_t data) {
 309     ((NativeLoadGot*) instruction)->set_data(data);
 310   }
 311 };
 312 
 313 #endif // SHARE_AOT_AOTCOMPILEDMETHOD_HPP