1 /* 2 * Copyright (c) 2017, 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 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/protectionDomainCache.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "memory/iterator.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "oops/oop.inline.hpp" 31 #include "utilities/hashtable.inline.hpp" 32 33 unsigned int ProtectionDomainCacheTable::compute_hash(Handle protection_domain) { 34 // Identity hash can safepoint, so keep protection domain in a Handle. 35 return (unsigned int)(protection_domain->identity_hash()); 36 } 37 38 int ProtectionDomainCacheTable::index_for(Handle protection_domain) { 39 return hash_to_index(compute_hash(protection_domain)); 40 } 41 42 ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size) 43 : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry)) 44 { 45 } 46 47 void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) { 48 assert(SafepointSynchronize::is_at_safepoint(), "must be"); 49 for (int i = 0; i < table_size(); ++i) { 50 ProtectionDomainCacheEntry** p = bucket_addr(i); 51 ProtectionDomainCacheEntry* entry = bucket(i); 52 while (entry != NULL) { 53 if (is_alive->do_object_b(entry->literal())) { 54 p = entry->next_addr(); 55 } else { 56 if (log_is_enabled(Debug, protectiondomain)) { 57 outputStream* log = Log(protectiondomain)::debug_stream(); 58 log->print("protection domain unlinked: "); 59 entry->literal()->print_value_on(log); 60 log->cr(); 61 } 62 *p = entry->next(); 63 free_entry(entry); 64 } 65 entry = *p; 66 } 67 } 68 } 69 70 void ProtectionDomainCacheTable::oops_do(OopClosure* f) { 71 for (int index = 0; index < table_size(); index++) { 72 for (ProtectionDomainCacheEntry* probe = bucket(index); 73 probe != NULL; 74 probe = probe->next()) { 75 probe->oops_do(f); 76 } 77 } 78 } 79 80 #ifndef PRODUCT 81 void ProtectionDomainCacheTable::print() { 82 tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)", 83 table_size(), number_of_entries()); 84 for (int index = 0; index < table_size(); index++) { 85 for (ProtectionDomainCacheEntry* probe = bucket(index); 86 probe != NULL; 87 probe = probe->next()) { 88 probe->print(); 89 } 90 } 91 } 92 93 void ProtectionDomainCacheEntry::print() { 94 tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " next " PTR_FORMAT, 95 p2i(this), p2i(literal()), p2i(next())); 96 } 97 #endif 98 99 void ProtectionDomainCacheTable::verify() { 100 verify_table<ProtectionDomainCacheEntry>("Protection Domain Table"); 101 } 102 103 void ProtectionDomainCacheEntry::verify() { 104 guarantee(literal()->is_oop(), "must be an oop"); 105 } 106 107 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(Handle protection_domain) { 108 unsigned int hash = compute_hash(protection_domain); 109 int index = hash_to_index(hash); 110 111 ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain); 112 if (entry == NULL) { 113 entry = add_entry(index, hash, protection_domain); 114 } 115 return entry; 116 } 117 118 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, Handle protection_domain) { 119 for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) { 120 if (e->protection_domain() == protection_domain()) { 121 return e; 122 } 123 } 124 125 return NULL; 126 } 127 128 ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, Handle protection_domain) { 129 assert_locked_or_safepoint(SystemDictionary_lock); 130 assert(index == index_for(protection_domain), "incorrect index?"); 131 assert(find_entry(index, protection_domain) == NULL, "no double entry"); 132 133 ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain); 134 Hashtable<oop, mtClass>::add_entry(index, p); 135 return p; 136 }