Path: blob/master/src/hotspot/share/code/compiledMethod.hpp
40931 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_CODE_COMPILEDMETHOD_HPP25#define SHARE_CODE_COMPILEDMETHOD_HPP2627#include "code/codeBlob.hpp"28#include "code/pcDesc.hpp"29#include "oops/metadata.hpp"30#include "oops/method.hpp"3132class Dependencies;33class ExceptionHandlerTable;34class ImplicitExceptionTable;35class AbstractCompiler;36class xmlStream;37class CompiledStaticCall;38class NativeCallWrapper;39class ScopeDesc;40class CompiledIC;41class MetadataClosure;4243// This class is used internally by nmethods, to cache44// exception/pc/handler information.4546class ExceptionCache : public CHeapObj<mtCode> {47friend class VMStructs;48private:49enum { cache_size = 16 };50Klass* _exception_type;51address _pc[cache_size];52address _handler[cache_size];53volatile int _count;54ExceptionCache* volatile _next;55ExceptionCache* _purge_list_next;5657inline address pc_at(int index);58void set_pc_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _pc[index] = a; }5960inline address handler_at(int index);61void set_handler_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _handler[index] = a; }6263inline int count();64// increment_count is only called under lock, but there may be concurrent readers.65void increment_count();6667public:6869ExceptionCache(Handle exception, address pc, address handler);7071Klass* exception_type() { return _exception_type; }72ExceptionCache* next();73void set_next(ExceptionCache *ec);74ExceptionCache* purge_list_next() { return _purge_list_next; }75void set_purge_list_next(ExceptionCache *ec) { _purge_list_next = ec; }7677address match(Handle exception, address pc);78bool match_exception_with_space(Handle exception) ;79address test_address(address addr);80bool add_address_and_handler(address addr, address handler) ;81};8283class nmethod;8485// cache pc descs found in earlier inquiries86class PcDescCache {87friend class VMStructs;88private:89enum { cache_size = 4 };90// The array elements MUST be volatile! Several threads may modify91// and read from the cache concurrently. find_pc_desc_internal has92// returned wrong results. C++ compiler (namely xlC12) may duplicate93// C++ field accesses if the elements are not volatile.94typedef PcDesc* PcDescPtr;95volatile PcDescPtr _pc_descs[cache_size]; // last cache_size pc_descs found96public:97PcDescCache() { debug_only(_pc_descs[0] = NULL); }98void reset_to(PcDesc* initial_pc_desc);99PcDesc* find_pc_desc(int pc_offset, bool approximate);100void add_pc_desc(PcDesc* pc_desc);101PcDesc* last_pc_desc() { return _pc_descs[0]; }102};103104class PcDescSearch {105private:106address _code_begin;107PcDesc* _lower;108PcDesc* _upper;109public:110PcDescSearch(address code, PcDesc* lower, PcDesc* upper) :111_code_begin(code), _lower(lower), _upper(upper)112{113}114115address code_begin() const { return _code_begin; }116PcDesc* scopes_pcs_begin() const { return _lower; }117PcDesc* scopes_pcs_end() const { return _upper; }118};119120class PcDescContainer {121private:122PcDescCache _pc_desc_cache;123public:124PcDescContainer() {}125126PcDesc* find_pc_desc_internal(address pc, bool approximate, const PcDescSearch& search);127void reset_to(PcDesc* initial_pc_desc) { _pc_desc_cache.reset_to(initial_pc_desc); }128129PcDesc* find_pc_desc(address pc, bool approximate, const PcDescSearch& search) {130address base_address = search.code_begin();131PcDesc* desc = _pc_desc_cache.last_pc_desc();132if (desc != NULL && desc->pc_offset() == pc - base_address) {133return desc;134}135return find_pc_desc_internal(pc, approximate, search);136}137};138139140class CompiledMethod : public CodeBlob {141friend class VMStructs;142friend class NMethodSweeper;143144void init_defaults();145protected:146enum MarkForDeoptimizationStatus {147not_marked,148deoptimize,149deoptimize_noupdate150};151152MarkForDeoptimizationStatus _mark_for_deoptimization_status; // Used for stack deoptimization153154// set during construction155unsigned int _has_unsafe_access:1; // May fault due to unsafe access.156unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes?157unsigned int _has_wide_vectors:1; // Preserve wide vectors at safepoints158159Method* _method;160address _scopes_data_begin;161// All deoptee's will resume execution at this location described by162// this address.163address _deopt_handler_begin;164// All deoptee's at a MethodHandle call site will resume execution165// at this location described by this offset.166address _deopt_mh_handler_begin;167168PcDescContainer _pc_desc_container;169ExceptionCache * volatile _exception_cache;170171void* _gc_data;172173virtual void flush() = 0;174protected:175CompiledMethod(Method* method, const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments);176CompiledMethod(Method* method, const char* name, CompilerType type, int size, int header_size, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);177178public:179// Only used by unit test.180CompiledMethod() {}181182virtual bool is_compiled() const { return true; }183184template<typename T>185T* gc_data() const { return reinterpret_cast<T*>(_gc_data); }186template<typename T>187void set_gc_data(T* gc_data) { _gc_data = reinterpret_cast<void*>(gc_data); }188189bool has_unsafe_access() const { return _has_unsafe_access; }190void set_has_unsafe_access(bool z) { _has_unsafe_access = z; }191192bool has_method_handle_invokes() const { return _has_method_handle_invokes; }193void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }194195bool has_wide_vectors() const { return _has_wide_vectors; }196void set_has_wide_vectors(bool z) { _has_wide_vectors = z; }197198enum { not_installed = -1, // in construction, only the owner doing the construction is199// allowed to advance state200in_use = 0, // executable nmethod201not_used = 1, // not entrant, but revivable202not_entrant = 2, // marked for deoptimization but activations may still exist,203// will be transformed to zombie when all activations are gone204unloaded = 3, // there should be no activations, should not be called, will be205// transformed to zombie by the sweeper, when not "locked in vm".206zombie = 4 // no activations exist, nmethod is ready for purge207};208209virtual bool is_in_use() const = 0;210virtual int comp_level() const = 0;211virtual int compile_id() const = 0;212213virtual address verified_entry_point() const = 0;214virtual void log_identity(xmlStream* log) const = 0;215virtual void log_state_change() const = 0;216virtual bool make_not_used() = 0;217virtual bool make_not_entrant() = 0;218virtual bool make_entrant() = 0;219virtual address entry_point() const = 0;220virtual bool make_zombie() = 0;221virtual bool is_osr_method() const = 0;222virtual int osr_entry_bci() const = 0;223Method* method() const { return _method; }224virtual void print_pcs() = 0;225bool is_native_method() const { return _method != NULL && _method->is_native(); }226bool is_java_method() const { return _method != NULL && !_method->is_native(); }227228// ScopeDesc retrieval operation229PcDesc* pc_desc_at(address pc) { return find_pc_desc(pc, false); }230// pc_desc_near returns the first PcDesc at or after the given pc.231PcDesc* pc_desc_near(address pc) { return find_pc_desc(pc, true); }232233// ScopeDesc for an instruction234ScopeDesc* scope_desc_at(address pc);235ScopeDesc* scope_desc_near(address pc);236237bool is_at_poll_return(address pc);238bool is_at_poll_or_poll_return(address pc);239240bool is_marked_for_deoptimization() const { return _mark_for_deoptimization_status != not_marked; }241void mark_for_deoptimization(bool inc_recompile_counts = true);242243bool update_recompile_counts() const {244// Update recompile counts when either the update is explicitly requested (deoptimize)245// or the nmethod is not marked for deoptimization at all (not_marked).246// The latter happens during uncommon traps when deoptimized nmethod is made not entrant.247return _mark_for_deoptimization_status != deoptimize_noupdate;248}249250// tells whether frames described by this nmethod can be deoptimized251// note: native wrappers cannot be deoptimized.252bool can_be_deoptimized() const { return is_java_method(); }253254virtual oop oop_at(int index) const = 0;255virtual Metadata* metadata_at(int index) const = 0;256257address scopes_data_begin() const { return _scopes_data_begin; }258virtual address scopes_data_end() const = 0;259int scopes_data_size() const { return scopes_data_end() - scopes_data_begin(); }260261virtual PcDesc* scopes_pcs_begin() const = 0;262virtual PcDesc* scopes_pcs_end() const = 0;263int scopes_pcs_size() const { return (intptr_t) scopes_pcs_end() - (intptr_t) scopes_pcs_begin(); }264265address insts_begin() const { return code_begin(); }266address insts_end() const { return stub_begin(); }267// Returns true if a given address is in the 'insts' section. The method268// insts_contains_inclusive() is end-inclusive.269bool insts_contains(address addr) const { return insts_begin() <= addr && addr < insts_end(); }270bool insts_contains_inclusive(address addr) const { return insts_begin() <= addr && addr <= insts_end(); }271272int insts_size() const { return insts_end() - insts_begin(); }273274virtual address consts_begin() const = 0;275virtual address consts_end() const = 0;276bool consts_contains(address addr) const { return consts_begin() <= addr && addr < consts_end(); }277int consts_size() const { return consts_end() - consts_begin(); }278279virtual address stub_begin() const = 0;280virtual address stub_end() const = 0;281bool stub_contains(address addr) const { return stub_begin() <= addr && addr < stub_end(); }282int stub_size() const { return stub_end() - stub_begin(); }283284virtual address handler_table_begin() const = 0;285virtual address handler_table_end() const = 0;286bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); }287int handler_table_size() const { return handler_table_end() - handler_table_begin(); }288289virtual address exception_begin() const = 0;290291virtual address nul_chk_table_begin() const = 0;292virtual address nul_chk_table_end() const = 0;293bool nul_chk_table_contains(address addr) const { return nul_chk_table_begin() <= addr && addr < nul_chk_table_end(); }294int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); }295296virtual oop* oop_addr_at(int index) const = 0;297virtual Metadata** metadata_addr_at(int index) const = 0;298virtual void set_original_pc(const frame* fr, address pc) = 0;299300protected:301// Exception cache support302// Note: _exception_cache may be read and cleaned concurrently.303ExceptionCache* exception_cache() const { return _exception_cache; }304ExceptionCache* exception_cache_acquire() const;305void set_exception_cache(ExceptionCache *ec) { _exception_cache = ec; }306307public:308address handler_for_exception_and_pc(Handle exception, address pc);309void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);310void clean_exception_cache();311312void add_exception_cache_entry(ExceptionCache* new_entry);313ExceptionCache* exception_cache_entry_for_exception(Handle exception);314315// MethodHandle316bool is_method_handle_return(address return_pc);317address deopt_mh_handler_begin() const { return _deopt_mh_handler_begin; }318319address deopt_handler_begin() const { return _deopt_handler_begin; }320virtual address get_original_pc(const frame* fr) = 0;321// Deopt322// Return true is the PC is one would expect if the frame is being deopted.323inline bool is_deopt_pc(address pc);324inline bool is_deopt_mh_entry(address pc);325inline bool is_deopt_entry(address pc);326327virtual bool can_convert_to_zombie() = 0;328virtual const char* compile_kind() const = 0;329virtual int get_state() const = 0;330331const char* state() const;332333bool inlinecache_check_contains(address addr) const {334return (addr >= code_begin() && addr < verified_entry_point());335}336337void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f);338339// implicit exceptions support340address continuation_for_implicit_div0_exception(address pc) { return continuation_for_implicit_exception(pc, true); }341address continuation_for_implicit_null_exception(address pc) { return continuation_for_implicit_exception(pc, false); }342343static address get_deopt_original_pc(const frame* fr);344345// Inline cache support for class unloading and nmethod unloading346private:347bool cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all);348349address continuation_for_implicit_exception(address pc, bool for_div0_check);350351public:352// Serial version used by sweeper and whitebox test353void cleanup_inline_caches(bool clean_all);354355virtual void clear_inline_caches();356void clear_ic_callsites();357358// Execute nmethod barrier code, as if entering through nmethod call.359void run_nmethod_entry_barrier();360361// Verify and count cached icholder relocations.362int verify_icholder_relocations();363void verify_oop_relocations();364365bool has_evol_metadata();366367// Fast breakpoint support. Tells if this compiled method is368// dependent on the given method. Returns true if this nmethod369// corresponds to the given method as well.370virtual bool is_dependent_on_method(Method* dependee) = 0;371372virtual NativeCallWrapper* call_wrapper_at(address call) const = 0;373virtual NativeCallWrapper* call_wrapper_before(address return_pc) const = 0;374virtual address call_instruction_address(address pc) const = 0;375376virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const = 0;377virtual CompiledStaticCall* compiledStaticCall_at(address addr) const = 0;378virtual CompiledStaticCall* compiledStaticCall_before(address addr) const = 0;379380Method* attached_method(address call_pc);381Method* attached_method_before_pc(address pc);382383virtual void metadata_do(MetadataClosure* f) = 0;384385// GC support386protected:387address oops_reloc_begin() const;388389private:390bool static clean_ic_if_metadata_is_dead(CompiledIC *ic);391392public:393// GC unloading support394// Cleans unloaded klasses and unloaded nmethods in inline caches395396virtual bool is_unloading() = 0;397398bool unload_nmethod_caches(bool class_unloading_occurred);399virtual void do_unloading(bool unloading_occurred) = 0;400401private:402PcDesc* find_pc_desc(address pc, bool approximate) {403return _pc_desc_container.find_pc_desc(pc, approximate, PcDescSearch(code_begin(), scopes_pcs_begin(), scopes_pcs_end()));404}405};406407#endif // SHARE_CODE_COMPILEDMETHOD_HPP408409410