1 /* 2 * Copyright (c) 2021, 2024, 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_CDS_LAMBDAPROXYCLASSINFO_HPP 26 #define SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP 27 #include "cds/metaspaceShared.hpp" 28 #include "classfile/javaClasses.hpp" 29 #include "utilities/growableArray.hpp" 30 #include "utilities/resourceHash.hpp" 31 32 class InstanceKlass; 33 class Method; 34 class Symbol; 35 class outputStream; 36 37 class LambdaProxyClassKey { 38 InstanceKlass* _caller_ik; 39 Symbol* _invoked_name; 40 Symbol* _invoked_type; 41 Symbol* _method_type; 42 Method* _member_method; 43 Symbol* _instantiated_method_type; 44 45 public: 46 LambdaProxyClassKey(InstanceKlass* caller_ik, 47 Symbol* invoked_name, 48 Symbol* invoked_type, 49 Symbol* method_type, 50 Method* member_method, 51 Symbol* instantiated_method_type) : 52 _caller_ik(caller_ik), 53 _invoked_name(invoked_name), 54 _invoked_type(invoked_type), 55 _method_type(method_type), 56 _member_method(member_method), 57 _instantiated_method_type(instantiated_method_type) {} 58 59 void metaspace_pointers_do(MetaspaceClosure* it) { 60 it->push(&_caller_ik); 61 it->push(&_invoked_name); 62 it->push(&_invoked_type); 63 it->push(&_method_type); 64 it->push(&_member_method); 65 it->push(&_instantiated_method_type); 66 } 67 68 bool equals(LambdaProxyClassKey const& other) const { 69 return _caller_ik == other._caller_ik && 70 _invoked_name == other._invoked_name && 71 _invoked_type == other._invoked_type && 72 _method_type == other._method_type && 73 _member_method == other._member_method && 74 _instantiated_method_type == other._instantiated_method_type; 75 } 76 77 unsigned int hash() const; 78 79 static unsigned int dumptime_hash(Symbol* sym) { 80 if (sym == nullptr) { 81 // _invoked_name maybe null 82 return 0; 83 } 84 return java_lang_String::hash_code((const jbyte*)sym->bytes(), sym->utf8_length()); 85 } 86 87 unsigned int dumptime_hash() const { 88 return dumptime_hash(_caller_ik->name()) + 89 dumptime_hash(_invoked_name) + 90 dumptime_hash(_invoked_type) + 91 dumptime_hash(_method_type) + 92 dumptime_hash(_instantiated_method_type); 93 } 94 95 static inline unsigned int DUMPTIME_HASH(LambdaProxyClassKey const& key) { 96 return (key.dumptime_hash()); 97 } 98 99 static inline bool DUMPTIME_EQUALS( 100 LambdaProxyClassKey const& k1, LambdaProxyClassKey const& k2) { 101 return (k1.equals(k2)); 102 } 103 104 InstanceKlass* caller_ik() const { return _caller_ik; } 105 Symbol* invoked_name() const { return _invoked_name; } 106 Symbol* invoked_type() const { return _invoked_type; } 107 Symbol* method_type() const { return _method_type; } 108 Method* member_method() const { return _member_method; } 109 Symbol* instantiated_method_type() const { return _instantiated_method_type; } 110 111 #ifndef PRODUCT 112 void print_on(outputStream* st) const; 113 #endif 114 }; 115 116 class RunTimeLambdaProxyClassKey { 117 u4 _caller_ik; 118 u4 _invoked_name; 119 u4 _invoked_type; 120 u4 _method_type; 121 u4 _member_method; 122 u4 _instantiated_method_type; 123 124 RunTimeLambdaProxyClassKey(u4 caller_ik, 125 u4 invoked_name, 126 u4 invoked_type, 127 u4 method_type, 128 u4 member_method, 129 u4 instantiated_method_type) : 130 _caller_ik(caller_ik), 131 _invoked_name(invoked_name), 132 _invoked_type(invoked_type), 133 _method_type(method_type), 134 _member_method(member_method), 135 _instantiated_method_type(instantiated_method_type) {} 136 137 public: 138 static RunTimeLambdaProxyClassKey init_for_dumptime(LambdaProxyClassKey& key) { 139 assert(ArchiveBuilder::is_active(), "sanity"); 140 ArchiveBuilder* b = ArchiveBuilder::current(); 141 142 u4 caller_ik = b->any_to_offset_u4(key.caller_ik()); 143 u4 invoked_name = b->any_to_offset_u4(key.invoked_name()); 144 u4 invoked_type = b->any_to_offset_u4(key.invoked_type()); 145 u4 method_type = b->any_to_offset_u4(key.method_type()); 146 u4 member_method = b->any_to_offset_u4(key.member_method()); 147 u4 instantiated_method_type = b->any_to_offset_u4(key.instantiated_method_type()); 148 149 return RunTimeLambdaProxyClassKey(caller_ik, invoked_name, invoked_type, method_type, 150 member_method, instantiated_method_type); 151 } 152 153 static RunTimeLambdaProxyClassKey init_for_runtime(InstanceKlass* caller_ik, 154 Symbol* invoked_name, 155 Symbol* invoked_type, 156 Symbol* method_type, 157 Method* member_method, 158 Symbol* instantiated_method_type) { 159 // All parameters must be in shared space, or else you'd get an assert in 160 // ArchiveUtils::to_offset(). 161 return RunTimeLambdaProxyClassKey(ArchiveUtils::to_offset(caller_ik), 162 ArchiveUtils::to_offset(invoked_name), 163 ArchiveUtils::to_offset(invoked_type), 164 ArchiveUtils::to_offset(method_type), 165 ArchiveUtils::to_offset(member_method), 166 ArchiveUtils::to_offset(instantiated_method_type)); 167 } 168 169 unsigned int hash() const; 170 bool equals(RunTimeLambdaProxyClassKey const& other) const { 171 return _caller_ik == other._caller_ik && 172 _invoked_name == other._invoked_name && 173 _invoked_type == other._invoked_type && 174 _method_type == other._method_type && 175 _member_method == other._member_method && 176 _instantiated_method_type == other._instantiated_method_type; 177 } 178 179 #ifndef PRODUCT 180 void print_on(outputStream* st) const; 181 #endif 182 }; 183 184 class DumpTimeLambdaProxyClassInfo { 185 public: 186 GrowableArray<InstanceKlass*>* _proxy_klasses; 187 DumpTimeLambdaProxyClassInfo() : _proxy_klasses(nullptr) {} 188 DumpTimeLambdaProxyClassInfo& operator=(const DumpTimeLambdaProxyClassInfo&) = delete; 189 ~DumpTimeLambdaProxyClassInfo(); 190 191 void add_proxy_klass(InstanceKlass* proxy_klass) { 192 if (_proxy_klasses == nullptr) { 193 _proxy_klasses = new (mtClassShared) GrowableArray<InstanceKlass*>(5, mtClassShared); 194 } 195 assert(_proxy_klasses != nullptr, "sanity"); 196 // Try to preserve the order. get_shared_lambda_proxy_class returns shared classes in reverse order. 197 _proxy_klasses->insert_before(0, proxy_klass); 198 } 199 200 void metaspace_pointers_do(MetaspaceClosure* it) { 201 for (int i=0; i<_proxy_klasses->length(); i++) { 202 it->push(_proxy_klasses->adr_at(i)); 203 } 204 } 205 }; 206 207 class RunTimeLambdaProxyClassInfo { 208 RunTimeLambdaProxyClassKey _key; 209 InstanceKlass* _proxy_klass_head; 210 public: 211 RunTimeLambdaProxyClassInfo(RunTimeLambdaProxyClassKey key, InstanceKlass* proxy_klass_head) : 212 _key(key), _proxy_klass_head(proxy_klass_head) {} 213 214 InstanceKlass* proxy_klass_head() const { return _proxy_klass_head; } 215 216 // Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS 217 static inline bool EQUALS( 218 const RunTimeLambdaProxyClassInfo* value, RunTimeLambdaProxyClassKey* key, int len_unused) { 219 return (value->_key.equals(*key)); 220 } 221 void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info); 222 223 unsigned int hash() const { 224 return _key.hash(); 225 } 226 RunTimeLambdaProxyClassKey key() const { 227 return _key; 228 } 229 #ifndef PRODUCT 230 void print_on(outputStream* st) const; 231 #endif 232 }; 233 234 class DumpTimeLambdaProxyClassDictionary 235 : public ResourceHashtable<LambdaProxyClassKey, 236 DumpTimeLambdaProxyClassInfo, 237 137, // prime number 238 AnyObj::C_HEAP, 239 mtClassShared, 240 LambdaProxyClassKey::DUMPTIME_HASH, 241 LambdaProxyClassKey::DUMPTIME_EQUALS> { 242 public: 243 DumpTimeLambdaProxyClassDictionary() : _count(0) {} 244 int _count; 245 }; 246 247 class LambdaProxyClassDictionary : public OffsetCompactHashtable< 248 RunTimeLambdaProxyClassKey*, 249 const RunTimeLambdaProxyClassInfo*, 250 RunTimeLambdaProxyClassInfo::EQUALS> {}; 251 252 #endif // SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP