/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * 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. *
*/
// A Method represents a Java method. // // Note that most applications load thousands of methods, so keeping the size of this // class small has a big impact on footprint. // // Note that native_function and signature_handler have to be at fixed offsets // (required by the interpreter) // // Method embedded field layout (after declared fields): // [EMBEDDED native_function (present only if native) ] // [EMBEDDED signature_handler (present only if native) ]
class CheckedExceptionElement; class LocalVariableTableElement; class AdapterHandlerEntry; class MethodData; class MethodCounters; class ConstMethod; class InlineTableSizes; class CompiledMethod; class InterpreterOopMap;
class Method : public Metadata { friendclass VMStructs; friendclass JVMCIVMStructs; friendclass MethodTest; private: // If you add a new field that points to any metaspace object, you // must add this field to Method::metaspace_pointers_do().
ConstMethod* _constMethod; // Method read-only data.
MethodData* _method_data;
MethodCounters* _method_counters;
AdapterHandlerEntry* _adapter;
AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) // note: can have vtables with >2**16 elements (because of inheritance)
u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
Symbol* _name; #endif // Entry point for calling both from and to the interpreter.
address _i2i_entry; // All-args-on-stack calling convention // 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).
CompiledMethod* volatile _code; // Points to the corresponding piece of native code volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
// Helper routine: get klass name + "." + method name + signature as // C string, for the purpose of providing more useful // 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; char* name_and_sig_as_C_string(char* buf, int size) const;
// Static routine in the situations we don't have a Method* staticchar* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature); staticchar* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size);
// Get return type + klass name + "." + method name + ( parameters types ) // as a C string or print it to an outputStream. // This is to be used to assemble strings passed to Java, so that // the text more resembles Java code. Used in exception messages. // Memory is allocated in the resource area; the caller needs // a ResourceMark. constchar* external_name() const; void print_external_name(outputStream *os) const;
// index into InstanceKlass methods() array // note: also used by jfr
u2 method_idnum() const { return constMethod()->method_idnum(); } void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); }
// code size int code_size() const { return constMethod()->code_size(); }
// method size in words int method_size() const { returnsizeof(Method)/wordSize + ( is_native() ? 2 : 0 ); }
// constant pool for Klass* holding this method
ConstantPool* constants() const { return constMethod()->constants(); } void set_constants(ConstantPool* c) { constMethod()->set_constants(c); }
// max stack // return original max stack size for method verification int verifier_max_stack() const { return constMethod()->max_stack(); } int max_stack() const { return constMethod()->max_stack() + extra_stack_entries(); } void set_max_stack(int size) { constMethod()->set_max_stack(size); }
// max locals int max_locals() const { return constMethod()->max_locals(); } void set_max_locals(int size) { constMethod()->set_max_locals(size); }
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);
#if COMPILER2_OR_JVMCI // Count of times method was exited via exception while interpreting void interpreter_throwout_increment(Thread* current) {
MethodCounters* mcs = get_method_counters(current); if (mcs != NULL) {
mcs->interpreter_throwout_increment();
}
} #endif
// 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. staticint fast_exception_handler_bci_for(const methodHandle& mh, Klass* ex_klass, int throw_bci, TRAPS);
address get_i2c_entry();
address get_c2i_entry();
address get_c2i_unverified_entry();
address get_c2i_no_clinit_check_entry();
AdapterHandlerEntry* adapter() const { return _adapter;
} // setup entry points void link_method(const methodHandle& method, TRAPS); // clear entry points. Used by sharing code during dump time void unlink_method() NOT_CDS_RETURN;
// the number of argument reg slots that the compiled method uses on the stack. int num_stack_arg_slots() const { return constMethod()->num_stack_arg_slots(); }
// vtable index enum VtableIndexFlag { // Valid vtable indexes are non-negative (>= 0). // These few negative values are used as sentinels.
itable_index_max = -10, // first itable index, growing downward
pending_itable_index = -9, // itable index will be assigned
invalid_vtable_index = -4, // distinct from any valid vtable index
garbage_vtable_index = -3, // not yet linked; no vtable layout yet
nonvirtual_vtable_index = -2 // there is no need for vtable dispatch // 6330203 Note: Do not use -1, which was overloaded with many meanings.
};
DEBUG_ONLY(bool valid_vtable_index() const { return _vtable_index >= nonvirtual_vtable_index; }) bool has_vtable_index() const { return _vtable_index >= 0; } int vtable_index() const { return _vtable_index; } void set_vtable_index(int index);
DEBUG_ONLY(bool valid_itable_index() const { return _vtable_index <= pending_itable_index; }) bool has_itable_index() const { return _vtable_index <= itable_index_max; } int itable_index() const { assert(valid_itable_index(), ""); return itable_index_max - _vtable_index; } void set_itable_index(int index);
// interpreter entry
address interpreter_entry() const { return _i2i_entry; } // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry void set_interpreter_entry(address entry) { if (_i2i_entry != entry) {
_i2i_entry = entry;
} if (_from_interpreted_entry != entry) {
_from_interpreted_entry = entry;
}
}
// Must specify a real function (not NULL). // Use clear_native_function() to unregister. void set_native_function(address function, bool post_event_flag); bool has_native_function() const; void clear_native_function();
// 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_final_method(AccessFlags class_access_flags) const; // interface method declared with 'default' - excludes private interface methods bool is_default_method() const;
// true if method needs no dynamic dispatch (final and/or no vtable entry) bool can_be_statically_bound() const; bool can_be_statically_bound(InstanceKlass* context) const; bool can_be_statically_bound(AccessFlags class_access_flags) const;
// true if method can omit stack trace in throw in compiled code. bool can_omit_stack_trace();
// returns true if the method has any backward branches. bool has_loops() { return access_flags().loops_flag_init() ? access_flags().has_loops() : compute_has_loops_flag();
};
// 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 guaranteed_monitor_matching() const { return access_flags().is_monitor_matching(); } void set_guaranteed_monitor_matching() { _access_flags.set_monitor_matching(); }
// returns true if the method is an accessor function (setter/getter). bool is_accessor() const;
// returns true if the method is a getter bool is_getter() const;
// returns true if the method is a setter bool is_setter() const;
// returns true if the method does nothing but return a constant of primitive type bool is_constant_getter() 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;
// returns true if the method name is <init> bool is_object_initializer() const;
// compiled code support // NOTE: code() is inherently racy as deopt can be clearing code // simultaneously. Use with caution. bool has_compiled_code() const;
// Static methods that are used to implement member methods where an exposed this pointer // is needed due to possible GCs static objArrayHandle resolved_checked_exceptions_impl(Method* method, TRAPS);
// Returns the byte code index from the byte code pointer int bci_from(address bcp) const;
address bcp_from(int bci) const;
address bcp_from(address bcp) const; int validate_bci_from_bcp(address bcp) const; int validate_bci(int bci) const;
// 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(Klass* k) const;
// Stack walking support bool is_ignored_by_security_stack_walk() 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(vmIntrinsicID iid, // _invokeBasic, _linkToVirtual
Symbol* signature, //anything at all
TRAPS); // Some special methods don't need to be findable by nmethod iterators and are permanent. bool can_be_allocated_in_NonNMethod_space() const { return is_method_handle_intrinsic(); }
enum { // How many extra stack entries for invokedynamic
extra_stack_entries_for_jsr292 = 1
};
// this operates only on invoke methods: // presize interpreter frames for extra interpreter stack entries, if needed // Account for the extra appendix argument for invokehandle/invokedynamic staticint extra_stack_entries() { return extra_stack_entries_for_jsr292; } staticint extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize
// Rewriting support static methodHandle clone_with_new_data(const methodHandle& m, u_char* new_code, int new_code_length,
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS);
// jmethodID handling // Because the useful life-span of a jmethodID cannot be determined, // once created they are never reclaimed. The methods to which they refer, // however, can be GC'ed away if the class is unloaded or if the method is // made obsolete or deleted -- in these cases, the jmethodID // refers to NULL (as is the case for any weak reference). static jmethodID make_jmethod_id(ClassLoaderData* cld, Method* mh); staticvoid destroy_jmethod_id(ClassLoaderData* cld, jmethodID mid);
// Ensure there is enough capacity in the internal tracking data // structures to hold the number of jmethodIDs you plan to generate. // This saves substantial time doing allocations. staticvoid ensure_jmethod_ids(ClassLoaderData* cld, int capacity);
// Use resolve_jmethod_id() in situations where the caller is expected // to provide a valid jmethodID; the only sanity checks are in asserts; // result guaranteed not to be NULL. inlinestatic Method* resolve_jmethod_id(jmethodID mid) {
assert(mid != NULL, "JNI method id should not be null"); return *((Method**)mid);
}
// Use checked_resolve_jmethod_id() in situations where the caller // should provide a valid jmethodID, but might not. NULL is returned // when the jmethodID does not refer to a valid method. static Method* checked_resolve_jmethod_id(jmethodID mid);
// Get this method's jmethodID -- allocate if it doesn't exist
jmethodID jmethod_id();
// 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 method_holder()->jmethod_id_or_null(this); }
// Support for inlining of intrinsic methods
vmIntrinsicID intrinsic_id() const { return (vmIntrinsicID) _intrinsic_id; } void set_intrinsic_id(vmIntrinsicID id) { _intrinsic_id = (u2) id; }
// Helper routines for intrinsic_id() and vmIntrinsics::method(). void init_intrinsic_id(vmSymbolID klass_id); // updates from _none if a match static vmSymbolID klass_id_for_intrinsics(const Klass* holder);
// Find if klass for method is loaded bool is_klass_loaded_by_klass_index(int klass_index) const; bool is_klass_loaded(int refinfo_index, bool must_be_resolved = false) 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. bool is_not_compilable(int comp_level = CompLevel_any) const; void set_not_compilable(constchar* reason, int comp_level = CompLevel_all, bool report = true); void set_not_compilable_quietly(constchar* reason, int comp_level = CompLevel_all) {
set_not_compilable(reason, comp_level, false);
} bool is_not_osr_compilable(int comp_level = CompLevel_any) const; void set_not_osr_compilable(constchar* reason, int comp_level = CompLevel_all, bool report = true); void set_not_osr_compilable_quietly(constchar* reason, int comp_level = CompLevel_all) {
set_not_osr_compilable(reason, comp_level, false);
} bool is_always_compilable() const;
// Resolve all classes in signature, return 'true' if successful staticbool load_signature_classes(const methodHandle& m, TRAPS);
// Printing void print_short_name(outputStream* st = tty) const; // prints as klassname::methodname; Exposed so field engineers can debug VM #if INCLUDE_JVMTI void print_name(outputStream* st = tty) const; // prints as "virtual void foo(int)"; exposed for -Xlog:redefine+class #else void print_name(outputStream* st = tty) const PRODUCT_RETURN; // prints as "virtual void foo(int)" #endif
typedefint (*method_comparator_func)(Method* a, Method* b);
// Helper routine used for method sorting staticvoid sort_methods(Array<Method*>* methods, bool set_idnums = true, method_comparator_func func = NULL);
// Deallocation function for redefine classes or if an error occurs void deallocate_contents(ClassLoaderData* loader_data);
// Utility class for compressing line number tables
class CompressedLineNumberWriteStream: public CompressedWriteStream { 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 void write_pair_regular(int bci_delta, int line_delta);
// If (bci delta, line delta) fits in (5-bit unsigned, 3-bit unsigned) // we save it as one byte, otherwise we write a 0xFF escape character // and use regular compression. 0x0 is used as end-of-stream terminator. void write_pair_inline(int bci, int line);
// Utility class for decompressing line number tables
class CompressedLineNumberReadStream: public CompressedReadStream { private: int _bci; int _line; public: // Constructor
CompressedLineNumberReadStream(u_char* buffer); // 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) int bci() const { return _bci; } int line() const { return _line; }
};
#if INCLUDE_JVMTI
/// 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.
class BreakpointInfo : public CHeapObj<mtClass> { friendclass VMStructs; private:
Bytecodes::Code _orig_bytecode; int _bci;
u2 _name_index; // of method
u2 _signature_index; // of method
BreakpointInfo* _next; // simple storage allocation
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.