1 /*
2  * Copyright (c) 2017, 2019, 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 #ifndef SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
26 #define SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
27 
28 #include "oops/oop.hpp"
29 #include "oops/weakHandle.hpp"
30 #include "memory/iterator.hpp"
31 #include "utilities/hashtable.hpp"
32 
33 // This class caches the approved protection domains that can access loaded classes.
34 // Dictionary entry pd_set point to entries in this hashtable.   Please refer
35 // to dictionary.hpp pd_set for more information about how protection domain entries
36 // are used.
37 // This table is walked during GC, rather than the class loader data graph dictionaries.
38 class ProtectionDomainCacheEntry : public HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass> {
39   friend class VMStructs;
40  public:
41   oop object();
42   oop object_no_keepalive();
43 
next()44   ProtectionDomainCacheEntry* next() {
45     return (ProtectionDomainCacheEntry*)HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass>::next();
46   }
47 
next_addr()48   ProtectionDomainCacheEntry** next_addr() {
49     return (ProtectionDomainCacheEntry**)HashtableEntry<WeakHandle<vm_class_loader_data>, mtClass>::next_addr();
50   }
51 
52   void verify();
53 };
54 
55 // The ProtectionDomainCacheTable contains all protection domain oops. The
56 // dictionary entries reference its entries instead of having references to oops
57 // directly.
58 // This is used to speed up system dictionary iteration: the oops in the
59 // protection domain are the only ones referring the Java heap. So when there is
60 // need to update these, instead of going over every entry of the system dictionary,
61 // we only need to iterate over this set.
62 // The amount of different protection domains used is typically magnitudes smaller
63 // than the number of system dictionary entries (loaded classes).
64 class ProtectionDomainCacheTable : public Hashtable<WeakHandle<vm_class_loader_data>, mtClass> {
65   friend class VMStructs;
66 private:
bucket(int i) const67   ProtectionDomainCacheEntry* bucket(int i) const {
68     return (ProtectionDomainCacheEntry*) Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::bucket(i);
69   }
70 
71   // The following method is not MT-safe and must be done under lock.
bucket_addr(int i)72   ProtectionDomainCacheEntry** bucket_addr(int i) {
73     return (ProtectionDomainCacheEntry**) Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::bucket_addr(i);
74   }
75 
new_entry(unsigned int hash,WeakHandle<vm_class_loader_data> protection_domain)76   ProtectionDomainCacheEntry* new_entry(unsigned int hash, WeakHandle<vm_class_loader_data> protection_domain) {
77     ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*)
78       Hashtable<WeakHandle<vm_class_loader_data>, mtClass>::new_entry(hash, protection_domain);
79     return entry;
80   }
81 
82   static unsigned int compute_hash(Handle protection_domain);
83 
84   int index_for(Handle protection_domain);
85   ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, Handle protection_domain);
86   ProtectionDomainCacheEntry* find_entry(int index, Handle protection_domain);
87 
88   bool _dead_entries;
89   int _total_oops_removed;
90 
91 public:
92   ProtectionDomainCacheTable(int table_size);
93   ProtectionDomainCacheEntry* get(Handle protection_domain);
94 
95   void unlink();
96 
97   void print_on(outputStream* st) const;
98   void verify();
99 
has_work()100   bool has_work() { return _dead_entries; }
101   void trigger_cleanup();
102 
removed_entries_count()103   int removed_entries_count() { return _total_oops_removed; };
104 };
105 
106 
107 class ProtectionDomainEntry :public CHeapObj<mtClass> {
108   friend class VMStructs;
109  public:
110   ProtectionDomainEntry* _next;
111   ProtectionDomainCacheEntry* _pd_cache;
112 
ProtectionDomainEntry(ProtectionDomainCacheEntry * pd_cache,ProtectionDomainEntry * next)113   ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) {
114     _pd_cache = pd_cache;
115     _next     = next;
116   }
117 
next()118   ProtectionDomainEntry* next() { return _next; }
set_next(ProtectionDomainEntry * entry)119   void set_next(ProtectionDomainEntry* entry) { _next = entry; }
120   oop object();
121   oop object_no_keepalive();
122 };
123 #endif // SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
124