/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_OOPS_METHODOOP_HPP
#define SHARE_VM_OOPS_METHODOOP_HPP
#include "classfile/vmSymbols.hpp"
#include "code/compressedStream.hpp"
#include "compiler/oopMap.hpp"
#include "interpreter/invocationCounter.hpp"
#include "oops/constMethodOop.hpp"
#include "oops/constantPoolOop.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/typeArrayOop.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/growableArray.hpp"
// A methodOop represents a Java method.
//
// Memory layout (each line represents a word). Note that most applications load thousands of methods,
// so keeping the size of this structure small has a big impact on footprint.
//
// We put all oops and method_size first for better gc cache locality.
//
// The actual bytecodes are inlined after the end of the methodOopDesc struct.
//
// There are bits in the access_flags telling whether inlined tables are present.
// Note that accessing the line number and local variable tables is not performance critical at all.
// Accessing the checked exceptions table is used by reflection, so we put that last to make access
// to it fast.
//
// The line number table is compressed and inlined following the byte codes. It is found as the first
// byte following the byte codes. The checked exceptions table and the local variable table are inlined
// after the line number table, and indexed from the end of the method. We do not compress the checked
// exceptions table since the average length is less than 2, and do not bother to compress the local
// variable table either since it is mostly absent.
//
// Note that native_function and signature_handler has to be at fixed offsets (required by the interpreter)
//
// |------------------------------------------------------|
// | header |
// | klass |
// |------------------------------------------------------|
// | constMethodOop (oop) |
// |------------------------------------------------------|
// | methodData (oop) |
// | interp_invocation_count |
// |------------------------------------------------------|
// | access_flags |
// | vtable_index |
// |------------------------------------------------------|
// | result_index (C++ interpreter only) |
// |------------------------------------------------------|
// | method_size | max_stack |
// | max_locals | size_of_parameters |
// |------------------------------------------------------|
// |intrinsic_id| flags | throwout_count |
// |------------------------------------------------------|
// | num_breakpoints | (unused) |
// |------------------------------------------------------|
// | invocation_counter |
// | backedge_counter |
// |------------------------------------------------------|
// | prev_time (tiered only, 64 bit wide) |
// | |
// |------------------------------------------------------|
// | rate (tiered) |
// |------------------------------------------------------|
// | code (pointer) |
// | i2i (pointer) |
// | adapter (pointer) |
// | from_compiled_entry (pointer) |
// | from_interpreted_entry (pointer) |
// |------------------------------------------------------|
// | native_function (present only if native) |
// | signature_handler (present only if native) |
// |------------------------------------------------------|
class CheckedExceptionElement;
class LocalVariableTableElement;
class AdapterHandlerEntry;
class methodDataOopDesc;
friend class methodKlass;
friend class VMStructs;
private:
// note: can have vtables with >2**16 elements (because of inheritance)
#ifdef CC_INTERP
#endif
_force_inline : 1,
_hidden : 1,
_dont_inline : 1,
: 4;
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations
#ifdef TIERED
#endif
#ifndef PRODUCT
#endif
// Entry point for calling both from and to the interpreter.
// Entry point for calling from compiled code, to compiled code if it exists
// or else the interpreter.
volatile address _from_compiled_entry; // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry()
// The entry point for calling both from and to compiled code is
// "_code->entry_point()". Because of tiered compilation and de-opt, this
// field can come and go. It can transition from NULL to not-null at any
// time (whenever a compile completes). It can transition from not-null to
// NULL only at safepoints (because of a de-opt).
public:
// accessors for instance variables
void set_constMethod(constMethodOop xconst) { oop_store_without_check((oop*)&_constMethod, (oop)xconst); }
volatile address from_compiled_entry() const { return (address)OrderAccess::load_ptr_acquire(&_from_compiled_entry); }
volatile address from_interpreted_entry() const{ return (address)OrderAccess::load_ptr_acquire(&_from_interpreted_entry); }
// access flag
// name
// signature
// generics support
Symbol* generic_signature() const { int idx = generic_signature_index(); return ((idx != 0) ? constants()->symbol_at(idx) : (Symbol*)NULL); }
// annotations support
typeArrayOop annotations() const { return instanceKlass::cast(method_holder())->get_method_annotations_of(method_idnum()); }
typeArrayOop parameter_annotations() const { return instanceKlass::cast(method_holder())->get_method_parameter_annotations_of(method_idnum()); }
typeArrayOop annotation_default() const { return instanceKlass::cast(method_holder())->get_method_default_annotations_of(method_idnum()); }
#ifdef CC_INTERP
#endif
// Helper routine: get klass name + "." + method name + signature as
// C string, for the purpose of providing more useful NoSuchMethodErrors
// and fatal error handling. The string is allocated in resource
// area if a buffer is not provided by the caller.
char* name_and_sig_as_C_string() const;
// Static routine in the situations we don't have a methodOop
static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size);
}
}
// JVMTI breakpoints
void set_breakpoint(int bci);
void clear_breakpoint(int bci);
void clear_all_breakpoints();
// Tracking number of breakpoints, for fullspeed debugging.
// Only mutated by VM thread.
// Initialization only
// index into instanceKlass methods() array
// note: also used by jfr
// code size
// method size
_method_size = size;
}
// constant pool for klassOop holding this method
// max stack
// return original max stack size for method verification
// max locals
int highest_comp_level() const;
void set_highest_comp_level(int level);
int highest_osr_comp_level() const;
void set_highest_osr_comp_level(int level);
// Count of times method was exited via exception while interpreting
void interpreter_throwout_increment() {
if (_interpreter_throwout_count < 65534) {
}
}
// size of parameters
bool has_stackmap_table() const {
return constMethod()->has_stackmap_table();
}
return constMethod()->stackmap_data();
}
}
// exception handler table
bool has_exception_handler() const
{ return constMethod()->has_exception_handler(); }
int exception_table_length() const
{ return constMethod()->exception_table_length(); }
{ return constMethod()->exception_table_start(); }
// Finds the first entry point bci of an exception handler for an
// exception of klass ex_klass thrown at throw_bci. A value of NULL
// for ex_klass indicates that the exception klass is not known; in
// this case it matches any constraint class. Returns -1 if the
// exception cannot be handled in this method. The handler
// constraint classes are loaded if necessary. Note that this may
// throw an exception if loading of the constraint classes causes
// an IllegalAccessError (bugid 4307310) or an OutOfMemoryError.
// If an exception is thrown, returns the bci of the
// exception handler which caused the exception to be thrown, which
// is needed for proper retries. See, for example,
// InterpreterRuntime::exception_handler_for_exception.
static int fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS);
// method data access
return _method_data;
}
}
// invocation counter
#ifdef TIERED
// We are reusing interpreter_invocation_count as a holder for the previous event count!
// We can do that since interpreter_invocation_count is not used in tiered.
#endif
int invocation_count();
int backedge_count();
bool was_executed_more_than(int n);
int interpreter_invocation_count() {
if (TieredCompilation) return invocation_count();
else return _interpreter_invocation_count;
}
if (TieredCompilation) ShouldNotReachHere();
return ++_interpreter_invocation_count;
}
#ifndef PRODUCT
#endif // not PRODUCT
// Clear (non-shared space) pointers which could not be relevant
// if this (shared) method were mapped into another JVM.
void remove_unshareable_info();
bool check_code() const; // Not inline to avoid circular ref
nmethod* volatile code() const { assert( check_code(), "" ); return (nmethod *)OrderAccess::load_ptr_acquire(&_code); }
void clear_code(); // Clear out any compiled code
// setup entry points
// clear entry points. Used by sharing code
void unlink_method();
// vtable index
enum VtableIndexFlag {
// Valid vtable indexes are non-negative (>= 0).
// These few negative values are used as sentinels.
// 6330203 Note: Do not use -1, which was overloaded with many meanings.
};
return _vtable_index; }
// interpreter entry
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
int interpreter_kind(void) {
return constMethod()->interpreter_kind();
}
void set_interpreter_kind();
}
// native function (used for native methods only)
enum {
};
// Must specify a real function (not NULL).
// Use clear_native_function() to unregister.
bool has_native_function() const;
void clear_native_function();
// signature handler (used for native methods only)
// Interpreter oopmap support
#ifndef PRODUCT
// operations on invocation counter
void print_invocation_count();
#endif
// byte codes
// prints byte codes
// checked exceptions
int checked_exceptions_length() const
{ return constMethod()->checked_exceptions_length(); }
{ return constMethod()->checked_exceptions_start(); }
// localvariable table
bool has_localvariable_table() const
{ return constMethod()->has_localvariable_table(); }
int localvariable_table_length() const
{ return constMethod()->localvariable_table_length(); }
{ return constMethod()->localvariable_table_start(); }
bool has_linenumber_table() const
{ return constMethod()->has_linenumber_table(); }
{ return constMethod()->compressed_linenumber_table(); }
// method holder (the klassOop holding this method)
void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments)
int result_type_index() const; // type index of the method result
bool is_returning_oop() const { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); }
bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); }
// Checked exceptions thrown by this method (resolved to mirrors)
objArrayHandle resolved_checked_exceptions(TRAPS) { return resolved_checked_exceptions_impl(this, THREAD); }
// Access flags
// returns true if contains only return operation
bool is_empty_method() const;
// returns true if this is a vanilla constructor
bool is_vanilla_constructor() const;
// checks method and its method holder
bool is_final_method() const;
bool is_strict_method() const;
bool can_be_statically_bound() const;
// returns true if the method has any backward branches.
bool has_loops() {
};
bool compute_has_loops_flag();
bool has_jsrs() {
return access_flags().has_jsrs();
};
void set_has_jsrs() {
}
// returns true if the method has any monitors.
// monitor matching. This returns a conservative estimate of whether the monitorenter/monitorexit bytecodes
// propererly nest in the method. It might return false, even though they actually nest properly, since the info.
// has not been computed yet.
bool is_accessor() const;
// returns true if the method is an initializer (<init> or <clinit>).
bool is_initializer() const;
// returns true if the method is static OR if the classfile version < 51
bool has_valid_initializer_flags() const;
// returns true if the method name is <clinit> and the method has
// valid static initializer flags.
bool is_static_initializer() const;
// compiled code support
// NOTE: code() is inherently racy as deopt can be clearing code
// simultaneously. Use with caution.
// sizing
static int object_size(bool is_native);
// interpreter support
#ifdef CC_INTERP
#endif /* CC_INTERP */
static ByteSize size_of_parameters_offset() { return byte_offset_of(methodOopDesc, _size_of_parameters); }
static ByteSize from_compiled_offset() { return byte_offset_of(methodOopDesc, _from_compiled_entry); }
static ByteSize invocation_counter_offset() { return byte_offset_of(methodOopDesc, _invocation_counter); }
static ByteSize backedge_counter_offset() { return byte_offset_of(methodOopDesc, _backedge_counter); }
}
static ByteSize interpreter_invocation_counter_offset() { return byte_offset_of(methodOopDesc, _interpreter_invocation_count); }
#ifndef PRODUCT
static ByteSize compiled_invocation_counter_offset() { return byte_offset_of(methodOopDesc, _compiled_invocation_count); }
#endif // not PRODUCT
static ByteSize from_interpreted_offset() { return byte_offset_of(methodOopDesc, _from_interpreted_entry ); }
static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(methodOopDesc) + wordSize); }
// for code generation
static int interpreter_invocation_counter_offset_in_bytes()
// Static methods that are used to implement member methods where an exposed this pointer
// is needed due to possible GCs
// Returns the byte code index from the byte code pointer
// Returns the line number for a bci if debugging information for the method is prowided,
// -1 is returned otherwise.
int line_number_from_bci(int bci) const;
// Reflection support
bool is_overridden_in(klassOop k) const;
// JSR 292 support
bool is_method_handle_intrinsic() const; // MethodHandles::is_signature_polymorphic_intrinsic(intrinsic_id)
bool is_compiled_lambda_form() const; // intrinsic_id() == vmIntrinsics::_compiledLambdaForm
bool has_member_arg() const; // intrinsic_id() == vmIntrinsics::_linkToSpecial, etc.
static methodHandle make_method_handle_intrinsic(vmIntrinsics::ID iid, // _invokeBasic, _linkToVirtual
TRAPS);
// these operate only on invoke methods:
// presize interpreter frames for extra interpreter stack entries, if needed
// method handles want to be able to push a few extra values (e.g., a bound receiver), and
// invokedynamic sometimes needs to push a bootstrap method, call site, and arglist,
// all without checking for a stack overflow
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
// RedefineClasses() support:
// see the definition in methodOop.cpp for the gory details
bool should_not_be_cached() const;
// JVMTI Native method prefixing support:
// Rewriting support
// Get this method's jmethodID -- allocate if it doesn't exist
// Lookup the jmethodID for this method. Return NULL if not found.
// NOTE that this function can be called from a signal handler
// (see AsyncGetCallTrace support for Forte Analyzer) and this
// needs to be async-safe. No allocation should be done and
// so handles are not used to avoid deadlock.
jmethodID find_jmethod_id_or_null() { return instanceKlass::cast(method_holder())->jmethod_id_or_null(this); }
// JNI static invoke cached itable index accessors
int cached_itable_index() { return instanceKlass::cast(method_holder())->cached_itable_index(method_idnum()); }
void set_cached_itable_index(int index) { instanceKlass::cast(method_holder())->set_cached_itable_index(method_idnum(), index); }
// Support for inlining of intrinsic methods
// Helper routines for intrinsic_id() and vmIntrinsics::method().
void init_intrinsic_id(); // updates from _none if a match
// On-stack replacement support
return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
}
}
// Inline cache support
void cleanup_inline_caches();
// Find if klass for method is loaded
bool is_klass_loaded_by_klass_index(int klass_index) const;
// Indicates whether compilation failed earlier for this method, or
// whether it is not compilable for another reason like having a
// breakpoint set in it.
void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL);
set_not_compilable(comp_level, false);
}
void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL);
set_not_osr_compilable(comp_level, false);
}
private:
public:
bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit
// Background compilation support
// Resolve all classes in signature, return 'true' if successful
// Return if true if not all classes references in signature, including return type, has been loaded
// Printing
void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
// Helper routine used for method sorting
bool idempotent = false);
// size of parameters
private:
// Inlined elements
address* native_function_addr() const { assert(is_native(), "must be native"); return (address*) (this+1); }
// Garbage collection support
};
// Utility class for compressing line number tables
private:
int _bci;
int _line;
public:
// Constructor
CompressedLineNumberWriteStream(int initial_size) : CompressedWriteStream(initial_size), _bci(0), _line(0) {}
CompressedLineNumberWriteStream(u_char* buffer, int initial_size) : CompressedWriteStream(buffer, initial_size), _bci(0), _line(0) {}
// Write (bci, line number) pair to stream
// Skip (0,0) deltas - they do not add information and conflict with terminator.
if (bci_delta == 0 && line_delta == 0) return;
// Check if bci is 5-bit and line number 3-bit unsigned.
// Compress into single byte.
// Check that value doesn't match escape character.
if (value != 0xFF) {
return;
}
}
}
// Windows AMD64 + Apr 2005 PSDK with /O2 generates bad code for write_pair.
// Disabling optimization doesn't work for methods in header files
// so we force it to call through the non-optimized version in the .cpp.
// It's gross, but it's the only way we can ensure that all callers are
// fixed. _MSC_VER is defined by the windows compiler
#else
#endif
// Write end-of-stream marker
};
// Utility class for decompressing line number tables
private:
int _bci;
int _line;
public:
// Constructor
// Read (bci, line number) pair from stream. Returns false at end-of-stream.
bool read_pair();
// Accessing bci and line number (after calling read_pair)
};
/// Fast Breakpoints.
// If this structure gets more complicated (because bpts get numerous),
// move it into its own header.
// There is presently no provision for concurrent access
// to breakpoint lists, which is only OK for JVMTI because
// breakpoints are written only at safepoints, and are read
// concurrently only outside of safepoints.
friend class VMStructs;
private:
int _bci;
public:
// accessors
// helps for searchers
}
return _name_index == m->name_index() &&
_signature_index == m->signature_index();
}
};
// Utility class for access exception handlers
private:
public:
if (m->has_exception_handler()) {
_table = m->exception_table_start();
_length = m->exception_table_length();
} else {
_length = 0;
}
}
int length() const {
return _length;
}
}
}
}
}
}
}
}
}
};
#endif // SHARE_VM_OOPS_METHODOOP_HPP