1 /*
  2  * Copyright (c) 2021, 2025, 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 
 28 #include "cds/archiveBuilder.hpp"
 29 #include "cds/metaspaceShared.hpp"
 30 #include "classfile/javaClasses.hpp"
 31 #include "memory/metaspaceClosure.hpp"
 32 #include "utilities/growableArray.hpp"
 33 #include "utilities/resourceHash.hpp"
 34 
 35 // This file contains *legacy* optimization for lambdas before JEP 483. May be removed in the future.
 36 //
 37 // The functionalties in this file are used only when CDSConfig::is_dumping_lambdas_in_legacy_mode()
 38 // returns true during the creation of a CDS archive.
 39 //
 40 // With the legacy optimization, generated lambda proxy classes (with names such as
 41 // java.util.ResourceBundle$Control$$Lambda/0x80000001d) are stored inside the CDS archive, accessible
 42 // by LambdaProxyClassDictionary::find_proxy_class(). This saves part of the time for resolving a
 43 // lambda call site (proxy class generation). However, a significant portion of the cost of
 44 // the lambda call site resolution still remains in the production run.
 45 //
 46 // In contrast, with JEP 483, the entire lambda call site (starting from the constant pool entry), is
 47 // resolved in the AOT cache assembly phase. No extra resolution is needed in the production run.
 48 
 49 class InstanceKlass;
 50 class Method;
 51 class MetaspaceClosure;
 52 class Symbol;
 53 class outputStream;
 54 
 55 class LambdaProxyClassKey {
 56   InstanceKlass* _caller_ik;
 57   Symbol*        _invoked_name;
 58   Symbol*        _invoked_type;
 59   Symbol*        _method_type;
 60   Method*        _member_method;
 61   Symbol*        _instantiated_method_type;
 62 
 63 public:
 64   LambdaProxyClassKey(InstanceKlass* caller_ik,
 65                       Symbol*        invoked_name,
 66                       Symbol*        invoked_type,
 67                       Symbol*        method_type,
 68                       Method*        member_method,
 69                       Symbol*        instantiated_method_type) :
 70     _caller_ik(caller_ik),
 71     _invoked_name(invoked_name),
 72     _invoked_type(invoked_type),
 73     _method_type(method_type),
 74     _member_method(member_method),
 75     _instantiated_method_type(instantiated_method_type) {}
 76 
 77   void metaspace_pointers_do(MetaspaceClosure* it) {
 78     it->push(&_caller_ik);
 79     it->push(&_invoked_name);
 80     it->push(&_invoked_type);
 81     it->push(&_method_type);
 82     it->push(&_member_method);
 83     it->push(&_instantiated_method_type);
 84   }
 85 
 86   bool equals(LambdaProxyClassKey const& other) const {
 87     return _caller_ik == other._caller_ik &&
 88            _invoked_name == other._invoked_name &&
 89            _invoked_type == other._invoked_type &&
 90            _method_type == other._method_type &&
 91            _member_method == other._member_method &&
 92            _instantiated_method_type == other._instantiated_method_type;
 93   }
 94 
 95   unsigned int hash() const;
 96 
 97   static unsigned int dumptime_hash(Symbol* sym)  {
 98     if (sym == nullptr) {
 99       // _invoked_name maybe null
100       return 0;
101     }
102     return java_lang_String::hash_code((const jbyte*)sym->bytes(), sym->utf8_length());
103   }
104 
105   unsigned int dumptime_hash() const {
106     return dumptime_hash(_caller_ik->name()) +
107            dumptime_hash(_invoked_name) +
108            dumptime_hash(_invoked_type) +
109            dumptime_hash(_method_type) +
110            dumptime_hash(_instantiated_method_type);
111   }
112 
113   static inline unsigned int DUMPTIME_HASH(LambdaProxyClassKey const& key) {
114     return (key.dumptime_hash());
115   }
116 
117   static inline bool DUMPTIME_EQUALS(
118       LambdaProxyClassKey const& k1, LambdaProxyClassKey const& k2) {
119     return (k1.equals(k2));
120   }
121 
122   InstanceKlass* caller_ik()         const { return _caller_ik; }
123   Symbol* invoked_name()             const { return _invoked_name; }
124   Symbol* invoked_type()             const { return _invoked_type; }
125   Symbol* method_type()              const { return _method_type; }
126   Method* member_method()            const { return _member_method; }
127   Symbol* instantiated_method_type() const { return _instantiated_method_type; }
128 
129 #ifndef PRODUCT
130   void print_on(outputStream* st) const;
131 #endif
132 };
133 
134 class RunTimeLambdaProxyClassKey {
135   u4 _caller_ik;
136   u4 _invoked_name;
137   u4 _invoked_type;
138   u4 _method_type;
139   u4 _member_method;
140   u4 _instantiated_method_type;
141 
142   RunTimeLambdaProxyClassKey(u4 caller_ik,
143                              u4 invoked_name,
144                              u4 invoked_type,
145                              u4 method_type,
146                              u4 member_method,
147                              u4 instantiated_method_type) :
148     _caller_ik(caller_ik),
149     _invoked_name(invoked_name),
150     _invoked_type(invoked_type),
151     _method_type(method_type),
152     _member_method(member_method),
153     _instantiated_method_type(instantiated_method_type) {}
154 
155 public:
156   static RunTimeLambdaProxyClassKey init_for_dumptime(LambdaProxyClassKey& key) {
157     assert(ArchiveBuilder::is_active(), "sanity");
158     ArchiveBuilder* b = ArchiveBuilder::current();
159 
160     u4 caller_ik                = b->any_to_offset_u4(key.caller_ik());
161     u4 invoked_name             = b->any_to_offset_u4(key.invoked_name());
162     u4 invoked_type             = b->any_to_offset_u4(key.invoked_type());
163     u4 method_type              = b->any_to_offset_u4(key.method_type());
164     u4 member_method            = b->any_or_null_to_offset_u4(key.member_method()); // could be null
165     u4 instantiated_method_type = b->any_to_offset_u4(key.instantiated_method_type());
166 
167     return RunTimeLambdaProxyClassKey(caller_ik, invoked_name, invoked_type, method_type,
168                                       member_method, instantiated_method_type);
169   }
170 
171   static RunTimeLambdaProxyClassKey init_for_runtime(InstanceKlass* caller_ik,
172                                                      Symbol*        invoked_name,
173                                                      Symbol*        invoked_type,
174                                                      Symbol*        method_type,
175                                                      Method*        member_method,
176                                                      Symbol*        instantiated_method_type) {
177     // All parameters must be in shared space, or else you'd get an assert in
178     // ArchiveUtils::to_offset().
179     return RunTimeLambdaProxyClassKey(ArchiveUtils::archived_address_to_offset(caller_ik),
180                                       ArchiveUtils::archived_address_to_offset(invoked_name),
181                                       ArchiveUtils::archived_address_to_offset(invoked_type),
182                                       ArchiveUtils::archived_address_to_offset(method_type),
183                                       ArchiveUtils::archived_address_or_null_to_offset(member_method), // could be null
184                                       ArchiveUtils::archived_address_to_offset(instantiated_method_type));
185   }
186 
187   unsigned int hash() const;
188   bool equals(RunTimeLambdaProxyClassKey const& other) const {
189     return _caller_ik == other._caller_ik &&
190            _invoked_name == other._invoked_name &&
191            _invoked_type == other._invoked_type &&
192            _method_type == other._method_type &&
193            _member_method == other._member_method &&
194            _instantiated_method_type == other._instantiated_method_type;
195   }
196 
197 #ifndef PRODUCT
198   void print_on(outputStream* st) const;
199 #endif
200 };
201 
202 class DumpTimeLambdaProxyClassInfo {
203 public:
204   GrowableArray<InstanceKlass*>* _proxy_klasses;
205   DumpTimeLambdaProxyClassInfo() : _proxy_klasses(nullptr) {}
206   DumpTimeLambdaProxyClassInfo& operator=(const DumpTimeLambdaProxyClassInfo&) = delete;
207   ~DumpTimeLambdaProxyClassInfo();
208 
209   void add_proxy_klass(InstanceKlass* proxy_klass) {
210     if (_proxy_klasses == nullptr) {
211       _proxy_klasses = new (mtClassShared) GrowableArray<InstanceKlass*>(5, mtClassShared);
212     }
213     assert(_proxy_klasses != nullptr, "sanity");
214     _proxy_klasses->append(proxy_klass);
215   }
216 
217   void metaspace_pointers_do(MetaspaceClosure* it) {
218     for (int i=0; i<_proxy_klasses->length(); i++) {
219       it->push(_proxy_klasses->adr_at(i));
220     }
221   }
222 };
223 
224 class RunTimeLambdaProxyClassInfo {
225   RunTimeLambdaProxyClassKey _key;
226   InstanceKlass* _proxy_klass_head;
227 public:
228   RunTimeLambdaProxyClassInfo(RunTimeLambdaProxyClassKey key, InstanceKlass* proxy_klass_head) :
229     _key(key), _proxy_klass_head(proxy_klass_head) {}
230 
231   InstanceKlass* proxy_klass_head() const { return _proxy_klass_head; }
232 
233   // Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS
234   static inline bool EQUALS(
235        const RunTimeLambdaProxyClassInfo* value, RunTimeLambdaProxyClassKey* key, int len_unused) {
236     return (value->_key.equals(*key));
237   }
238   void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info);
239 
240   unsigned int hash() const {
241     return _key.hash();
242   }
243   RunTimeLambdaProxyClassKey key() const {
244     return _key;
245   }
246 #ifndef PRODUCT
247   void print_on(outputStream* st) const;
248 #endif
249 };
250 
251 class DumpTimeLambdaProxyClassDictionary
252   : public ResourceHashtable<LambdaProxyClassKey,
253                              DumpTimeLambdaProxyClassInfo,
254                              137, // prime number
255                              AnyObj::C_HEAP,
256                              mtClassShared,
257                              LambdaProxyClassKey::DUMPTIME_HASH,
258                              LambdaProxyClassKey::DUMPTIME_EQUALS> {
259 public:
260   DumpTimeLambdaProxyClassDictionary() : _count(0) {}
261   int _count;
262 };
263 
264 // *Legacy* optimization for lambdas before JEP 483. May be removed in the future.
265 class LambdaProxyClassDictionary : public OffsetCompactHashtable<
266   RunTimeLambdaProxyClassKey*,
267   const RunTimeLambdaProxyClassInfo*,
268   RunTimeLambdaProxyClassInfo::EQUALS>
269 {
270 private:
271   class CleanupDumpTimeLambdaProxyClassTable;
272   static DumpTimeLambdaProxyClassDictionary* _dumptime_table;
273   static LambdaProxyClassDictionary _runtime_static_table; // for static CDS archive
274   static LambdaProxyClassDictionary _runtime_dynamic_table; // for dynamic CDS archive
275 
276   static void add_to_dumptime_table(LambdaProxyClassKey& key,
277                                     InstanceKlass* proxy_klass);
278   static InstanceKlass* find_lambda_proxy_class(const RunTimeLambdaProxyClassInfo* info);
279   static InstanceKlass* find_lambda_proxy_class(InstanceKlass* caller_ik,
280                                                 Symbol* invoked_name,
281                                                 Symbol* invoked_type,
282                                                 Symbol* method_type,
283                                                 Method* member_method,
284                                                 Symbol* instantiated_method_type);
285   static InstanceKlass* load_and_init_lambda_proxy_class(InstanceKlass* lambda_ik,
286                                                          InstanceKlass* caller_ik, TRAPS);
287   static void reset_registered_lambda_proxy_class(InstanceKlass* ik);
288   static InstanceKlass* get_shared_nest_host(InstanceKlass* lambda_ik);
289 
290 public:
291   static void dumptime_init();
292   static void dumptime_classes_do(MetaspaceClosure* it);
293   static void add_lambda_proxy_class(InstanceKlass* caller_ik,
294                                      InstanceKlass* lambda_ik,
295                                      Symbol* invoked_name,
296                                      Symbol* invoked_type,
297                                      Symbol* method_type,
298                                      Method* member_method,
299                                      Symbol* instantiated_method_type,
300                                      TRAPS);
301   static bool is_supported_invokedynamic(BootstrapInfo* bsi);
302   static bool is_registered_lambda_proxy_class(InstanceKlass* ik);
303   static InstanceKlass* load_shared_lambda_proxy_class(InstanceKlass* caller_ik,
304                                                        Symbol* invoked_name,
305                                                        Symbol* invoked_type,
306                                                        Symbol* method_type,
307                                                        Method* member_method,
308                                                        Symbol* instantiated_method_type,
309                                                        TRAPS);
310   static void write_dictionary(bool is_static_archive);
311   static void adjust_dumptime_table();
312   static void cleanup_dumptime_table();
313 
314   static void reset_dictionary(bool is_static_archive) {
315     if (is_static_archive) {
316       _runtime_static_table.reset();
317     } else {
318       _runtime_dynamic_table.reset();
319     }
320   }
321 
322   static void serialize(SerializeClosure* soc, bool is_static_archive) {
323     if (is_static_archive) {
324       _runtime_static_table.serialize_header(soc);
325     } else {
326       _runtime_dynamic_table.serialize_header(soc);
327     }
328   }
329 
330   static void print_on(const char* prefix, outputStream* st,
331                        int start_index, bool is_static_archive);
332   static void print_statistics(outputStream* st,  bool is_static_archive);
333 };
334 
335 #endif // SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP