annotate src/share/vm/oops/klassVtable.cpp @ 452:00b023ae2d78

6722113: CMS: Incorrect overflow handling during precleaning of Reference lists Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery. Reviewed-by: apetrusenko, jcoomes
author ysr
date Thu, 20 Nov 2008 12:27:41 -0800
parents d1605aabd0a1
children 70998f2e05ef
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
196
d1605aabd0a1 6719955: Update copyright year
xdono
parents: 113
diff changeset
2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include "incls/_klassVtable.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 inline instanceKlass* klassVtable::ik() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
29 Klass* k = _klass()->klass_part();
a61af66fc99e Initial load
duke
parents:
diff changeset
30 assert(k->oop_is_instance(), "not an instanceKlass");
a61af66fc99e Initial load
duke
parents:
diff changeset
31 return (instanceKlass*)k;
a61af66fc99e Initial load
duke
parents:
diff changeset
32 }
a61af66fc99e Initial load
duke
parents:
diff changeset
33
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // this function computes the vtable size (including the size needed for miranda
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // methods) and the number of miranda methods in this class
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // Note on Miranda methods: Let's say there is a class C that implements
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // interface I. Let's say there is a method m in I that neither C nor any
a61af66fc99e Initial load
duke
parents:
diff changeset
39 // of its super classes implement (i.e there is no method of any access, with
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // the same name and signature as m), then m is a Miranda method which is
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // entered as a public abstract method in C's vtable. From then on it should
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // treated as any other public method in C for method over-ride purposes.
a61af66fc99e Initial load
duke
parents:
diff changeset
43 void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length,
a61af66fc99e Initial load
duke
parents:
diff changeset
44 int &num_miranda_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
45 klassOop super,
a61af66fc99e Initial load
duke
parents:
diff changeset
46 objArrayOop methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
47 AccessFlags class_flags,
a61af66fc99e Initial load
duke
parents:
diff changeset
48 oop classloader,
a61af66fc99e Initial load
duke
parents:
diff changeset
49 symbolOop classname,
a61af66fc99e Initial load
duke
parents:
diff changeset
50 objArrayOop local_interfaces
a61af66fc99e Initial load
duke
parents:
diff changeset
51 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 No_Safepoint_Verifier nsv;
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // set up default result values
a61af66fc99e Initial load
duke
parents:
diff changeset
56 vtable_length = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
57 num_miranda_methods = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 // start off with super's vtable length
a61af66fc99e Initial load
duke
parents:
diff changeset
60 instanceKlass* sk = (instanceKlass*)super->klass_part();
a61af66fc99e Initial load
duke
parents:
diff changeset
61 vtable_length = super == NULL ? 0 : sk->vtable_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // go thru each method in the methods table to see if it needs a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
64 int len = methods->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
65 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 assert(methods->obj_at(i)->is_method(), "must be a methodOop");
a61af66fc99e Initial load
duke
parents:
diff changeset
67 methodOop m = methodOop(methods->obj_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 if (needs_new_vtable_entry(m, super, classloader, classname, class_flags)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 vtable_length += vtableEntry::size(); // we need a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
71 }
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 // compute the number of mirandas methods that must be added to the end
a61af66fc99e Initial load
duke
parents:
diff changeset
75 num_miranda_methods = get_num_mirandas(super, methods, local_interfaces);
a61af66fc99e Initial load
duke
parents:
diff changeset
76 vtable_length += (num_miranda_methods * vtableEntry::size());
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 if (Universe::is_bootstrapping() && vtable_length == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
79 // array classes don't have their superclass set correctly during
a61af66fc99e Initial load
duke
parents:
diff changeset
80 // bootstrapping
a61af66fc99e Initial load
duke
parents:
diff changeset
81 vtable_length = Universe::base_vtable_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
82 }
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 if (super == NULL && !Universe::is_bootstrapping() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
85 vtable_length != Universe::base_vtable_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // Someone is attempting to redefine java.lang.Object incorrectly. The
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // only way this should happen is from
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // SystemDictionary::resolve_from_stream(), which will detect this later
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // and throw a security exception. So don't assert here to let
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // the exception occur.
a61af66fc99e Initial load
duke
parents:
diff changeset
91 vtable_length = Universe::base_vtable_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93 assert(super != NULL || vtable_length == Universe::base_vtable_size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
94 "bad vtable size for class Object");
a61af66fc99e Initial load
duke
parents:
diff changeset
95 assert(vtable_length % vtableEntry::size() == 0, "bad vtable length");
a61af66fc99e Initial load
duke
parents:
diff changeset
96 assert(vtable_length >= Universe::base_vtable_size(), "vtable too small");
a61af66fc99e Initial load
duke
parents:
diff changeset
97 }
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 int klassVtable::index_of(methodOop m, int len) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods");
a61af66fc99e Initial load
duke
parents:
diff changeset
101 return m->vtable_index();
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 int klassVtable::initialize_from_super(KlassHandle super) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (super.is_null()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
107 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // copy methods from superKlass
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // can't inherit from array class, so must be instanceKlass
a61af66fc99e Initial load
duke
parents:
diff changeset
110 assert(super->oop_is_instance(), "must be instance klass");
a61af66fc99e Initial load
duke
parents:
diff changeset
111 instanceKlass* sk = (instanceKlass*)super()->klass_part();
a61af66fc99e Initial load
duke
parents:
diff changeset
112 klassVtable* superVtable = sk->vtable();
a61af66fc99e Initial load
duke
parents:
diff changeset
113 assert(superVtable->length() <= _length, "vtable too short");
a61af66fc99e Initial load
duke
parents:
diff changeset
114 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
115 superVtable->verify(tty, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
116 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
117 superVtable->copy_vtable_to(table());
a61af66fc99e Initial load
duke
parents:
diff changeset
118 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
119 if (PrintVtables && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length);
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
123 return superVtable->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // Revised lookup semantics introduced 1.3 (Kestral beta)
a61af66fc99e Initial load
duke
parents:
diff changeset
128 void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // Note: Arrays can have intermediate array supers. Use java_super to skip them.
a61af66fc99e Initial load
duke
parents:
diff changeset
131 KlassHandle super (THREAD, klass()->java_super());
a61af66fc99e Initial load
duke
parents:
diff changeset
132 int nofNewEntries = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
133
a61af66fc99e Initial load
duke
parents:
diff changeset
134
a61af66fc99e Initial load
duke
parents:
diff changeset
135 if (PrintVtables && !klass()->oop_is_array()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 ResourceMark rm(THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
137 tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
141 oop* end_of_obj = (oop*)_klass() + _klass()->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
142 oop* end_of_vtable = (oop*)&table()[_length];
a61af66fc99e Initial load
duke
parents:
diff changeset
143 assert(end_of_vtable <= end_of_obj, "vtable extends beyond end");
a61af66fc99e Initial load
duke
parents:
diff changeset
144 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
145
a61af66fc99e Initial load
duke
parents:
diff changeset
146 if (Universe::is_bootstrapping()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // just clear everything
a61af66fc99e Initial load
duke
parents:
diff changeset
148 for (int i = 0; i < _length; i++) table()[i].clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
149 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 int super_vtable_len = initialize_from_super(super);
a61af66fc99e Initial load
duke
parents:
diff changeset
153 if (klass()->oop_is_array()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 assert(super_vtable_len == _length, "arrays shouldn't introduce new methods");
a61af66fc99e Initial load
duke
parents:
diff changeset
155 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 assert(_klass->oop_is_instance(), "must be instanceKlass");
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 objArrayHandle methods(THREAD, ik()->methods());
a61af66fc99e Initial load
duke
parents:
diff changeset
159 int len = methods()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
160 int initialized = super_vtable_len;
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // update_super_vtable can stop for gc - ensure using handles
a61af66fc99e Initial load
duke
parents:
diff changeset
163 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 HandleMark hm(THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 assert(methods()->obj_at(i)->is_method(), "must be a methodOop");
a61af66fc99e Initial load
duke
parents:
diff changeset
166 methodHandle mh(THREAD, (methodOop)methods()->obj_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168 bool needs_new_entry = update_super_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
169
a61af66fc99e Initial load
duke
parents:
diff changeset
170 if (needs_new_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 put_method_at(mh(), initialized);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 mh()->set_vtable_index(initialized); // set primary vtable index
a61af66fc99e Initial load
duke
parents:
diff changeset
173 initialized++;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 }
a61af66fc99e Initial load
duke
parents:
diff changeset
175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
176
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // add miranda methods; it will also update the value of initialized
a61af66fc99e Initial load
duke
parents:
diff changeset
178 fill_in_mirandas(initialized);
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // In class hierachieswhere the accesibility is not increasing (i.e., going from private ->
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // package_private -> publicprotected), the vtable might actually be smaller than our initial
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // calculation.
a61af66fc99e Initial load
duke
parents:
diff changeset
183 assert(initialized <= _length, "vtable initialization failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
184 for(;initialized < _length; initialized++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
185 put_method_at(NULL, initialized);
a61af66fc99e Initial load
duke
parents:
diff changeset
186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
187 NOT_PRODUCT(verify(tty, true));
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // Interates through the vtables to find the broadest access level. This
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // will always be monotomic for valid Java programs - but not neccesarily
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // for incompatible class files.
a61af66fc99e Initial load
duke
parents:
diff changeset
194 klassVtable::AccessType klassVtable::vtable_accessibility_at(int i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
195 // This vtable is not implementing the specific method
a61af66fc99e Initial load
duke
parents:
diff changeset
196 if (i >= length()) return acc_private;
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // Compute AccessType for current method. public or protected we are done.
a61af66fc99e Initial load
duke
parents:
diff changeset
199 methodOop m = method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
200 if (m->is_protected() || m->is_public()) return acc_publicprotected;
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 AccessType acc = m->is_package_private() ? acc_package_private : acc_private;
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // Compute AccessType for method in super classes
a61af66fc99e Initial load
duke
parents:
diff changeset
205 klassOop super = klass()->super();
a61af66fc99e Initial load
duke
parents:
diff changeset
206 AccessType super_acc = (super != NULL) ? instanceKlass::cast(klass()->super())->vtable()->vtable_accessibility_at(i)
a61af66fc99e Initial load
duke
parents:
diff changeset
207 : acc_private;
a61af66fc99e Initial load
duke
parents:
diff changeset
208
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // Merge
a61af66fc99e Initial load
duke
parents:
diff changeset
210 return (AccessType)MAX2((int)acc, (int)super_acc);
a61af66fc99e Initial load
duke
parents:
diff changeset
211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
212
a61af66fc99e Initial load
duke
parents:
diff changeset
213
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // Update child's copy of super vtable for overrides
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // OR return true if a new vtable entry is required
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // Only called for instanceKlass's, i.e. not for arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
217 // If that changed, could not use _klass as handle for klass
a61af66fc99e Initial load
duke
parents:
diff changeset
218 bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
220 bool allocate_new = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 assert(klass->oop_is_instance(), "must be instanceKlass");
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // Initialize the method's vtable index to "nonvirtual".
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // If we allocate a vtable entry, we will update it to a non-negative number.
a61af66fc99e Initial load
duke
parents:
diff changeset
225 target_method()->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
226
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // Static and <init> methods are never in
a61af66fc99e Initial load
duke
parents:
diff changeset
228 if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
229 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 if (klass->is_final() || target_method()->is_final()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // a final method never needs a new entry; final methods can be statically
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // resolved and they have to be present in the vtable only if they override
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // a super's method, in which case they re-use its entry
a61af66fc99e Initial load
duke
parents:
diff changeset
236 allocate_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // we need a new entry if there is no superclass
a61af66fc99e Initial load
duke
parents:
diff changeset
240 if (klass->super() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 return allocate_new;
a61af66fc99e Initial load
duke
parents:
diff changeset
242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
243
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // private methods always have a new entry in the vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
245 if (target_method()->is_private()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 return allocate_new;
a61af66fc99e Initial load
duke
parents:
diff changeset
247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
248
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // search through the vtable and update overridden entries
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // Since check_signature_loaders acquires SystemDictionary_lock
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // which can block for gc, once we are in this loop, use handles, not
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // unhandled oops unless they are reinitialized for each loop
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // handles for name, signature, klass, target_method
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // not for match_method, holder
a61af66fc99e Initial load
duke
parents:
diff changeset
255
a61af66fc99e Initial load
duke
parents:
diff changeset
256 symbolHandle name(THREAD,target_method()->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
257 symbolHandle signature(THREAD,target_method()->signature());
a61af66fc99e Initial load
duke
parents:
diff changeset
258 for(int i = 0; i < super_vtable_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
259 methodOop match_method = method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // Check if method name matches
a61af66fc99e Initial load
duke
parents:
diff changeset
261 if (match_method->name() == name() && match_method->signature() == signature()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 instanceKlass* holder = (THREAD, instanceKlass::cast(match_method->method_holder()));
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // Check if the match_method is accessable from current class
a61af66fc99e Initial load
duke
parents:
diff changeset
266
a61af66fc99e Initial load
duke
parents:
diff changeset
267 bool same_package_init = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 bool same_package_flag = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
269 bool simple_match = match_method->is_public() || match_method->is_protected();
a61af66fc99e Initial load
duke
parents:
diff changeset
270 if (!simple_match) {
a61af66fc99e Initial load
duke
parents:
diff changeset
271 same_package_init = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
272 same_package_flag = holder->is_same_class_package(_klass->class_loader(), _klass->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
273
a61af66fc99e Initial load
duke
parents:
diff changeset
274 simple_match = match_method->is_package_private() && same_package_flag;
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // match_method is the superclass' method. Note we can't override
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // and shouldn't access superclass' ACC_PRIVATE methods
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // (although they have been copied into our vtable)
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // A simple form of this statement is:
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // if ( (match_method->is_public() || match_method->is_protected()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // (match_method->is_package_private() && holder->is_same_class_package(klass->class_loader(), klass->name()))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
282 //
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // The complexity is introduced it avoid recomputing 'is_same_class_package' which is expensive.
a61af66fc99e Initial load
duke
parents:
diff changeset
284 if (simple_match) {
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // Check if target_method and match_method has same level of accessibility. The accesibility of the
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // match method is the "most-general" visibility of all entries at it's particular vtable index for
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // all superclasses. This check must be done before we override the current entry in the vtable.
a61af66fc99e Initial load
duke
parents:
diff changeset
288 AccessType at = vtable_accessibility_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 bool same_access = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
290
a61af66fc99e Initial load
duke
parents:
diff changeset
291 if ( (at == acc_publicprotected && (target_method()->is_public() || target_method()->is_protected())
a61af66fc99e Initial load
duke
parents:
diff changeset
292 || (at == acc_package_private && (target_method()->is_package_private() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
293 (( same_package_init && same_package_flag) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
294 (!same_package_init && holder->is_same_class_package(_klass->class_loader(), _klass->name()))))))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
295 same_access = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 if (checkconstraints) {
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // Override vtable entry if passes loader constraint check
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // if loader constraint checking requested
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // No need to visit his super, since he and his super
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // have already made any needed loader constraints.
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // Since loader constraints are transitive, it is enough
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // to link to the first super, and we get all the others.
a61af66fc99e Initial load
duke
parents:
diff changeset
305 symbolHandle signature(THREAD, target_method()->signature());
a61af66fc99e Initial load
duke
parents:
diff changeset
306 Handle this_loader(THREAD, _klass->class_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
307 instanceKlassHandle super_klass(THREAD, _klass->super());
a61af66fc99e Initial load
duke
parents:
diff changeset
308 Handle super_loader(THREAD, super_klass->class_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
309
a61af66fc99e Initial load
duke
parents:
diff changeset
310 if (this_loader() != super_loader()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
311 ResourceMark rm(THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
312 char* failed_type_name =
a61af66fc99e Initial load
duke
parents:
diff changeset
313 SystemDictionary::check_signature_loaders(signature, this_loader,
a61af66fc99e Initial load
duke
parents:
diff changeset
314 super_loader, true,
a61af66fc99e Initial load
duke
parents:
diff changeset
315 CHECK_(false));
a61af66fc99e Initial load
duke
parents:
diff changeset
316 if (failed_type_name != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
317 const char* msg = "loader constraint violation: when resolving "
a61af66fc99e Initial load
duke
parents:
diff changeset
318 "overridden method \"%s\" the class loader (instance"
a61af66fc99e Initial load
duke
parents:
diff changeset
319 " of %s) of the current class, %s, and its superclass loader "
a61af66fc99e Initial load
duke
parents:
diff changeset
320 "(instance of %s), have different Class objects for the type "
a61af66fc99e Initial load
duke
parents:
diff changeset
321 "%s used in the signature";
a61af66fc99e Initial load
duke
parents:
diff changeset
322 char* sig = target_method()->name_and_sig_as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
323 const char* loader1 = SystemDictionary::loader_name(this_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
324 char* current = _klass->name()->as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
325 const char* loader2 = SystemDictionary::loader_name(super_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
326 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
a61af66fc99e Initial load
duke
parents:
diff changeset
327 strlen(current) + strlen(loader2) + strlen(failed_type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
328 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
a61af66fc99e Initial load
duke
parents:
diff changeset
330 failed_type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
331 THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335 put_method_at(target_method(), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
336
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 if (same_access) {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // target and match has same accessiblity - share entry
a61af66fc99e Initial load
duke
parents:
diff changeset
340 allocate_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
341 target_method()->set_vtable_index(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
342 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
343 if (PrintVtables && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 AccessType targetacc;
a61af66fc99e Initial load
duke
parents:
diff changeset
345 if (target_method()->is_protected() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
346 target_method()->is_public()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 targetacc = acc_publicprotected;
a61af66fc99e Initial load
duke
parents:
diff changeset
348 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 targetacc = target_method()->is_package_private() ? acc_package_private : acc_private;
a61af66fc99e Initial load
duke
parents:
diff changeset
350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
351 tty->print_cr("overriding with %s::%s index %d, original flags: %x overriders flags: %x",
a61af66fc99e Initial load
duke
parents:
diff changeset
352 _klass->internal_name(), (target_method() != NULL) ?
a61af66fc99e Initial load
duke
parents:
diff changeset
353 target_method()->name()->as_C_string() : "<NULL>", i,
a61af66fc99e Initial load
duke
parents:
diff changeset
354 at, targetacc);
a61af66fc99e Initial load
duke
parents:
diff changeset
355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
356 #endif /*PRODUCT*/
a61af66fc99e Initial load
duke
parents:
diff changeset
357 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
359 if (PrintVtables && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
360 AccessType targetacc;
a61af66fc99e Initial load
duke
parents:
diff changeset
361 if (target_method()->is_protected() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
362 target_method()->is_public()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
363 targetacc = acc_publicprotected;
a61af66fc99e Initial load
duke
parents:
diff changeset
364 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 targetacc = target_method()->is_package_private() ? acc_package_private : acc_private;
a61af66fc99e Initial load
duke
parents:
diff changeset
366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
367 tty->print_cr("override %s %s::%s at index %d, original flags: %x overriders flags: %x",
a61af66fc99e Initial load
duke
parents:
diff changeset
368 allocate_new ? "+ new" : "only",
a61af66fc99e Initial load
duke
parents:
diff changeset
369 _klass->internal_name(), (target_method() != NULL) ?
a61af66fc99e Initial load
duke
parents:
diff changeset
370 target_method()->name()->as_C_string() : "<NULL>", i,
a61af66fc99e Initial load
duke
parents:
diff changeset
371 at, targetacc);
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373 #endif /*PRODUCT*/
a61af66fc99e Initial load
duke
parents:
diff changeset
374 }
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376 }
a61af66fc99e Initial load
duke
parents:
diff changeset
377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
378 return allocate_new;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380
a61af66fc99e Initial load
duke
parents:
diff changeset
381
a61af66fc99e Initial load
duke
parents:
diff changeset
382
a61af66fc99e Initial load
duke
parents:
diff changeset
383 void klassVtable::put_method_at(methodOop m, int index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
384 assert(m->is_oop_or_null(), "Not an oop or null");
a61af66fc99e Initial load
duke
parents:
diff changeset
385 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
386 if (PrintVtables && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 tty->print_cr("adding %s::%s at index %d", _klass->internal_name(),
a61af66fc99e Initial load
duke
parents:
diff changeset
388 (m != NULL) ? m->name()->as_C_string() : "<NULL>", index);
a61af66fc99e Initial load
duke
parents:
diff changeset
389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
390 assert(unchecked_method_at(index)->is_oop_or_null(), "Not an oop or null");
a61af66fc99e Initial load
duke
parents:
diff changeset
391 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
392 table()[index].set(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
394
a61af66fc99e Initial load
duke
parents:
diff changeset
395 // Find out if a method "m" with superclass "super", loader "classloader" and
a61af66fc99e Initial load
duke
parents:
diff changeset
396 // name "classname" needs a new vtable entry. Let P be a class package defined
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // by "classloader" and "classname".
a61af66fc99e Initial load
duke
parents:
diff changeset
398 // NOTE: The logic used here is very similar to the one used for computing
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // the vtables indices for a method. We cannot directly use that function because,
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // when the Universe is boostrapping, a super's vtable might not be initialized.
a61af66fc99e Initial load
duke
parents:
diff changeset
401 bool klassVtable::needs_new_vtable_entry(methodOop target_method,
a61af66fc99e Initial load
duke
parents:
diff changeset
402 klassOop super,
a61af66fc99e Initial load
duke
parents:
diff changeset
403 oop classloader,
a61af66fc99e Initial load
duke
parents:
diff changeset
404 symbolOop classname,
a61af66fc99e Initial load
duke
parents:
diff changeset
405 AccessFlags class_flags) {
a61af66fc99e Initial load
duke
parents:
diff changeset
406 if ((class_flags.is_final() || target_method->is_final()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // a final method never needs a new entry; final methods can be statically
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // resolved and they have to be present in the vtable only if they override
a61af66fc99e Initial load
duke
parents:
diff changeset
409 // a super's method, in which case they re-use its entry
a61af66fc99e Initial load
duke
parents:
diff changeset
410 (target_method->is_static()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // static methods don't need to be in vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
412 (target_method->name() == vmSymbols::object_initializer_name())
a61af66fc99e Initial load
duke
parents:
diff changeset
413 // <init> is never called dynamically-bound
a61af66fc99e Initial load
duke
parents:
diff changeset
414 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
415 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
417
a61af66fc99e Initial load
duke
parents:
diff changeset
418 // we need a new entry if there is no superclass
a61af66fc99e Initial load
duke
parents:
diff changeset
419 if (super == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
420 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // private methods always have a new entry in the vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
424 if (target_method->is_private()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
425 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
427
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // search through the super class hierarchy to see if we need
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
430 symbolOop name = target_method->name();
a61af66fc99e Initial load
duke
parents:
diff changeset
431 symbolOop signature = target_method->signature();
a61af66fc99e Initial load
duke
parents:
diff changeset
432 klassOop k = super;
a61af66fc99e Initial load
duke
parents:
diff changeset
433 methodOop match_method = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
434 instanceKlass *holder = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
435 while (k != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // lookup through the hierarchy for a method with matching name and sign.
a61af66fc99e Initial load
duke
parents:
diff changeset
437 match_method = instanceKlass::cast(k)->lookup_method(name, signature);
a61af66fc99e Initial load
duke
parents:
diff changeset
438 if (match_method == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
439 break; // we still have to search for a matching miranda method
a61af66fc99e Initial load
duke
parents:
diff changeset
440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
441 // get the class holding the matching method
a61af66fc99e Initial load
duke
parents:
diff changeset
442 holder = instanceKlass::cast(match_method->method_holder());
a61af66fc99e Initial load
duke
parents:
diff changeset
443
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (!match_method->is_static()) { // we want only instance method matches
a61af66fc99e Initial load
duke
parents:
diff changeset
445 if ((target_method->is_public() || target_method->is_protected()) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
446 (match_method->is_public() || match_method->is_protected())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
447 // target and match are public/protected; we do not need a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
448 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
450
a61af66fc99e Initial load
duke
parents:
diff changeset
451 if (target_method->is_package_private() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
452 match_method->is_package_private() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
453 holder->is_same_class_package(classloader, classname)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // target and match are P private; we do not need a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
455 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
458
a61af66fc99e Initial load
duke
parents:
diff changeset
459 k = holder->super(); // haven't found a match yet; continue to look
a61af66fc99e Initial load
duke
parents:
diff changeset
460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
461
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // if the target method is public or protected it may have a matching
a61af66fc99e Initial load
duke
parents:
diff changeset
463 // miranda method in the super, whose entry it should re-use.
a61af66fc99e Initial load
duke
parents:
diff changeset
464 if (target_method->is_public() || target_method->is_protected()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
465 instanceKlass *sk = instanceKlass::cast(super);
a61af66fc99e Initial load
duke
parents:
diff changeset
466 if (sk->has_miranda_methods()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
467 if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
468 return false; // found a matching miranda; we do not need a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
472
a61af66fc99e Initial load
duke
parents:
diff changeset
473 return true; // found no match; we need a new entry
a61af66fc99e Initial load
duke
parents:
diff changeset
474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 // Support for miranda methods
a61af66fc99e Initial load
duke
parents:
diff changeset
477
a61af66fc99e Initial load
duke
parents:
diff changeset
478 // get the vtable index of a miranda method with matching "name" and "signature"
a61af66fc99e Initial load
duke
parents:
diff changeset
479 int klassVtable::index_of_miranda(symbolOop name, symbolOop signature) {
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // search from the bottom, might be faster
a61af66fc99e Initial load
duke
parents:
diff changeset
481 for (int i = (length() - 1); i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
482 methodOop m = table()[i].method();
a61af66fc99e Initial load
duke
parents:
diff changeset
483 if (is_miranda_entry_at(i) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
484 m->name() == name && m->signature() == signature) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 return i;
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
488 return methodOopDesc::invalid_vtable_index;
a61af66fc99e Initial load
duke
parents:
diff changeset
489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
490
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // check if an entry is miranda
a61af66fc99e Initial load
duke
parents:
diff changeset
492 bool klassVtable::is_miranda_entry_at(int i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
493 methodOop m = method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
494 klassOop method_holder = m->method_holder();
a61af66fc99e Initial load
duke
parents:
diff changeset
495 instanceKlass *mhk = instanceKlass::cast(method_holder);
a61af66fc99e Initial load
duke
parents:
diff changeset
496
a61af66fc99e Initial load
duke
parents:
diff changeset
497 // miranda methods are interface methods in a class's vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
498 if (mhk->is_interface()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
499 assert(m->is_public() && m->is_abstract(), "should be public and abstract");
a61af66fc99e Initial load
duke
parents:
diff changeset
500 assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
a61af66fc99e Initial load
duke
parents:
diff changeset
501 assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method");
a61af66fc99e Initial load
duke
parents:
diff changeset
502 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
504 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
506
a61af66fc99e Initial load
duke
parents:
diff changeset
507 // check if a method is a miranda method, given a class's methods table and it's super
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // the caller must make sure that the method belongs to an interface implemented by the class
a61af66fc99e Initial load
duke
parents:
diff changeset
509 bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) {
a61af66fc99e Initial load
duke
parents:
diff changeset
510 symbolOop name = m->name();
a61af66fc99e Initial load
duke
parents:
diff changeset
511 symbolOop signature = m->signature();
a61af66fc99e Initial load
duke
parents:
diff changeset
512 if (instanceKlass::find_method(class_methods, name, signature) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // did not find it in the method table of the current class
a61af66fc99e Initial load
duke
parents:
diff changeset
514 if (super == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 // super doesn't exist
a61af66fc99e Initial load
duke
parents:
diff changeset
516 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
518 if (instanceKlass::cast(super)->lookup_method(name, signature) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
519 // super class hierarchy does not implement it
a61af66fc99e Initial load
duke
parents:
diff changeset
520 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
521 }
a61af66fc99e Initial load
duke
parents:
diff changeset
522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
523 }
a61af66fc99e Initial load
duke
parents:
diff changeset
524 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
526
a61af66fc99e Initial load
duke
parents:
diff changeset
527 void klassVtable::add_new_mirandas_to_list(GrowableArray<methodOop>* list_of_current_mirandas,
a61af66fc99e Initial load
duke
parents:
diff changeset
528 objArrayOop current_interface_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
529 objArrayOop class_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
530 klassOop super) {
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // iterate thru the current interface's method to see if it a miranda
a61af66fc99e Initial load
duke
parents:
diff changeset
532 int num_methods = current_interface_methods->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
533 for (int i = 0; i < num_methods; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 methodOop im = methodOop(current_interface_methods->obj_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
535 bool is_duplicate = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
536 int num_of_current_mirandas = list_of_current_mirandas->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // check for duplicate mirandas in different interfaces we implement
a61af66fc99e Initial load
duke
parents:
diff changeset
538 for (int j = 0; j < num_of_current_mirandas; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 methodOop miranda = list_of_current_mirandas->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
540 if ((im->name() == miranda->name()) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
541 (im->signature() == miranda->signature())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 is_duplicate = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
543 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
546
a61af66fc99e Initial load
duke
parents:
diff changeset
547 if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
548 if (is_miranda(im, class_methods, super)) { // is it a miranda at all?
a61af66fc99e Initial load
duke
parents:
diff changeset
549 instanceKlass *sk = instanceKlass::cast(super);
a61af66fc99e Initial load
duke
parents:
diff changeset
550 // check if it is a duplicate of a super's miranda
a61af66fc99e Initial load
duke
parents:
diff changeset
551 if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
552 list_of_current_mirandas->append(im);
a61af66fc99e Initial load
duke
parents:
diff changeset
553 }
a61af66fc99e Initial load
duke
parents:
diff changeset
554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
558
a61af66fc99e Initial load
duke
parents:
diff changeset
559 void klassVtable::get_mirandas(GrowableArray<methodOop>* mirandas,
a61af66fc99e Initial load
duke
parents:
diff changeset
560 klassOop super, objArrayOop class_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
561 objArrayOop local_interfaces) {
a61af66fc99e Initial load
duke
parents:
diff changeset
562 assert((mirandas->length() == 0) , "current mirandas must be 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
563
a61af66fc99e Initial load
duke
parents:
diff changeset
564 // iterate thru the local interfaces looking for a miranda
a61af66fc99e Initial load
duke
parents:
diff changeset
565 int num_local_ifs = local_interfaces->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
566 for (int i = 0; i < num_local_ifs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
567 instanceKlass *ik = instanceKlass::cast(klassOop(local_interfaces->obj_at(i)));
a61af66fc99e Initial load
duke
parents:
diff changeset
568 add_new_mirandas_to_list(mirandas, ik->methods(), class_methods, super);
a61af66fc99e Initial load
duke
parents:
diff changeset
569 // iterate thru each local's super interfaces
a61af66fc99e Initial load
duke
parents:
diff changeset
570 objArrayOop super_ifs = ik->transitive_interfaces();
a61af66fc99e Initial load
duke
parents:
diff changeset
571 int num_super_ifs = super_ifs->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
572 for (int j = 0; j < num_super_ifs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
573 instanceKlass *sik = instanceKlass::cast(klassOop(super_ifs->obj_at(j)));
a61af66fc99e Initial load
duke
parents:
diff changeset
574 add_new_mirandas_to_list(mirandas, sik->methods(), class_methods, super);
a61af66fc99e Initial load
duke
parents:
diff changeset
575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
576 }
a61af66fc99e Initial load
duke
parents:
diff changeset
577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
578
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // get number of mirandas
a61af66fc99e Initial load
duke
parents:
diff changeset
580 int klassVtable::get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces) {
a61af66fc99e Initial load
duke
parents:
diff changeset
581 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
582 GrowableArray<methodOop>* mirandas = new GrowableArray<methodOop>(20);
a61af66fc99e Initial load
duke
parents:
diff changeset
583 get_mirandas(mirandas, super, class_methods, local_interfaces);
a61af66fc99e Initial load
duke
parents:
diff changeset
584 return mirandas->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
586
a61af66fc99e Initial load
duke
parents:
diff changeset
587 // fill in mirandas
a61af66fc99e Initial load
duke
parents:
diff changeset
588 void klassVtable::fill_in_mirandas(int& initialized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
590 GrowableArray<methodOop>* mirandas = new GrowableArray<methodOop>(20);
a61af66fc99e Initial load
duke
parents:
diff changeset
591 instanceKlass *this_ik = ik();
a61af66fc99e Initial load
duke
parents:
diff changeset
592 get_mirandas(mirandas, this_ik->super(), this_ik->methods(), this_ik->local_interfaces());
a61af66fc99e Initial load
duke
parents:
diff changeset
593 int num_mirandas = mirandas->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
594 for (int i = 0; i < num_mirandas; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
595 put_method_at(mirandas->at(i), initialized);
a61af66fc99e Initial load
duke
parents:
diff changeset
596 initialized++;
a61af66fc99e Initial load
duke
parents:
diff changeset
597 }
a61af66fc99e Initial load
duke
parents:
diff changeset
598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
599
a61af66fc99e Initial load
duke
parents:
diff changeset
600 void klassVtable::copy_vtable_to(vtableEntry* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
601 Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
a61af66fc99e Initial load
duke
parents:
diff changeset
602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
603
a61af66fc99e Initial load
duke
parents:
diff changeset
604 void klassVtable::adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
605 int methods_length, bool * trace_name_printed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
606 // search the vtable for uses of either obsolete or EMCP methods
a61af66fc99e Initial load
duke
parents:
diff changeset
607 for (int j = 0; j < methods_length; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 methodOop old_method = old_methods[j];
a61af66fc99e Initial load
duke
parents:
diff changeset
609 methodOop new_method = new_methods[j];
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 // In the vast majority of cases we could get the vtable index
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // by using: old_method->vtable_index()
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // However, there are rare cases, eg. sun.awt.X11.XDecoratedPeer.getX()
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // in sun.awt.X11.XFramePeer where methods occur more than once in the
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // vtable, so, alas, we must do an exhaustive search.
a61af66fc99e Initial load
duke
parents:
diff changeset
616 for (int index = 0; index < length(); index++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
617 if (unchecked_method_at(index) == old_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 put_method_at(new_method, index);
a61af66fc99e Initial load
duke
parents:
diff changeset
619
a61af66fc99e Initial load
duke
parents:
diff changeset
620 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
621 if (!(*trace_name_printed)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // RC_TRACE_MESG macro has an embedded ResourceMark
a61af66fc99e Initial load
duke
parents:
diff changeset
623 RC_TRACE_MESG(("adjust: name=%s",
a61af66fc99e Initial load
duke
parents:
diff changeset
624 Klass::cast(old_method->method_holder())->external_name()));
a61af66fc99e Initial load
duke
parents:
diff changeset
625 *trace_name_printed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
626 }
a61af66fc99e Initial load
duke
parents:
diff changeset
627 // RC_TRACE macro has an embedded ResourceMark
a61af66fc99e Initial load
duke
parents:
diff changeset
628 RC_TRACE(0x00100000, ("vtable method update: %s(%s)",
a61af66fc99e Initial load
duke
parents:
diff changeset
629 new_method->name()->as_C_string(),
a61af66fc99e Initial load
duke
parents:
diff changeset
630 new_method->signature()->as_C_string()));
a61af66fc99e Initial load
duke
parents:
diff changeset
631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
634 }
a61af66fc99e Initial load
duke
parents:
diff changeset
635 }
a61af66fc99e Initial load
duke
parents:
diff changeset
636
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 // Garbage collection
a61af66fc99e Initial load
duke
parents:
diff changeset
639 void klassVtable::oop_follow_contents() {
a61af66fc99e Initial load
duke
parents:
diff changeset
640 int len = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
641 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 MarkSweep::mark_and_push(adr_method_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645
a61af66fc99e Initial load
duke
parents:
diff changeset
646 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
647 void klassVtable::oop_follow_contents(ParCompactionManager* cm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
648 int len = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
649 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
650 PSParallelCompact::mark_and_push(cm, adr_method_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
653 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
654
a61af66fc99e Initial load
duke
parents:
diff changeset
655 void klassVtable::oop_adjust_pointers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
656 int len = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
657 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
658 MarkSweep::adjust_pointer(adr_method_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
661
a61af66fc99e Initial load
duke
parents:
diff changeset
662 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
663 void klassVtable::oop_update_pointers(ParCompactionManager* cm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
664 const int n = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
665 for (int i = 0; i < n; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 PSParallelCompact::adjust_pointer(adr_method_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
669
a61af66fc99e Initial load
duke
parents:
diff changeset
670 void klassVtable::oop_update_pointers(ParCompactionManager* cm,
a61af66fc99e Initial load
duke
parents:
diff changeset
671 HeapWord* beg_addr, HeapWord* end_addr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
672 const int n = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
673 const int entry_size = vtableEntry::size();
a61af66fc99e Initial load
duke
parents:
diff changeset
674
a61af66fc99e Initial load
duke
parents:
diff changeset
675 int beg_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
676 HeapWord* const method_0 = (HeapWord*)adr_method_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
677 if (beg_addr > method_0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
678 // it's safe to use cast, as we have guarantees on vtable size to be sane
a61af66fc99e Initial load
duke
parents:
diff changeset
679 beg_idx = int((pointer_delta(beg_addr, method_0) + entry_size - 1) / entry_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
681
a61af66fc99e Initial load
duke
parents:
diff changeset
682 oop* const beg_oop = adr_method_at(beg_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
683 oop* const end_oop = MIN2((oop*)end_addr, adr_method_at(n));
a61af66fc99e Initial load
duke
parents:
diff changeset
684 for (oop* cur_oop = beg_oop; cur_oop < end_oop; cur_oop += entry_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
685 PSParallelCompact::adjust_pointer(cur_oop);
a61af66fc99e Initial load
duke
parents:
diff changeset
686 }
a61af66fc99e Initial load
duke
parents:
diff changeset
687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
688 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
689
a61af66fc99e Initial load
duke
parents:
diff changeset
690 // Iterators
a61af66fc99e Initial load
duke
parents:
diff changeset
691 void klassVtable::oop_oop_iterate(OopClosure* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
692 int len = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
693 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
694 blk->do_oop(adr_method_at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
696 }
a61af66fc99e Initial load
duke
parents:
diff changeset
697
a61af66fc99e Initial load
duke
parents:
diff changeset
698 void klassVtable::oop_oop_iterate_m(OopClosure* blk, MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
699 int len = length();
a61af66fc99e Initial load
duke
parents:
diff changeset
700 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
701 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
702 if ((HeapWord*)adr_method_at(i) >= mr.start()) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
704 for (; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
705 oop* adr = adr_method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
706 if ((HeapWord*)adr < mr.end()) blk->do_oop(adr);
a61af66fc99e Initial load
duke
parents:
diff changeset
707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
709
a61af66fc99e Initial load
duke
parents:
diff changeset
710 //-----------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
711 // Itable code
a61af66fc99e Initial load
duke
parents:
diff changeset
712
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // Initialize a itableMethodEntry
a61af66fc99e Initial load
duke
parents:
diff changeset
714 void itableMethodEntry::initialize(methodOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
715 if (m == NULL) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
716
a61af66fc99e Initial load
duke
parents:
diff changeset
717 _method = m;
a61af66fc99e Initial load
duke
parents:
diff changeset
718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
719
a61af66fc99e Initial load
duke
parents:
diff changeset
720 klassItable::klassItable(instanceKlassHandle klass) {
a61af66fc99e Initial load
duke
parents:
diff changeset
721 _klass = klass;
a61af66fc99e Initial load
duke
parents:
diff changeset
722
a61af66fc99e Initial load
duke
parents:
diff changeset
723 if (klass->itable_length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
724 itableOffsetEntry* offset_entry = (itableOffsetEntry*)klass->start_of_itable();
a61af66fc99e Initial load
duke
parents:
diff changeset
725 if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized
a61af66fc99e Initial load
duke
parents:
diff changeset
726 // First offset entry points to the first method_entry
a61af66fc99e Initial load
duke
parents:
diff changeset
727 intptr_t* method_entry = (intptr_t *)(((address)klass->as_klassOop()) + offset_entry->offset());
a61af66fc99e Initial load
duke
parents:
diff changeset
728 intptr_t* end = klass->end_of_itable();
a61af66fc99e Initial load
duke
parents:
diff changeset
729
a61af66fc99e Initial load
duke
parents:
diff changeset
730 _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass->as_klassOop();
a61af66fc99e Initial load
duke
parents:
diff changeset
731 _size_offset_table = (method_entry - ((intptr_t*)offset_entry)) / itableOffsetEntry::size();
a61af66fc99e Initial load
duke
parents:
diff changeset
732 _size_method_table = (end - method_entry) / itableMethodEntry::size();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation");
a61af66fc99e Initial load
duke
parents:
diff changeset
734 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
735 }
a61af66fc99e Initial load
duke
parents:
diff changeset
736 }
a61af66fc99e Initial load
duke
parents:
diff changeset
737
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
738 // The length of the itable was either zero, or it has not yet been initialized.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
739 _table_offset = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
740 _size_offset_table = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
741 _size_method_table = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
742 }
a61af66fc99e Initial load
duke
parents:
diff changeset
743
a61af66fc99e Initial load
duke
parents:
diff changeset
744 // Garbage Collection
a61af66fc99e Initial load
duke
parents:
diff changeset
745
a61af66fc99e Initial load
duke
parents:
diff changeset
746 void klassItable::oop_follow_contents() {
a61af66fc99e Initial load
duke
parents:
diff changeset
747 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
748 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
749 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
750 MarkSweep::mark_and_push((oop*)&ioe->_interface);
a61af66fc99e Initial load
duke
parents:
diff changeset
751 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
752 }
a61af66fc99e Initial load
duke
parents:
diff changeset
753
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
755 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
756 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
757 MarkSweep::mark_and_push((oop*)&ime->_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
758 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
759 }
a61af66fc99e Initial load
duke
parents:
diff changeset
760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
761
a61af66fc99e Initial load
duke
parents:
diff changeset
762 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
763 void klassItable::oop_follow_contents(ParCompactionManager* cm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
764 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
765 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
766 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
767 PSParallelCompact::mark_and_push(cm, (oop*)&ioe->_interface);
a61af66fc99e Initial load
duke
parents:
diff changeset
768 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
769 }
a61af66fc99e Initial load
duke
parents:
diff changeset
770
a61af66fc99e Initial load
duke
parents:
diff changeset
771 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
772 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
773 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
774 PSParallelCompact::mark_and_push(cm, (oop*)&ime->_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
775 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
777 }
a61af66fc99e Initial load
duke
parents:
diff changeset
778 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
779
a61af66fc99e Initial load
duke
parents:
diff changeset
780 void klassItable::oop_adjust_pointers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
781 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
782 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
783 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 MarkSweep::adjust_pointer((oop*)&ioe->_interface);
a61af66fc99e Initial load
duke
parents:
diff changeset
785 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
787
a61af66fc99e Initial load
duke
parents:
diff changeset
788 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
789 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
790 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
791 MarkSweep::adjust_pointer((oop*)&ime->_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
792 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
795
a61af66fc99e Initial load
duke
parents:
diff changeset
796 #ifndef SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
797 void klassItable::oop_update_pointers(ParCompactionManager* cm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
798 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
799 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
800 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
801 PSParallelCompact::adjust_pointer((oop*)&ioe->_interface);
a61af66fc99e Initial load
duke
parents:
diff changeset
802 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
803 }
a61af66fc99e Initial load
duke
parents:
diff changeset
804
a61af66fc99e Initial load
duke
parents:
diff changeset
805 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
806 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
807 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
808 PSParallelCompact::adjust_pointer((oop*)&ime->_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
809 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
810 }
a61af66fc99e Initial load
duke
parents:
diff changeset
811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
812
a61af66fc99e Initial load
duke
parents:
diff changeset
813 void klassItable::oop_update_pointers(ParCompactionManager* cm,
a61af66fc99e Initial load
duke
parents:
diff changeset
814 HeapWord* beg_addr, HeapWord* end_addr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
815 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
816 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
817 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
818 oop* p = (oop*)&ioe->_interface;
a61af66fc99e Initial load
duke
parents:
diff changeset
819 PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
820 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
821 }
a61af66fc99e Initial load
duke
parents:
diff changeset
822
a61af66fc99e Initial load
duke
parents:
diff changeset
823 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
824 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
825 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
826 oop* p = (oop*)&ime->_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
827 PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
828 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
830 }
a61af66fc99e Initial load
duke
parents:
diff changeset
831 #endif // SERIALGC
a61af66fc99e Initial load
duke
parents:
diff changeset
832
a61af66fc99e Initial load
duke
parents:
diff changeset
833 // Iterators
a61af66fc99e Initial load
duke
parents:
diff changeset
834 void klassItable::oop_oop_iterate(OopClosure* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
835 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
836 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
837 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
838 blk->do_oop((oop*)&ioe->_interface);
a61af66fc99e Initial load
duke
parents:
diff changeset
839 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
840 }
a61af66fc99e Initial load
duke
parents:
diff changeset
841
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
843 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
844 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
845 blk->do_oop((oop*)&ime->_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
846 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
849
a61af66fc99e Initial load
duke
parents:
diff changeset
850 void klassItable::oop_oop_iterate_m(OopClosure* blk, MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
852 itableOffsetEntry* ioe = offset_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
853 for(int i = 0; i < _size_offset_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
854 oop* adr = (oop*)&ioe->_interface;
a61af66fc99e Initial load
duke
parents:
diff changeset
855 if (mr.contains(adr)) blk->do_oop(adr);
a61af66fc99e Initial load
duke
parents:
diff changeset
856 ioe++;
a61af66fc99e Initial load
duke
parents:
diff changeset
857 }
a61af66fc99e Initial load
duke
parents:
diff changeset
858
a61af66fc99e Initial load
duke
parents:
diff changeset
859 // method table
a61af66fc99e Initial load
duke
parents:
diff changeset
860 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
861 for(int j = 0; j < _size_method_table; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
862 oop* adr = (oop*)&ime->_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
863 if (mr.contains(adr)) blk->do_oop(adr);
a61af66fc99e Initial load
duke
parents:
diff changeset
864 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
866 }
a61af66fc99e Initial load
duke
parents:
diff changeset
867
a61af66fc99e Initial load
duke
parents:
diff changeset
868
a61af66fc99e Initial load
duke
parents:
diff changeset
869 static int initialize_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
870
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // Initialization
a61af66fc99e Initial load
duke
parents:
diff changeset
872 void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
873 // Cannot be setup doing bootstrapping, interfaces don't have
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
874 // itables, and klass with only ones entry have empty itables
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
875 if (Universe::is_bootstrapping() ||
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
876 _klass->is_interface() ||
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
877 _klass->itable_length() == itableOffsetEntry::size()) return;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
878
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
879 // There's alway an extra itable entry so we can null-terminate it.
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
880 guarantee(size_offset_table() >= 1, "too small");
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
881 int num_interfaces = size_offset_table() - 1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
882 if (num_interfaces > 0) {
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
883 if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count,
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
884 _klass->name()->as_C_string());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886
a61af66fc99e Initial load
duke
parents:
diff changeset
887 // Interate through all interfaces
a61af66fc99e Initial load
duke
parents:
diff changeset
888 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
889 for(i = 0; i < num_interfaces; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
890 itableOffsetEntry* ioe = offset_entry(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
891 KlassHandle interf_h (THREAD, ioe->interface_klass());
a61af66fc99e Initial load
duke
parents:
diff changeset
892 assert(interf_h() != NULL && ioe->offset() != 0, "bad offset entry in itable");
a61af66fc99e Initial load
duke
parents:
diff changeset
893 initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
895
a61af66fc99e Initial load
duke
parents:
diff changeset
896 }
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
897 // Check that the last entry is empty
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
898 itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1);
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
899 guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
900 }
a61af66fc99e Initial load
duke
parents:
diff changeset
901
a61af66fc99e Initial load
duke
parents:
diff changeset
902
a61af66fc99e Initial load
duke
parents:
diff changeset
903 void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
904 objArrayHandle methods(THREAD, instanceKlass::cast(interf_h())->methods());
a61af66fc99e Initial load
duke
parents:
diff changeset
905 int nof_methods = methods()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
906 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
907 KlassHandle klass = _klass;
a61af66fc99e Initial load
duke
parents:
diff changeset
908 assert(nof_methods > 0, "at least one method must exist for interface to be in vtable")
a61af66fc99e Initial load
duke
parents:
diff changeset
909 Handle interface_loader (THREAD, instanceKlass::cast(interf_h())->class_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
910 int ime_num = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
911
a61af66fc99e Initial load
duke
parents:
diff changeset
912 // Skip first methodOop if it is a class initializer
a61af66fc99e Initial load
duke
parents:
diff changeset
913 int i = ((methodOop)methods()->obj_at(0))->name() != vmSymbols::class_initializer_name() ? 0 : 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
914
a61af66fc99e Initial load
duke
parents:
diff changeset
915 // m, method_name, method_signature, klass reset each loop so they
a61af66fc99e Initial load
duke
parents:
diff changeset
916 // don't need preserving across check_signature_loaders call
a61af66fc99e Initial load
duke
parents:
diff changeset
917 // methods needs a handle in case of gc from check_signature_loaders
a61af66fc99e Initial load
duke
parents:
diff changeset
918 for(; i < nof_methods; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
919 methodOop m = (methodOop)methods()->obj_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
920 symbolOop method_name = m->name();
a61af66fc99e Initial load
duke
parents:
diff changeset
921 symbolOop method_signature = m->signature();
a61af66fc99e Initial load
duke
parents:
diff changeset
922
a61af66fc99e Initial load
duke
parents:
diff changeset
923 // This is same code as in Linkresolver::lookup_instance_method_in_klasses
a61af66fc99e Initial load
duke
parents:
diff changeset
924 methodOop target = klass->uncached_lookup_method(method_name, method_signature);
a61af66fc99e Initial load
duke
parents:
diff changeset
925 while (target != NULL && target->is_static()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
926 // continue with recursive lookup through the superclass
a61af66fc99e Initial load
duke
parents:
diff changeset
927 klassOop super = Klass::cast(target->method_holder())->super();
a61af66fc99e Initial load
duke
parents:
diff changeset
928 target = (super == NULL) ? methodOop(NULL) : Klass::cast(super)->uncached_lookup_method(method_name, method_signature);
a61af66fc99e Initial load
duke
parents:
diff changeset
929 }
a61af66fc99e Initial load
duke
parents:
diff changeset
930 if (target == NULL || !target->is_public() || target->is_abstract()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 // Entry do not resolve. Leave it empty
a61af66fc99e Initial load
duke
parents:
diff changeset
932 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
933 // Entry did resolve, check loader constraints before initializing
a61af66fc99e Initial load
duke
parents:
diff changeset
934 // if checkconstraints requested
a61af66fc99e Initial load
duke
parents:
diff changeset
935 methodHandle target_h (THREAD, target); // preserve across gc
a61af66fc99e Initial load
duke
parents:
diff changeset
936 if (checkconstraints) {
a61af66fc99e Initial load
duke
parents:
diff changeset
937 Handle method_holder_loader (THREAD, instanceKlass::cast(target->method_holder())->class_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
938 if (method_holder_loader() != interface_loader()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
939 ResourceMark rm(THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
940 char* failed_type_name =
a61af66fc99e Initial load
duke
parents:
diff changeset
941 SystemDictionary::check_signature_loaders(method_signature,
a61af66fc99e Initial load
duke
parents:
diff changeset
942 method_holder_loader,
a61af66fc99e Initial load
duke
parents:
diff changeset
943 interface_loader,
a61af66fc99e Initial load
duke
parents:
diff changeset
944 true, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
945 if (failed_type_name != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
946 const char* msg = "loader constraint violation in interface "
a61af66fc99e Initial load
duke
parents:
diff changeset
947 "itable initialization: when resolving method \"%s\" the class"
a61af66fc99e Initial load
duke
parents:
diff changeset
948 " loader (instance of %s) of the current class, %s, "
a61af66fc99e Initial load
duke
parents:
diff changeset
949 "and the class loader (instance of %s) for interface "
a61af66fc99e Initial load
duke
parents:
diff changeset
950 "%s have different Class objects for the type %s "
a61af66fc99e Initial load
duke
parents:
diff changeset
951 "used in the signature";
a61af66fc99e Initial load
duke
parents:
diff changeset
952 char* sig = target_h()->name_and_sig_as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
953 const char* loader1 = SystemDictionary::loader_name(method_holder_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
954 char* current = klass->name()->as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
955 const char* loader2 = SystemDictionary::loader_name(interface_loader());
a61af66fc99e Initial load
duke
parents:
diff changeset
956 char* iface = instanceKlass::cast(interf_h())->name()->as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
957 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
a61af66fc99e Initial load
duke
parents:
diff changeset
958 strlen(current) + strlen(loader2) + strlen(iface) +
a61af66fc99e Initial load
duke
parents:
diff changeset
959 strlen(failed_type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
960 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
a61af66fc99e Initial load
duke
parents:
diff changeset
961 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
a61af66fc99e Initial load
duke
parents:
diff changeset
962 iface, failed_type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
963 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
a61af66fc99e Initial load
duke
parents:
diff changeset
964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
965 }
a61af66fc99e Initial load
duke
parents:
diff changeset
966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
967
a61af66fc99e Initial load
duke
parents:
diff changeset
968 // ime may have moved during GC so recalculate address
a61af66fc99e Initial load
duke
parents:
diff changeset
969 itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h());
a61af66fc99e Initial load
duke
parents:
diff changeset
970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
971 // Progress to next entry
a61af66fc99e Initial load
duke
parents:
diff changeset
972 ime_num++;
a61af66fc99e Initial load
duke
parents:
diff changeset
973 }
a61af66fc99e Initial load
duke
parents:
diff changeset
974 }
a61af66fc99e Initial load
duke
parents:
diff changeset
975
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
976 // Update entry for specific methodOop
0
a61af66fc99e Initial load
duke
parents:
diff changeset
977 void klassItable::initialize_with_method(methodOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
978 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
979 for(int i = 0; i < _size_method_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
980 if (ime->method() == m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
981 ime->initialize(m);
a61af66fc99e Initial load
duke
parents:
diff changeset
982 }
a61af66fc99e Initial load
duke
parents:
diff changeset
983 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
984 }
a61af66fc99e Initial load
duke
parents:
diff changeset
985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
986
a61af66fc99e Initial load
duke
parents:
diff changeset
987 void klassItable::adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
a61af66fc99e Initial load
duke
parents:
diff changeset
988 int methods_length, bool * trace_name_printed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
989 // search the itable for uses of either obsolete or EMCP methods
a61af66fc99e Initial load
duke
parents:
diff changeset
990 for (int j = 0; j < methods_length; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
991 methodOop old_method = old_methods[j];
a61af66fc99e Initial load
duke
parents:
diff changeset
992 methodOop new_method = new_methods[j];
a61af66fc99e Initial load
duke
parents:
diff changeset
993 itableMethodEntry* ime = method_entry(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
994
a61af66fc99e Initial load
duke
parents:
diff changeset
995 for (int i = 0; i < _size_method_table; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
996 if (ime->method() == old_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
997 ime->initialize(new_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
998
a61af66fc99e Initial load
duke
parents:
diff changeset
999 if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 if (!(*trace_name_printed)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 // RC_TRACE_MESG macro has an embedded ResourceMark
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 RC_TRACE_MESG(("adjust: name=%s",
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 Klass::cast(old_method->method_holder())->external_name()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 *trace_name_printed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 // RC_TRACE macro has an embedded ResourceMark
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 RC_TRACE(0x00200000, ("itable method update: %s(%s)",
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 new_method->name()->as_C_string(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 new_method->signature()->as_C_string()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 ime++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1017
a61af66fc99e Initial load
duke
parents:
diff changeset
1018
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 // Setup
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 class InterfaceVisiterClosure : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 virtual void doit(klassOop intf, int method_count) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1024
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 // Visit all interfaces with at-least one method (excluding <clinit>)
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 void visit_all_interfaces(objArrayOop transitive_intf, InterfaceVisiterClosure *blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 // Handle array argument
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 for(int i = 0; i < transitive_intf->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 klassOop intf = (klassOop)transitive_intf->obj_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 assert(Klass::cast(intf)->is_interface(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1031
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // Find no. of methods excluding a <clinit>
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 int method_count = instanceKlass::cast(intf)->methods()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 if (method_count > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 methodOop m = (methodOop)instanceKlass::cast(intf)->methods()->obj_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 assert(m != NULL && m->is_method(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 if (m->name() == vmSymbols::object_initializer_name()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 method_count--;
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1041
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 // Only count interfaces with at least one method
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 if (method_count > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 blk->doit(intf, method_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1048
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 class CountInterfacesClosure : public InterfaceVisiterClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 int _nof_methods;
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 int _nof_interfaces;
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 CountInterfacesClosure() { _nof_methods = 0; _nof_interfaces = 0; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1055
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 int nof_methods() const { return _nof_methods; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 int nof_interfaces() const { return _nof_interfaces; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1058
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 void doit(klassOop intf, int method_count) { _nof_methods += method_count; _nof_interfaces++; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1061
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 class SetupItableClosure : public InterfaceVisiterClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 itableOffsetEntry* _offset_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 itableMethodEntry* _method_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 address _klass_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 SetupItableClosure(address klass_begin, itableOffsetEntry* offset_entry, itableMethodEntry* method_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 _klass_begin = klass_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 _offset_entry = offset_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 _method_entry = method_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1073
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 itableMethodEntry* method_entry() const { return _method_entry; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1075
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 void doit(klassOop intf, int method_count) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 int offset = ((address)_method_entry) - _klass_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 _offset_entry->initialize(intf, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 _offset_entry++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 _method_entry += method_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1083
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 int klassItable::compute_itable_size(objArrayHandle transitive_interfaces) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 // Count no of interfaces and total number of interface methods
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 CountInterfacesClosure cic;
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 visit_all_interfaces(transitive_interfaces(), &cic);
a61af66fc99e Initial load
duke
parents:
diff changeset
1088
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
1089 // There's alway an extra itable entry so we can null-terminate it.
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
1090 int itable_size = calc_itable_size(cic.nof_interfaces() + 1, cic.nof_methods());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1091
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 // Statistics
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 update_stats(itable_size * HeapWordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1094
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 return itable_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1097
a61af66fc99e Initial load
duke
parents:
diff changeset
1098
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 // Fill out offset table and interface klasses into the itable space
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 void klassItable::setup_itable_offset_table(instanceKlassHandle klass) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 if (klass->itable_length() == 0) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 assert(!klass->is_interface(), "Should have zero length itable");
a61af66fc99e Initial load
duke
parents:
diff changeset
1103
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 // Count no of interfaces and total number of interface methods
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 CountInterfacesClosure cic;
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 visit_all_interfaces(klass->transitive_interfaces(), &cic);
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 int nof_methods = cic.nof_methods();
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 int nof_interfaces = cic.nof_interfaces();
a61af66fc99e Initial load
duke
parents:
diff changeset
1109
16
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
1110 // Add one extra entry so we can null-terminate the table
f8236e79048a 6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents: 0
diff changeset
1111 nof_interfaces++;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1112
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 assert(compute_itable_size(objArrayHandle(klass->transitive_interfaces())) ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 calc_itable_size(nof_interfaces, nof_methods),
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 "mismatch calculation of itable size");
a61af66fc99e Initial load
duke
parents:
diff changeset
1116
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 // Fill-out offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 itableOffsetEntry* ioe = (itableOffsetEntry*)klass->start_of_itable();
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 itableMethodEntry* ime = (itableMethodEntry*)(ioe + nof_interfaces);
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 intptr_t* end = klass->end_of_itable();
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
1121 assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_static_fields(), "wrong offset calculation (1)");
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
1122 assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1123
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 // Visit all interfaces and initialize itable offset table
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 SetupItableClosure sic((address)klass->as_klassOop(), ioe, ime);
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 visit_all_interfaces(klass->transitive_interfaces(), &sic);
a61af66fc99e Initial load
duke
parents:
diff changeset
1127
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 ime = sic.method_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 oop* v = (oop*) klass->end_of_itable();
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 assert( (oop*)(ime) == v, "wrong offset calculation (2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1134
a61af66fc99e Initial load
duke
parents:
diff changeset
1135
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 // m must be a method in an interface
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 int klassItable::compute_itable_index(methodOop m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 klassOop intf = m->method_holder();
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 assert(instanceKlass::cast(intf)->is_interface(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 objArrayOop methods = instanceKlass::cast(intf)->methods();
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 int index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 while(methods->obj_at(index) != m) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 assert(index < methods->length(), "should find index for resolve_invoke");
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 // Adjust for <clinit>, which is left out of table if first method
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 index--;
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 return index;
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1152
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 void klassVtable::verify(outputStream* st, bool forced) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 // make sure table is initialized
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 if (!Universe::is_fully_initialized()) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 // avoid redundant verifies
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 if (!forced && _verify_count == Universe::verify_count()) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 _verify_count = Universe::verify_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 oop* end_of_obj = (oop*)_klass() + _klass()->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 oop* end_of_vtable = (oop *)&table()[_length];
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 if (end_of_vtable > end_of_obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1164 fatal1("klass %s: klass object too short (vtable extends beyond end)",
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 _klass->internal_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1167
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 for (int i = 0; i < _length; i++) table()[i].verify(this, st);
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 // verify consistency with superKlass vtable
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 klassOop super = _klass->super();
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 if (super != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 instanceKlass* sk = instanceKlass::cast(super);
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 klassVtable* vt = sk->vtable();
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 for (int i = 0; i < vt->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 verify_against(st, vt, i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1179
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 void klassVtable::verify_against(outputStream* st, klassVtable* vt, int index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 vtableEntry* vte = &vt->table()[index];
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 if (vte->method()->name() != table()[index].method()->name() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 vte->method()->signature() != table()[index].method()->signature()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 fatal("mismatched name/signature of vtable entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1187
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 void klassVtable::print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 tty->print("klassVtable for klass %s (length %d):\n", _klass->internal_name(), length());
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 for (int i = 0; i < length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 table()[i].print();
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1198
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 void vtableEntry::verify(klassVtable* vt, outputStream* st) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true));
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 assert(method() != NULL, "must have set method");
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 method()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 // we sub_type, because it could be a miranda method
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 if (!vt->klass()->is_subtype_of(method()->method_holder())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 print();
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 fatal1("vtableEntry %#lx: method is from subclass", this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1211
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1213
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 void vtableEntry::print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 tty->print("vtableEntry %s: ", method()->name()->as_C_string());
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 if (Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 tty->print("m %#lx ", (address)method());
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1221
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 class VtableStats : AllStatic {
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 static int no_klasses; // # classes with vtables
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 static int no_array_klasses; // # array classes
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 static int no_instance_klasses; // # instanceKlasses
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 static int sum_of_vtable_len; // total # of vtable entries
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 static int sum_of_array_vtable_len; // total # of vtable entries in array klasses only
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 static int fixed; // total fixed overhead in bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 static int filler; // overhead caused by filler bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 static int entries; // total bytes consumed by vtable entries
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 static int array_entries; // total bytes consumed by array vtable entries
a61af66fc99e Initial load
duke
parents:
diff changeset
1233
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 static void do_class(klassOop k) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 Klass* kl = k->klass_part();
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 klassVtable* vt = kl->vtable();
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 if (vt == NULL) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 no_klasses++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 if (kl->oop_is_instance()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 no_instance_klasses++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 kl->array_klasses_do(do_class);
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 if (kl->oop_is_array()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 no_array_klasses++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 sum_of_array_vtable_len += vt->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 sum_of_vtable_len += vt->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1249
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 static void compute() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 SystemDictionary::classes_do(do_class);
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 fixed = no_klasses * oopSize; // vtable length
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 // filler size is a conservative approximation
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 filler = oopSize * (no_klasses - no_instance_klasses) * (sizeof(instanceKlass) - sizeof(arrayKlass) - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 entries = sizeof(vtableEntry) * sum_of_vtable_len;
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 array_entries = sizeof(vtableEntry) * sum_of_array_vtable_len;
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1259
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 int VtableStats::no_klasses = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 int VtableStats::no_array_klasses = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 int VtableStats::no_instance_klasses = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 int VtableStats::sum_of_vtable_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 int VtableStats::sum_of_array_vtable_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 int VtableStats::fixed = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 int VtableStats::filler = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 int VtableStats::entries = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 int VtableStats::array_entries = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1269
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 void klassVtable::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 VtableStats::compute();
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 tty->print_cr("vtable statistics:");
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 tty->print_cr("%6d classes (%d instance, %d array)", VtableStats::no_klasses, VtableStats::no_instance_klasses, VtableStats::no_array_klasses);
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 int total = VtableStats::fixed + VtableStats::filler + VtableStats::entries;
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 tty->print_cr("%6d bytes fixed overhead (refs + vtable object header)", VtableStats::fixed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 tty->print_cr("%6d bytes filler overhead", VtableStats::filler);
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 tty->print_cr("%6d bytes for vtable entries (%d for arrays)", VtableStats::entries, VtableStats::array_entries);
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 tty->print_cr("%6d bytes total", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1282
a61af66fc99e Initial load
duke
parents:
diff changeset
1283 bool klassVtable::check_no_old_entries() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 // Check that there really is no entry
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 for (int i = 0; i < length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 methodOop m = unchecked_method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 if (m != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 if (m->is_old()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1295
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 void klassVtable::dump_vtable() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 tty->print_cr("vtable dump --");
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 for (int i = 0; i < length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 methodOop m = unchecked_method_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 if (m != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 tty->print(" (%5d) ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 m->access_flags().print_on(tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 tty->print(" -- ");
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 m->print_name(tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1309
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 int klassItable::_total_classes; // Total no. of classes with itables
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 long klassItable::_total_size; // Total no. of bytes used for itables
a61af66fc99e Initial load
duke
parents:
diff changeset
1312
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 void klassItable::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 tty->print_cr("itable statistics:");
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 tty->print_cr("%6d classes with itables", _total_classes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 tty->print_cr("%6d K uses for itables (average by class: %d bytes)", _total_size / K, _total_size / _total_classes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1318
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 #endif // PRODUCT