/* * 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. *
*/
// All the necessary definitions for run-time link resolution.
// CallInfo provides all the information gathered for a particular // linked call site after resolving it. A link is any reference // made from within the bytecodes of a method to an object outside of // that method. If the info is invalid, the link has not been resolved // successfully.
class CallInfo : public StackObj { public: // Ways that a method call might be selected (or not) based on receiver type. // Note that an invokevirtual instruction might be linked with no_dispatch, // and an invokeinterface instruction might be linked with any of the three options enum CallKind {
direct_call, // jump into resolved_method (must be concrete)
vtable_call, // select recv.klass.method_at_vtable(index)
itable_call, // select recv.klass.method_at_itable(resolved_method.holder, index)
unknown_kind = -1
}; private:
Klass* _resolved_klass; // static receiver klass, resolved from a symbolic reference
methodHandle _resolved_method; // static target method
methodHandle _selected_method; // dynamic (actual) target method
CallKind _call_kind; // kind of call (static(=bytecode static/special + // others inferred), vtable, itable) int _call_index; // vtable or itable index of selected class method (if any)
Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix)
Handle _resolved_method_name; // Object holding the ResolvedMethodName
// utility to extract an effective CallInfo from a method and an optional receiver limit // does not queue the method for compilation. This also creates a ResolvedMethodName // object for the resolved_method.
CallInfo(Method* resolved_method, Klass* resolved_klass, TRAPS);
BasicType result_type() const { return selected_method()->result_type(); }
CallKind call_kind() const { return _call_kind; } int vtable_index() const { // Even for interface calls the vtable index could be non-negative. // See CallInfo::set_interface.
assert(has_vtable_index() || is_statically_bound(), "");
assert(call_kind() == vtable_call || call_kind() == direct_call, ""); // The returned value is < 0 if the call is statically bound. // But, the returned value may be >= 0 even if the kind is direct_call. // It is up to the caller to decide which way to go. return _call_index;
} int itable_index() const {
assert(call_kind() == itable_call, ""); // The returned value is always >= 0, a valid itable index. return _call_index;
}
// Condensed information from constant pool to use to resolve the method or field. // resolved_klass = specified class (i.e., static receiver class) // current_klass = sending method holder (i.e., class containing the method // containing the call being resolved) // current_method = sending method (relevant for field resolution) class LinkInfo : public StackObj {
Symbol* _name; // extracted from JVM_CONSTANT_NameAndType
Symbol* _signature;
Klass* _resolved_klass; // class that the constant pool entry points to
Klass* _current_klass; // class that owns the constant pool
methodHandle _current_method; // sending method bool _check_access; bool _check_loader_constraints;
constantTag _tag;
LinkInfo(const constantPoolHandle& pool, int index, const methodHandle& current_method, TRAPS);
LinkInfo(const constantPoolHandle& pool, int index, TRAPS);
// Condensed information from other call sites within the vm.
LinkInfo(Klass* resolved_klass, Symbol* name, Symbol* signature, Klass* current_klass,
AccessCheck check_access = AccessCheck::required,
LoaderConstraintCheck check_loader_constraints = LoaderConstraintCheck::required,
constantTag tag = JVM_CONSTANT_Invalid) :
_name(name),
_signature(signature), _resolved_klass(resolved_klass), _current_klass(current_klass), _current_method(methodHandle()),
_check_access(check_access == AccessCheck::required),
_check_loader_constraints(check_loader_constraints == LoaderConstraintCheck::required), _tag(tag) {}
// Case where we just find the method and don't check access against the current class
LinkInfo(Klass* resolved_klass, Symbol*name, Symbol* signature) :
_name(name),
_signature(signature), _resolved_klass(resolved_klass), _current_klass(NULL), _current_method(methodHandle()),
_check_access(false), _check_loader_constraints(false), _tag(JVM_CONSTANT_Invalid) {}
// Link information for getfield/putfield & getstatic/putstatic bytecodes // is represented using a fieldDescriptor.
// The LinkResolver is used to resolve constant-pool references at run-time. // It does all necessary link-time checks & throws exceptions if necessary.
class LinkResolver: AllStatic { friendclass klassVtable; friendclass klassItable;
// runtime resolving from constant pool staticvoid resolve_invokestatic (CallInfo& result, const constantPoolHandle& pool, int index, TRAPS); staticvoid resolve_invokespecial (CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); staticvoid resolve_invokevirtual (CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); staticvoid resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); staticvoid resolve_invokedynamic (CallInfo& result, const constantPoolHandle& pool, int index, TRAPS); staticvoid resolve_invokehandle (CallInfo& result, const constantPoolHandle& pool, int index, TRAPS); public: // constant pool resolving staticvoid check_klass_accessibility(Klass* ref_klass, Klass* sel_klass, TRAPS);
// static resolving calls (will not run any Java code); // used only from Bytecode_invoke::static_target static Method* resolve_method_statically(Bytecodes::Code code, const constantPoolHandle& pool, int index, TRAPS);
// same as above for compile-time resolution; but returns null handle instead of throwing // an exception on error also, does not initialize klass (i.e., no side effects) static Method* resolve_virtual_call_or_null(Klass* receiver_klass, const LinkInfo& link_info); static Method* resolve_interface_call_or_null(Klass* receiver_klass, const LinkInfo& link_info); static Method* resolve_static_call_or_null(const LinkInfo& link_info); static Method* resolve_special_call_or_null(const LinkInfo& link_info);
// same as above for compile-time resolution; returns vtable_index if current_klass if linked staticint resolve_virtual_vtable_index (Klass* receiver_klass, const LinkInfo& link_info);
// static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful) static Method* linktime_resolve_virtual_method_or_null (const LinkInfo& link_info); static Method* linktime_resolve_interface_method_or_null(const LinkInfo& link_info);
// runtime resolving from constant pool staticvoid resolve_invoke(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index,
Bytecodes::Code byte, TRAPS);
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.