Tue, 23 Nov 2010 13:22:55 -0800
6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg
1 /*
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "classfile/loaderConstraints.hpp"
27 #include "memory/resourceArea.hpp"
28 #include "oops/oop.inline.hpp"
29 #include "runtime/handles.inline.hpp"
30 #include "runtime/safepoint.hpp"
31 #include "utilities/hashtable.inline.hpp"
33 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
34 : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
37 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
38 unsigned int hash, symbolOop name,
39 klassOop klass, int num_loaders,
40 int max_loaders) {
41 LoaderConstraintEntry* entry;
42 entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass);
43 entry->set_name(name);
44 entry->set_num_loaders(num_loaders);
45 entry->set_max_loaders(max_loaders);
46 return entry;
47 }
50 void LoaderConstraintTable::oops_do(OopClosure* f) {
51 for (int index = 0; index < table_size(); index++) {
52 for (LoaderConstraintEntry* probe = bucket(index);
53 probe != NULL;
54 probe = probe->next()) {
55 f->do_oop((oop*)(probe->name_addr()));
56 if (probe->klass() != NULL) {
57 f->do_oop((oop*)probe->klass_addr());
58 }
59 for (int n = 0; n < probe->num_loaders(); n++) {
60 if (probe->loader(n) != NULL) {
61 f->do_oop(probe->loader_addr(n));
62 }
63 }
64 }
65 }
66 }
68 // We must keep the symbolOop used in the name alive. We'll use the
69 // loaders to decide if a particular entry can be purged.
70 void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) {
71 // We must keep the symbolOop used in the name alive.
72 for (int cindex = 0; cindex < table_size(); cindex++) {
73 for (LoaderConstraintEntry* lc_probe = bucket(cindex);
74 lc_probe != NULL;
75 lc_probe = lc_probe->next()) {
76 assert (lc_probe->name() != NULL, "corrupted loader constraint table");
77 blk->do_oop((oop*)lc_probe->name_addr());
78 }
79 }
80 }
83 // The loaderConstraintTable must always be accessed with the
84 // SystemDictionary lock held. This is true even for readers as
85 // entries in the table could be being dynamically resized.
87 LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
88 symbolHandle name, Handle loader) {
90 unsigned int hash = compute_hash(name);
91 int index = hash_to_index(hash);
92 LoaderConstraintEntry** pp = bucket_addr(index);
93 while (*pp) {
94 LoaderConstraintEntry* p = *pp;
95 if (p->hash() == hash) {
96 if (p->name() == name()) {
97 for (int i = p->num_loaders() - 1; i >= 0; i--) {
98 if (p->loader(i) == loader()) {
99 return pp;
100 }
101 }
102 }
103 }
104 pp = p->next_addr();
105 }
106 return pp;
107 }
110 void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) {
111 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
112 // Remove unloaded entries from constraint table
113 for (int index = 0; index < table_size(); index++) {
114 LoaderConstraintEntry** p = bucket_addr(index);
115 while(*p) {
116 LoaderConstraintEntry* probe = *p;
117 klassOop klass = probe->klass();
118 // Remove klass that is no longer alive
119 if (klass != NULL && !is_alive->do_object_b(klass)) {
120 probe->set_klass(NULL);
121 if (TraceLoaderConstraints) {
122 ResourceMark rm;
123 tty->print_cr("[Purging class object from constraint for name %s,"
124 " loader list:",
125 probe->name()->as_C_string());
126 for (int i = 0; i < probe->num_loaders(); i++) {
127 tty->print_cr("[ [%d]: %s", i,
128 SystemDictionary::loader_name(probe->loader(i)));
129 }
130 }
131 }
132 // Remove entries no longer alive from loader array
133 int n = 0;
134 while (n < probe->num_loaders()) {
135 if (probe->loader(n) != NULL) {
136 if (!is_alive->do_object_b(probe->loader(n))) {
137 if (TraceLoaderConstraints) {
138 ResourceMark rm;
139 tty->print_cr("[Purging loader %s from constraint for name %s",
140 SystemDictionary::loader_name(probe->loader(n)),
141 probe->name()->as_C_string()
142 );
143 }
145 // Compact array
146 int num = probe->num_loaders() - 1;
147 probe->set_num_loaders(num);
148 probe->set_loader(n, probe->loader(num));
149 probe->set_loader(num, NULL);
151 if (TraceLoaderConstraints) {
152 ResourceMark rm;
153 tty->print_cr("[New loader list:");
154 for (int i = 0; i < probe->num_loaders(); i++) {
155 tty->print_cr("[ [%d]: %s", i,
156 SystemDictionary::loader_name(probe->loader(i)));
157 }
158 }
160 continue; // current element replaced, so restart without
161 // incrementing n
162 }
163 }
164 n++;
165 }
166 // Check whether entry should be purged
167 if (probe->num_loaders() < 2) {
168 if (TraceLoaderConstraints) {
169 ResourceMark rm;
170 tty->print("[Purging complete constraint for name %s\n",
171 probe->name()->as_C_string());
172 }
174 // Purge entry
175 *p = probe->next();
176 FREE_C_HEAP_ARRAY(oop, probe->loaders());
177 free_entry(probe);
178 } else {
179 #ifdef ASSERT
180 assert(is_alive->do_object_b(probe->name()), "name should be live");
181 if (probe->klass() != NULL) {
182 assert(is_alive->do_object_b(probe->klass()), "klass should be live");
183 }
184 for (n = 0; n < probe->num_loaders(); n++) {
185 if (probe->loader(n) != NULL) {
186 assert(is_alive->do_object_b(probe->loader(n)), "loader should be live");
187 }
188 }
189 #endif
190 // Go to next entry
191 p = probe->next_addr();
192 }
193 }
194 }
195 }
197 bool LoaderConstraintTable::add_entry(symbolHandle class_name,
198 klassOop klass1, Handle class_loader1,
199 klassOop klass2, Handle class_loader2) {
200 int failure_code = 0; // encode different reasons for failing
202 if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
203 failure_code = 1;
204 } else {
205 klassOop klass = klass1 != NULL ? klass1 : klass2;
207 LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
208 class_loader1);
209 if (*pp1 != NULL && (*pp1)->klass() != NULL) {
210 if (klass != NULL) {
211 if (klass != (*pp1)->klass()) {
212 failure_code = 2;
213 }
214 } else {
215 klass = (*pp1)->klass();
216 }
217 }
219 LoaderConstraintEntry** pp2 = find_loader_constraint(class_name,
220 class_loader2);
221 if (*pp2 != NULL && (*pp2)->klass() != NULL) {
222 if (klass != NULL) {
223 if (klass != (*pp2)->klass()) {
224 failure_code = 3;
225 }
226 } else {
227 klass = (*pp2)->klass();
228 }
229 }
231 if (failure_code == 0) {
232 if (*pp1 == NULL && *pp2 == NULL) {
233 unsigned int hash = compute_hash(class_name);
234 int index = hash_to_index(hash);
235 LoaderConstraintEntry* p;
236 p = new_entry(hash, class_name(), klass, 2, 2);
237 p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2));
238 p->set_loader(0, class_loader1());
239 p->set_loader(1, class_loader2());
240 p->set_klass(klass);
241 p->set_next(bucket(index));
242 set_entry(index, p);
243 if (TraceLoaderConstraints) {
244 ResourceMark rm;
245 tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
246 " loader[1]: %s ]\n",
247 class_name()->as_C_string(),
248 SystemDictionary::loader_name(class_loader1()),
249 SystemDictionary::loader_name(class_loader2())
250 );
251 }
252 } else if (*pp1 == *pp2) {
253 /* constraint already imposed */
254 if ((*pp1)->klass() == NULL) {
255 (*pp1)->set_klass(klass);
256 if (TraceLoaderConstraints) {
257 ResourceMark rm;
258 tty->print("[Setting class object in existing constraint for"
259 " name: %s and loader %s ]\n",
260 class_name()->as_C_string(),
261 SystemDictionary::loader_name(class_loader1())
262 );
263 }
264 } else {
265 assert((*pp1)->klass() == klass, "loader constraints corrupted");
266 }
267 } else if (*pp1 == NULL) {
268 extend_loader_constraint(*pp2, class_loader1, klass);
269 } else if (*pp2 == NULL) {
270 extend_loader_constraint(*pp1, class_loader2, klass);
271 } else {
272 merge_loader_constraints(pp1, pp2, klass);
273 }
274 }
275 }
277 if (failure_code != 0 && TraceLoaderConstraints) {
278 ResourceMark rm;
279 const char* reason = "";
280 switch(failure_code) {
281 case 1: reason = "the class objects presented by loader[0] and loader[1]"
282 " are different"; break;
283 case 2: reason = "the class object presented by loader[0] does not match"
284 " the stored class object in the constraint"; break;
285 case 3: reason = "the class object presented by loader[1] does not match"
286 " the stored class object in the constraint"; break;
287 default: reason = "unknown reason code";
288 }
289 tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
290 " loader[1]: %s, Reason: %s ]\n",
291 class_name()->as_C_string(),
292 SystemDictionary::loader_name(class_loader1()),
293 SystemDictionary::loader_name(class_loader2()),
294 reason
295 );
296 }
298 return failure_code == 0;
299 }
302 // return true if the constraint was updated, false if the constraint is
303 // violated
304 bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
305 Handle loader,
306 symbolHandle name) {
307 LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
308 if (p && p->klass() != NULL && p->klass() != k()) {
309 if (TraceLoaderConstraints) {
310 ResourceMark rm;
311 tty->print("[Constraint check failed for name %s, loader %s: "
312 "the presented class object differs from that stored ]\n",
313 name()->as_C_string(),
314 SystemDictionary::loader_name(loader()));
315 }
316 return false;
317 } else {
318 if (p && p->klass() == NULL) {
319 p->set_klass(k());
320 if (TraceLoaderConstraints) {
321 ResourceMark rm;
322 tty->print("[Updating constraint for name %s, loader %s, "
323 "by setting class object ]\n",
324 name()->as_C_string(),
325 SystemDictionary::loader_name(loader()));
326 }
327 }
328 return true;
329 }
330 }
332 klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name,
333 Handle loader) {
334 LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
335 if (p != NULL && p->klass() != NULL)
336 return p->klass();
338 // No constraints, or else no klass loaded yet.
339 return NULL;
340 }
342 void LoaderConstraintTable::ensure_loader_constraint_capacity(
343 LoaderConstraintEntry *p,
344 int nfree) {
345 if (p->max_loaders() - p->num_loaders() < nfree) {
346 int n = nfree + p->num_loaders();
347 oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n);
348 memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
349 p->set_max_loaders(n);
350 FREE_C_HEAP_ARRAY(oop, p->loaders());
351 p->set_loaders(new_loaders);
352 }
353 }
356 void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
357 Handle loader,
358 klassOop klass) {
359 ensure_loader_constraint_capacity(p, 1);
360 int num = p->num_loaders();
361 p->set_loader(num, loader());
362 p->set_num_loaders(num + 1);
363 if (TraceLoaderConstraints) {
364 ResourceMark rm;
365 tty->print("[Extending constraint for name %s by adding loader[%d]: %s %s",
366 p->name()->as_C_string(),
367 num,
368 SystemDictionary::loader_name(loader()),
369 (p->klass() == NULL ? " and setting class object ]\n" : " ]\n")
370 );
371 }
372 if (p->klass() == NULL) {
373 p->set_klass(klass);
374 } else {
375 assert(klass == NULL || p->klass() == klass, "constraints corrupted");
376 }
377 }
380 void LoaderConstraintTable::merge_loader_constraints(
381 LoaderConstraintEntry** pp1,
382 LoaderConstraintEntry** pp2,
383 klassOop klass) {
384 // make sure *pp1 has higher capacity
385 if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
386 LoaderConstraintEntry** tmp = pp2;
387 pp2 = pp1;
388 pp1 = tmp;
389 }
391 LoaderConstraintEntry* p1 = *pp1;
392 LoaderConstraintEntry* p2 = *pp2;
394 ensure_loader_constraint_capacity(p1, p2->num_loaders());
396 for (int i = 0; i < p2->num_loaders(); i++) {
397 int num = p1->num_loaders();
398 p1->set_loader(num, p2->loader(i));
399 p1->set_num_loaders(num + 1);
400 }
402 if (TraceLoaderConstraints) {
403 ResourceMark rm;
404 tty->print_cr("[Merged constraints for name %s, new loader list:",
405 p1->name()->as_C_string()
406 );
408 for (int i = 0; i < p1->num_loaders(); i++) {
409 tty->print_cr("[ [%d]: %s", i,
410 SystemDictionary::loader_name(p1->loader(i)));
411 }
412 if (p1->klass() == NULL) {
413 tty->print_cr("[... and setting class object]");
414 }
415 }
417 // p1->klass() will hold NULL if klass, p2->klass(), and old
418 // p1->klass() are all NULL. In addition, all three must have
419 // matching non-NULL values, otherwise either the constraints would
420 // have been violated, or the constraints had been corrupted (and an
421 // assertion would fail).
422 if (p2->klass() != NULL) {
423 assert(p2->klass() == klass, "constraints corrupted");
424 }
425 if (p1->klass() == NULL) {
426 p1->set_klass(klass);
427 } else {
428 assert(p1->klass() == klass, "constraints corrupted");
429 }
431 *pp2 = p2->next();
432 FREE_C_HEAP_ARRAY(oop, p2->loaders());
433 free_entry(p2);
434 return;
435 }
438 void LoaderConstraintTable::verify(Dictionary* dictionary,
439 PlaceholderTable* placeholders) {
440 Thread *thread = Thread::current();
441 for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
442 for (LoaderConstraintEntry* probe = bucket(cindex);
443 probe != NULL;
444 probe = probe->next()) {
445 guarantee(probe->name()->is_symbol(), "should be symbol");
446 if (probe->klass() != NULL) {
447 instanceKlass* ik = instanceKlass::cast(probe->klass());
448 guarantee(ik->name() == probe->name(), "name should match");
449 symbolHandle name (thread, ik->name());
450 Handle loader(thread, ik->class_loader());
451 unsigned int d_hash = dictionary->compute_hash(name, loader);
452 int d_index = dictionary->hash_to_index(d_hash);
453 klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
454 if (k != NULL) {
455 // We found the class in the system dictionary, so we should
456 // make sure that the klassOop matches what we already have.
457 guarantee(k == probe->klass(), "klass should be in dictionary");
458 } else {
459 // If we don't find the class in the system dictionary, it
460 // has to be in the placeholders table.
461 unsigned int p_hash = placeholders->compute_hash(name, loader);
462 int p_index = placeholders->hash_to_index(p_hash);
463 PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
464 name, loader);
466 // The instanceKlass might not be on the entry, so the only
467 // thing we can check here is whether we were successful in
468 // finding the class in the placeholders table.
469 guarantee(entry != NULL, "klass should be in the placeholders");
470 }
471 }
472 for (int n = 0; n< probe->num_loaders(); n++) {
473 guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
474 }
475 }
476 }
477 }
479 #ifndef PRODUCT
481 // Called with the system dictionary lock held
482 void LoaderConstraintTable::print() {
483 ResourceMark rm;
485 assert_locked_or_safepoint(SystemDictionary_lock);
486 tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
487 for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
488 for (LoaderConstraintEntry* probe = bucket(cindex);
489 probe != NULL;
490 probe = probe->next()) {
491 tty->print("%4d: ", cindex);
492 probe->name()->print();
493 tty->print(" , loaders:");
494 for (int n = 0; n < probe->num_loaders(); n++) {
495 probe->loader(n)->print_value();
496 tty->print(", ");
497 }
498 tty->cr();
499 }
500 }
501 }
502 #endif