1 /* 2 * Copyright (c) 2021, 2023, 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 106 void init_for_archive(LambdaProxyClassKey& dumptime_key); 107 108 #ifndef PRODUCT 109 void print_on(outputStream* st) const; 110 #endif 111 }; 112 113 class DumpTimeLambdaProxyClassInfo { 114 public: 115 GrowableArray<InstanceKlass*>* _proxy_klasses; 116 DumpTimeLambdaProxyClassInfo() : _proxy_klasses(nullptr) {} 117 DumpTimeLambdaProxyClassInfo& operator=(const DumpTimeLambdaProxyClassInfo&) = delete; 118 ~DumpTimeLambdaProxyClassInfo(); 119 120 void add_proxy_klass(InstanceKlass* proxy_klass) { 121 if (_proxy_klasses == nullptr) { 122 _proxy_klasses = new (mtClassShared) GrowableArray<InstanceKlass*>(5, mtClassShared); 123 } 124 assert(_proxy_klasses != nullptr, "sanity"); 125 _proxy_klasses->append(proxy_klass); 126 } 127 128 void metaspace_pointers_do(MetaspaceClosure* it) { 129 for (int i=0; i<_proxy_klasses->length(); i++) { 130 it->push(_proxy_klasses->adr_at(i)); 131 } 132 } 133 }; 134 135 class RunTimeLambdaProxyClassInfo { 136 LambdaProxyClassKey _key; 137 InstanceKlass* _proxy_klass_head; 138 public: 139 RunTimeLambdaProxyClassInfo(LambdaProxyClassKey key, InstanceKlass* proxy_klass_head) : 140 _key(key), _proxy_klass_head(proxy_klass_head) {} 141 142 InstanceKlass* proxy_klass_head() const { return _proxy_klass_head; } 143 144 // Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS 145 static inline bool EQUALS( 146 const RunTimeLambdaProxyClassInfo* value, LambdaProxyClassKey* key, int len_unused) { 147 return (value->_key.equals(*key)); 148 } 149 void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info); 150 151 unsigned int hash() const { 152 return _key.hash(); 153 } 154 LambdaProxyClassKey key() const { 155 return _key; 156 } 157 #ifndef PRODUCT 158 void print_on(outputStream* st) const; 159 #endif 160 }; 161 162 class DumpTimeLambdaProxyClassDictionary 163 : public ResourceHashtable<LambdaProxyClassKey, 164 DumpTimeLambdaProxyClassInfo, 165 137, // prime number 166 AnyObj::C_HEAP, 167 mtClassShared, 168 LambdaProxyClassKey::DUMPTIME_HASH, 169 LambdaProxyClassKey::DUMPTIME_EQUALS> { 170 public: 171 DumpTimeLambdaProxyClassDictionary() : _count(0) {} 172 int _count; 173 }; 174 175 class LambdaProxyClassDictionary : public OffsetCompactHashtable< 176 LambdaProxyClassKey*, 177 const RunTimeLambdaProxyClassInfo*, 178 RunTimeLambdaProxyClassInfo::EQUALS> {}; 179 180 #endif // SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP