1.1 --- a/src/share/vm/classfile/classFileParser.cpp Fri Dec 03 12:14:33 2010 -0800 1.2 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Dec 03 15:53:57 2010 -0800 1.3 @@ -99,12 +99,6 @@ 1.4 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; 1.5 int names_count = 0; 1.6 1.7 - // Side buffer for operands of variable-sized (InvokeDynamic) entries. 1.8 - GrowableArray<int>* operands = NULL; 1.9 -#ifdef ASSERT 1.10 - GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); 1.11 -#endif 1.12 - 1.13 // parsing Index 0 is unused 1.14 for (int index = 1; index < length; index++) { 1.15 // Each of the following case guarantees one more byte in the stream 1.16 @@ -184,36 +178,20 @@ 1.17 "Class file version does not support constant tag %u in class file %s"), 1.18 tag, CHECK); 1.19 } 1.20 - if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { 1.21 - classfile_parse_error( 1.22 + cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags 1.23 + u2 bootstrap_specifier_index = cfs->get_u2_fast(); 1.24 + u2 name_and_type_index = cfs->get_u2_fast(); 1.25 + if (tag == JVM_CONSTANT_InvokeDynamicTrans) { 1.26 + if (!AllowTransitionalJSR292) 1.27 + classfile_parse_error( 1.28 "This JVM does not support transitional InvokeDynamic tag %u in class file %s", 1.29 tag, CHECK); 1.30 + cp->invoke_dynamic_trans_at_put(index, bootstrap_specifier_index, name_and_type_index); 1.31 + break; 1.32 } 1.33 - bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); 1.34 - cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags 1.35 - u2 bootstrap_method_index = cfs->get_u2_fast(); 1.36 - u2 name_and_type_index = cfs->get_u2_fast(); 1.37 - int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); 1.38 - cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags 1.39 - int argv_offset = constantPoolOopDesc::_indy_argv_offset; 1.40 - int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... 1.41 - int op_base = start_operand_group(operands, op_count, CHECK); 1.42 - assert(argv_offset == 3, "else adjust next 3 assignments"); 1.43 - operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); 1.44 - operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); 1.45 - operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); 1.46 - for (int arg_i = 0; arg_i < argument_count; arg_i++) { 1.47 - int arg = cfs->get_u2_fast(); 1.48 - operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); 1.49 - } 1.50 - cp->invoke_dynamic_at_put(index, op_base, op_count); 1.51 -#ifdef ASSERT 1.52 - // Record the steps just taken for later checking. 1.53 - indy_instructions->append(index); 1.54 - indy_instructions->append(bootstrap_method_index); 1.55 - indy_instructions->append(name_and_type_index); 1.56 - indy_instructions->append(argument_count); 1.57 -#endif //ASSERT 1.58 + if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) 1.59 + _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later 1.60 + cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index); 1.61 } 1.62 break; 1.63 case JVM_CONSTANT_Integer : 1.64 @@ -316,23 +294,6 @@ 1.65 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); 1.66 } 1.67 1.68 - if (operands != NULL && operands->length() > 0) { 1.69 - store_operand_array(operands, cp, CHECK); 1.70 - } 1.71 -#ifdef ASSERT 1.72 - // Re-assert the indy structures, now that assertion checking can work. 1.73 - for (int indy_i = 0; indy_i < indy_instructions->length(); ) { 1.74 - int index = indy_instructions->at(indy_i++); 1.75 - int bootstrap_method_index = indy_instructions->at(indy_i++); 1.76 - int name_and_type_index = indy_instructions->at(indy_i++); 1.77 - int argument_count = indy_instructions->at(indy_i++); 1.78 - assert(cp->check_invoke_dynamic_at(index, 1.79 - bootstrap_method_index, name_and_type_index, 1.80 - argument_count), 1.81 - "indy structure is OK"); 1.82 - } 1.83 -#endif //ASSERT 1.84 - 1.85 // Copy _current pointer of local copy back to stream(). 1.86 #ifdef ASSERT 1.87 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); 1.88 @@ -340,41 +301,6 @@ 1.89 cfs0->set_current(cfs1.current()); 1.90 } 1.91 1.92 -int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { 1.93 - if (operands == NULL) { 1.94 - operands = new GrowableArray<int>(THREAD, 100); 1.95 - int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.96 - while (operands->length() <= fillp_offset) 1.97 - operands->append(0); // force op_base > 0, for an error check 1.98 - DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); 1.99 - } 1.100 - int cnt_pos = operands->append(op_count); 1.101 - int arg_pos = operands->length(); 1.102 - operands->at_grow(arg_pos + op_count - 1); // grow to include the operands 1.103 - assert(operands->length() == arg_pos + op_count, ""); 1.104 - int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; 1.105 - return op_base; 1.106 -} 1.107 - 1.108 -void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { 1.109 - // Collect the buffer of operands from variable-sized entries into a permanent array. 1.110 - int arraylen = operands->length(); 1.111 - int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.112 - assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); 1.113 - operands->at_put(fillp_offset, arraylen); 1.114 - cp->multi_operand_buffer_grow(arraylen, CHECK); 1.115 - typeArrayOop operands_oop = cp->operands(); 1.116 - assert(operands_oop->length() == arraylen, ""); 1.117 - for (int i = 0; i < arraylen; i++) { 1.118 - operands_oop->int_at_put(i, operands->at(i)); 1.119 - } 1.120 - cp->set_operands(operands_oop); 1.121 - // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, 1.122 - // when constant pools need to be merged. Make sure it is sane now. 1.123 - assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); 1.124 -} 1.125 - 1.126 - 1.127 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } 1.128 1.129 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { 1.130 @@ -401,7 +327,8 @@ 1.131 1.132 // first verification pass - validate cross references and fixup class and string constants 1.133 for (index = 1; index < length; index++) { // Index 0 is unused 1.134 - switch (cp->tag_at(index).value()) { 1.135 + jbyte tag = cp->tag_at(index).value(); 1.136 + switch (tag) { 1.137 case JVM_CONSTANT_Class : 1.138 ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present 1.139 break; 1.140 @@ -543,35 +470,23 @@ 1.141 } 1.142 break; 1.143 case JVM_CONSTANT_InvokeDynamicTrans : 1.144 - ShouldNotReachHere(); // this tag does not appear in the heap 1.145 case JVM_CONSTANT_InvokeDynamic : 1.146 { 1.147 - int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); 1.148 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); 1.149 - check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) 1.150 - || 1.151 - (valid_cp_range(bootstrap_method_ref_index, length) && 1.152 - (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), 1.153 - "Invalid constant pool index %u in class file %s", 1.154 - bootstrap_method_ref_index, 1.155 - CHECK_(nullHandle)); 1.156 check_property(valid_cp_range(name_and_type_ref_index, length) && 1.157 cp->tag_at(name_and_type_ref_index).is_name_and_type(), 1.158 "Invalid constant pool index %u in class file %s", 1.159 name_and_type_ref_index, 1.160 CHECK_(nullHandle)); 1.161 - int argc = cp->invoke_dynamic_argument_count_at(index); 1.162 - for (int arg_i = 0; arg_i < argc; arg_i++) { 1.163 - int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); 1.164 - check_property(valid_cp_range(arg, length) && 1.165 - cp->tag_at(arg).is_loadable_constant() || 1.166 - // temporary early forms of string and class: 1.167 - cp->tag_at(arg).is_klass_index() || 1.168 - cp->tag_at(arg).is_string_index(), 1.169 + if (tag == JVM_CONSTANT_InvokeDynamicTrans) { 1.170 + int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); 1.171 + check_property(valid_cp_range(bootstrap_method_ref_index, length) && 1.172 + cp->tag_at(bootstrap_method_ref_index).is_method_handle(), 1.173 "Invalid constant pool index %u in class file %s", 1.174 - arg, 1.175 + bootstrap_method_ref_index, 1.176 CHECK_(nullHandle)); 1.177 } 1.178 + // bootstrap specifier index must be checked later, when BootstrapMethods attr is available 1.179 break; 1.180 } 1.181 default: 1.182 @@ -2429,6 +2344,76 @@ 1.183 k->set_generic_signature(cp->symbol_at(signature_index)); 1.184 } 1.185 1.186 +void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, 1.187 + u4 attribute_byte_length, TRAPS) { 1.188 + ClassFileStream* cfs = stream(); 1.189 + u1* current_start = cfs->current(); 1.190 + 1.191 + cfs->guarantee_more(2, CHECK); // length 1.192 + int attribute_array_length = cfs->get_u2_fast(); 1.193 + 1.194 + guarantee_property(_max_bootstrap_specifier_index < attribute_array_length, 1.195 + "Short length on BootstrapMethods in class file %s", 1.196 + CHECK); 1.197 + 1.198 + // The attribute contains a counted array of counted tuples of shorts, 1.199 + // represending bootstrap specifiers: 1.200 + // length*{bootstrap_method_index, argument_count*{argument_index}} 1.201 + int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2); 1.202 + // operand_count = number of shorts in attr, except for leading length 1.203 + 1.204 + // The attribute is copied into a short[] array. 1.205 + // The array begins with a series of short[2] pairs, one for each tuple. 1.206 + int index_size = (attribute_array_length * 2); 1.207 + 1.208 + typeArrayOop operands_oop = oopFactory::new_permanent_intArray(index_size + operand_count, CHECK); 1.209 + typeArrayHandle operands(THREAD, operands_oop); 1.210 + operands_oop = NULL; // tidy 1.211 + 1.212 + int operand_fill_index = index_size; 1.213 + int cp_size = cp->length(); 1.214 + 1.215 + for (int n = 0; n < attribute_array_length; n++) { 1.216 + // Store a 32-bit offset into the header of the operand array. 1.217 + assert(constantPoolOopDesc::operand_offset_at(operands(), n) == 0, ""); 1.218 + constantPoolOopDesc::operand_offset_at_put(operands(), n, operand_fill_index); 1.219 + 1.220 + // Read a bootstrap specifier. 1.221 + cfs->guarantee_more(sizeof(u2) * 2, CHECK); // bsm, argc 1.222 + u2 bootstrap_method_index = cfs->get_u2_fast(); 1.223 + u2 argument_count = cfs->get_u2_fast(); 1.224 + check_property( 1.225 + valid_cp_range(bootstrap_method_index, cp_size) && 1.226 + cp->tag_at(bootstrap_method_index).is_method_handle(), 1.227 + "bootstrap_method_index %u has bad constant type in class file %s", 1.228 + CHECK); 1.229 + operands->short_at_put(operand_fill_index++, bootstrap_method_index); 1.230 + operands->short_at_put(operand_fill_index++, argument_count); 1.231 + 1.232 + cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc] 1.233 + for (int j = 0; j < argument_count; j++) { 1.234 + u2 arg_index = cfs->get_u2_fast(); 1.235 + check_property( 1.236 + valid_cp_range(arg_index, cp_size) && 1.237 + cp->tag_at(arg_index).is_loadable_constant(), 1.238 + "argument_index %u has bad constant type in class file %s", 1.239 + CHECK); 1.240 + operands->short_at_put(operand_fill_index++, arg_index); 1.241 + } 1.242 + } 1.243 + 1.244 + assert(operand_fill_index == operands()->length(), "exact fill"); 1.245 + assert(constantPoolOopDesc::operand_array_length(operands()) == attribute_array_length, "correct decode"); 1.246 + 1.247 + u1* current_end = cfs->current(); 1.248 + guarantee_property(current_end == current_start + attribute_byte_length, 1.249 + "Bad length on BootstrapMethods in class file %s", 1.250 + CHECK); 1.251 + 1.252 + cp->set_operands(operands()); 1.253 +} 1.254 + 1.255 + 1.256 void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { 1.257 ClassFileStream* cfs = stream(); 1.258 // Set inner classes attribute to default sentinel 1.259 @@ -2438,6 +2423,7 @@ 1.260 bool parsed_sourcefile_attribute = false; 1.261 bool parsed_innerclasses_attribute = false; 1.262 bool parsed_enclosingmethod_attribute = false; 1.263 + bool parsed_bootstrap_methods_attribute = false; 1.264 u1* runtime_visible_annotations = NULL; 1.265 int runtime_visible_annotations_length = 0; 1.266 u1* runtime_invisible_annotations = NULL; 1.267 @@ -2536,6 +2522,12 @@ 1.268 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); 1.269 } 1.270 k->set_enclosing_method_indices(class_index, method_index); 1.271 + } else if (tag == vmSymbols::tag_bootstrap_methods() && 1.272 + _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { 1.273 + if (parsed_bootstrap_methods_attribute) 1.274 + classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); 1.275 + parsed_bootstrap_methods_attribute = true; 1.276 + parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK); 1.277 } else { 1.278 // Unknown attribute 1.279 cfs->skip_u1(attribute_length, CHECK); 1.280 @@ -2551,6 +2543,11 @@ 1.281 runtime_invisible_annotations_length, 1.282 CHECK); 1.283 k->set_class_annotations(annotations()); 1.284 + 1.285 + if (_max_bootstrap_specifier_index >= 0) { 1.286 + guarantee_property(parsed_bootstrap_methods_attribute, 1.287 + "Missing BootstrapMethods attribute in class file %s", CHECK); 1.288 + } 1.289 } 1.290 1.291 1.292 @@ -2868,6 +2865,7 @@ 1.293 PerfClassTraceTime::PARSE_CLASS); 1.294 1.295 _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; 1.296 + _max_bootstrap_specifier_index = -1; 1.297 1.298 if (JvmtiExport::should_post_class_file_load_hook()) { 1.299 unsigned char* ptr = cfs->buffer();