28 #include "oops/method.hpp" |
28 #include "oops/method.hpp" |
29 #include "utilities/top.hpp" |
29 #include "utilities/top.hpp" |
30 |
30 |
31 // All the necessary definitions for run-time link resolution. |
31 // All the necessary definitions for run-time link resolution. |
32 |
32 |
33 // LinkInfo & its subclasses provide all the information gathered |
33 // CallInfo provides all the information gathered for a particular |
34 // for a particular link after resolving it. A link is any reference |
34 // linked call site after resolving it. A link is any reference |
35 // made from within the bytecodes of a method to an object outside of |
35 // made from within the bytecodes of a method to an object outside of |
36 // that method. If the info is invalid, the link has not been resolved |
36 // that method. If the info is invalid, the link has not been resolved |
37 // successfully. |
37 // successfully. |
38 |
38 |
39 class LinkInfo VALUE_OBJ_CLASS_SPEC { |
39 class CallInfo VALUE_OBJ_CLASS_SPEC { |
40 }; |
|
41 |
|
42 |
|
43 // Link information for getfield/putfield & getstatic/putstatic bytecodes. |
|
44 |
|
45 class FieldAccessInfo: public LinkInfo { |
|
46 protected: |
|
47 KlassHandle _klass; |
|
48 Symbol* _name; |
|
49 AccessFlags _access_flags; |
|
50 int _field_index; // original index in the klass |
|
51 int _field_offset; |
|
52 BasicType _field_type; |
|
53 |
|
54 public: |
40 public: |
55 void set(KlassHandle klass, Symbol* name, int field_index, int field_offset, |
41 // Ways that a method call might be selected (or not) based on receiver type. |
56 BasicType field_type, AccessFlags access_flags); |
42 // Note that an invokevirtual instruction might be linked with no_dispatch, |
57 KlassHandle klass() const { return _klass; } |
43 // and an invokeinterface instruction might be linked with any of the three options |
58 Symbol* name() const { return _name; } |
44 enum CallKind { |
59 int field_index() const { return _field_index; } |
45 direct_call, // jump into resolved_method (must be concrete) |
60 int field_offset() const { return _field_offset; } |
46 vtable_call, // select recv.klass.method_at_vtable(index) |
61 BasicType field_type() const { return _field_type; } |
47 itable_call, // select recv.klass.method_at_itable(resolved_method.holder, index) |
62 AccessFlags access_flags() const { return _access_flags; } |
48 unknown_kind = -1 |
63 |
49 }; |
64 // debugging |
|
65 void print() PRODUCT_RETURN; |
|
66 }; |
|
67 |
|
68 |
|
69 // Link information for all calls. |
|
70 |
|
71 class CallInfo: public LinkInfo { |
|
72 private: |
50 private: |
73 KlassHandle _resolved_klass; // static receiver klass |
51 KlassHandle _resolved_klass; // static receiver klass, resolved from a symbolic reference |
74 KlassHandle _selected_klass; // dynamic receiver class (same as static, or subklass) |
52 KlassHandle _selected_klass; // dynamic receiver class (same as static, or subklass) |
75 methodHandle _resolved_method; // static target method |
53 methodHandle _resolved_method; // static target method |
76 methodHandle _selected_method; // dynamic (actual) target method |
54 methodHandle _selected_method; // dynamic (actual) target method |
77 int _vtable_index; // vtable index of selected method |
55 CallKind _call_kind; // kind of call (static(=bytecode static/special + |
|
56 // others inferred), vtable, itable) |
|
57 int _call_index; // vtable or itable index of selected class method (if any) |
78 Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) |
58 Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) |
79 Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) |
59 Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) |
80 |
60 |
81 void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); |
61 void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); |
82 void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS); |
62 void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS); |
83 void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); |
63 void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); |
84 void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); |
64 void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); |
85 void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); |
65 void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS); |
86 |
66 |
87 friend class LinkResolver; |
67 friend class LinkResolver; |
88 |
68 |
89 public: |
69 public: |
|
70 CallInfo() { |
|
71 #ifndef PRODUCT |
|
72 _call_kind = CallInfo::unknown_kind; |
|
73 _call_index = Method::garbage_vtable_index; |
|
74 #endif //PRODUCT |
|
75 } |
|
76 |
|
77 // utility to extract an effective CallInfo from a method and an optional receiver limit |
|
78 // does not queue the method for compilation |
|
79 CallInfo(Method* resolved_method, Klass* resolved_klass = NULL); |
|
80 |
90 KlassHandle resolved_klass() const { return _resolved_klass; } |
81 KlassHandle resolved_klass() const { return _resolved_klass; } |
91 KlassHandle selected_klass() const { return _selected_klass; } |
82 KlassHandle selected_klass() const { return _selected_klass; } |
92 methodHandle resolved_method() const { return _resolved_method; } |
83 methodHandle resolved_method() const { return _resolved_method; } |
93 methodHandle selected_method() const { return _selected_method; } |
84 methodHandle selected_method() const { return _selected_method; } |
94 Handle resolved_appendix() const { return _resolved_appendix; } |
85 Handle resolved_appendix() const { return _resolved_appendix; } |
95 Handle resolved_method_type() const { return _resolved_method_type; } |
86 Handle resolved_method_type() const { return _resolved_method_type; } |
96 |
87 |
97 BasicType result_type() const { return selected_method()->result_type(); } |
88 BasicType result_type() const { return selected_method()->result_type(); } |
98 bool has_vtable_index() const { return _vtable_index >= 0; } |
89 CallKind call_kind() const { return _call_kind; } |
99 bool is_statically_bound() const { return _vtable_index == Method::nonvirtual_vtable_index; } |
90 int call_index() const { return _call_index; } |
100 int vtable_index() const { |
91 int vtable_index() const { |
101 // Even for interface calls the vtable index could be non-negative. |
92 // Even for interface calls the vtable index could be non-negative. |
102 // See CallInfo::set_interface. |
93 // See CallInfo::set_interface. |
103 assert(has_vtable_index() || is_statically_bound(), ""); |
94 assert(has_vtable_index() || is_statically_bound(), ""); |
104 return _vtable_index; |
95 assert(call_kind() == vtable_call || call_kind() == direct_call, ""); |
105 } |
96 // The returned value is < 0 if the call is statically bound. |
|
97 // But, the returned value may be >= 0 even if the kind is direct_call. |
|
98 // It is up to the caller to decide which way to go. |
|
99 return _call_index; |
|
100 } |
|
101 int itable_index() const { |
|
102 assert(call_kind() == itable_call, ""); |
|
103 // The returned value is always >= 0, a valid itable index. |
|
104 return _call_index; |
|
105 } |
|
106 |
|
107 // debugging |
|
108 #ifdef ASSERT |
|
109 bool has_vtable_index() const { return _call_index >= 0 && _call_kind != CallInfo::itable_call; } |
|
110 bool is_statically_bound() const { return _call_index == Method::nonvirtual_vtable_index; } |
|
111 #endif //ASSERT |
|
112 void verify() PRODUCT_RETURN; |
|
113 void print() PRODUCT_RETURN; |
106 }; |
114 }; |
107 |
115 |
|
116 // Link information for getfield/putfield & getstatic/putstatic bytecodes |
|
117 // is represented using a fieldDescriptor. |
108 |
118 |
109 // The LinkResolver is used to resolve constant-pool references at run-time. |
119 // The LinkResolver is used to resolve constant-pool references at run-time. |
110 // It does all necessary link-time checks & throws exceptions if necessary. |
120 // It does all necessary link-time checks & throws exceptions if necessary. |
111 |
121 |
112 class LinkResolver: AllStatic { |
122 class LinkResolver: AllStatic { |
|
123 friend class klassVtable; |
|
124 friend class klassItable; |
|
125 |
113 private: |
126 private: |
114 static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
127 static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
115 static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
128 static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
116 static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
129 static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
117 static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, |
130 static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, |
118 KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS); |
131 KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS); |
119 |
132 |
120 static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
133 static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); |
121 |
134 |
122 static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); |
135 static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); |
123 static void resolve_klass_no_update (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); // no update of constantPool entry |
|
124 |
136 |
125 static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); |
137 static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); |
126 |
138 |
127 static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); |
139 static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); |
128 static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); |
140 static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); |
146 // static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target |
158 // static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target |
147 static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result, |
159 static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result, |
148 Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS); |
160 Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS); |
149 |
161 |
150 // runtime/static resolving for fields |
162 // runtime/static resolving for fields |
151 static void resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS); |
163 static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS); |
152 // takes an extra bool argument "update_pool" to decide whether to update the constantPool during klass resolution. |
164 static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature, |
153 static void resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS); |
165 KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS); |
|
166 |
|
167 // source of access_kind codes: |
|
168 static Bytecodes::Code field_access_kind(bool is_static, bool is_put) { |
|
169 return (is_static |
|
170 ? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic) |
|
171 : (is_put ? Bytecodes::_putfield : Bytecodes::_getfield )); |
|
172 } |
154 |
173 |
155 // runtime resolving: |
174 // runtime resolving: |
156 // resolved_klass = specified class (i.e., static receiver class) |
175 // resolved_klass = specified class (i.e., static receiver class) |
157 // current_klass = sending method holder (i.e., class containing the method containing the call being resolved) |
176 // current_klass = sending method holder (i.e., class containing the method containing the call being resolved) |
158 static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS); |
177 static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS); |