1 /* 2 * Copyright (c) 2015, 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_CLASSLISTPARSER_HPP 26 #define SHARE_CDS_CLASSLISTPARSER_HPP 27 28 #include "utilities/exceptions.hpp" 29 #include "utilities/globalDefinitions.hpp" 30 #include "utilities/growableArray.hpp" 31 #include "utilities/istream.hpp" 32 #include "utilities/resizeableResourceHash.hpp" 33 34 class constantPoolHandle; 35 class Thread; 36 37 class CDSIndyInfo { 38 GrowableArray<const char*>* _items; 39 public: 40 CDSIndyInfo() : _items(nullptr) {} 41 void add_item(const char* item) { 42 if (_items == nullptr) { 43 _items = new GrowableArray<const char*>(9); 44 } 45 assert(_items != nullptr, "sanity"); 46 _items->append(item); 47 } 48 void add_ref_kind(int ref_kind) { 49 switch (ref_kind) { 50 case JVM_REF_getField : _items->append("REF_getField"); break; 51 case JVM_REF_getStatic : _items->append("REF_getStatic"); break; 52 case JVM_REF_putField : _items->append("REF_putField"); break; 53 case JVM_REF_putStatic : _items->append("REF_putStatic"); break; 54 case JVM_REF_invokeVirtual : _items->append("REF_invokeVirtual"); break; 55 case JVM_REF_invokeStatic : _items->append("REF_invokeStatic"); break; 56 case JVM_REF_invokeSpecial : _items->append("REF_invokeSpecial"); break; 57 case JVM_REF_newInvokeSpecial : _items->append("REF_newInvokeSpecial"); break; 58 case JVM_REF_invokeInterface : _items->append("REF_invokeInterface"); break; 59 default : ShouldNotReachHere(); 60 } 61 } 62 GrowableArray<const char*>* items() { 63 return _items; 64 } 65 }; 66 67 class ClassListParser : public StackObj { 68 static const char* CONSTANT_POOL_TAG; 69 static const char* LAMBDA_FORM_TAG; 70 static const char* LAMBDA_PROXY_TAG; 71 72 public: 73 enum ParseMode { 74 _parse_all, 75 _parse_lambda_forms_invokers_only, 76 }; 77 78 private: 79 // Must be C_HEAP allocated -- we don't want nested resource allocations. 80 typedef ResizeableResourceHashtable<int, InstanceKlass*, 81 AnyObj::C_HEAP, mtClassShared> ID2KlassTable; 82 83 enum { 84 _unspecified = -999, 85 }; 86 87 // Use a small initial size in debug build to test resizing logic 88 static const int INITIAL_TABLE_SIZE = DEBUG_ONLY(17) NOT_DEBUG(1987); 89 static const int MAX_TABLE_SIZE = 61333; 90 static volatile Thread* _parsing_thread; // the thread that created _instance 91 static ClassListParser* _instance; // the singleton. 92 const char* _classlist_file; 93 94 ID2KlassTable _id2klass_table; 95 96 FileInput _file_input; 97 inputStream _input_stream; 98 char* _line; // The buffer that holds the current line. Some characters in 99 // the buffer may be overwritten by '\0' during parsing. 100 int _line_len; // Original length of the input line. 101 const char* _class_name; 102 GrowableArray<const char*>* _indy_items; // items related to invoke dynamic for archiving lambda proxy classes 103 int _id; 104 int _super; 105 GrowableArray<int>* _interfaces; 106 bool _interfaces_specified; 107 const char* _source; 108 ParseMode _parse_mode; 109 110 bool parse_int_option(const char* option_name, int* value); 111 bool parse_uint_option(const char* option_name, int* value); 112 InstanceKlass* load_class_from_source(Symbol* class_name, TRAPS); 113 ID2KlassTable* id2klass_table() { 114 return &_id2klass_table; 115 } 116 InstanceKlass* lookup_class_by_id(int id); 117 void print_specified_interfaces(); 118 void print_actual_interfaces(InstanceKlass *ik); 119 bool is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS); 120 121 InstanceKlass* find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop); 122 InstanceKlass* find_builtin_class(JavaThread* current, const char* class_name); 123 124 void resolve_indy(JavaThread* current, Symbol* class_name_symbol); 125 void resolve_indy_impl(Symbol* class_name_symbol, TRAPS); 126 void clean_up_input_line(); 127 void read_class_name_and_attributes(); 128 void parse_class_name_and_attributes(TRAPS); 129 Klass* load_current_class(Symbol* class_name_symbol, TRAPS); 130 void parse_constant_pool_tag(); 131 132 size_t lineno() { return _input_stream.lineno(); } 133 FILE* do_open(const char* file); 134 ClassListParser(const char* file, ParseMode _parse_mode); 135 ~ClassListParser(); 136 void print_diagnostic_info(outputStream* st, const char* msg, va_list ap) ATTRIBUTE_PRINTF(3, 0); 137 void print_diagnostic_info(outputStream* st, const char* msg, ...) ATTRIBUTE_PRINTF(3, 0); 138 void constant_pool_resolution_warning(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 139 void error(const char* msg, ...) ATTRIBUTE_PRINTF(2, 0); 140 141 public: 142 static void parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) { 143 ClassListParser parser(classlist_path, parse_mode); 144 parser.parse(THREAD); 145 } 146 147 static bool is_parsing_thread(); 148 static ClassListParser* instance() { 149 assert(is_parsing_thread(), "call this only in the thread that created ClassListParsing::_instance"); 150 assert(_instance != nullptr, "must be"); 151 return _instance; 152 } 153 static const char* lambda_proxy_tag() { 154 return LAMBDA_PROXY_TAG; 155 } 156 static const char* lambda_form_tag() { 157 return LAMBDA_FORM_TAG; 158 } 159 160 void parse(TRAPS); 161 void split_tokens_by_whitespace(int offset, GrowableArray<const char*>* items); 162 int split_at_tag_from_line(); 163 void parse_at_tags(TRAPS); 164 char* _token; 165 void parse_int(int* value); 166 void parse_uint(int* value); 167 bool try_parse_uint(int* value); 168 bool skip_token(const char* option_name); 169 void skip_whitespaces(); 170 void skip_non_whitespaces(); 171 172 bool parse_lambda_forms_invokers_only() { 173 return _parse_mode == _parse_lambda_forms_invokers_only; 174 } 175 bool is_id_specified() { 176 return _id != _unspecified; 177 } 178 bool is_super_specified() { 179 return _super != _unspecified; 180 } 181 bool are_interfaces_specified() { 182 return _interfaces->length() > 0; 183 } 184 int id() { 185 assert(is_id_specified(), "do not query unspecified id"); 186 return _id; 187 } 188 int super() { 189 assert(is_super_specified(), "do not query unspecified super"); 190 return _super; 191 } 192 void check_already_loaded(const char* which, int id) { 193 if (!id2klass_table()->contains(id)) { 194 error("%s id %d is not yet loaded", which, id); 195 } 196 } 197 void check_class_name(const char* class_name); 198 199 const char* current_class_name() { 200 return _class_name; 201 } 202 203 bool is_loading_from_source(); 204 205 // Look up the super or interface of the current class being loaded 206 // (in this->load_current_class()). 207 InstanceKlass* lookup_super_for_current_class(Symbol* super_name); 208 InstanceKlass* lookup_interface_for_current_class(Symbol* interface_name); 209 210 static void populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS); 211 }; 212 #endif // SHARE_CDS_CLASSLISTPARSER_HPP