1.1 --- a/src/share/vm/classfile/classFileParser.cpp Sat Oct 30 12:19:07 2010 -0700 1.2 +++ b/src/share/vm/classfile/classFileParser.cpp Sat Oct 30 13:08:23 2010 -0700 1.3 @@ -73,6 +73,12 @@ 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 @@ -141,6 +147,7 @@ 1.17 ShouldNotReachHere(); 1.18 } 1.19 break; 1.20 + case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles 1.21 case JVM_CONSTANT_InvokeDynamic : 1.22 { 1.23 if (!EnableInvokeDynamic || 1.24 @@ -151,10 +158,36 @@ 1.25 "Class file version does not support constant tag %u in class file %s"), 1.26 tag, CHECK); 1.27 } 1.28 - cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags 1.29 + if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { 1.30 + classfile_parse_error( 1.31 + "This JVM does not support transitional InvokeDynamic tag %u in class file %s", 1.32 + tag, CHECK); 1.33 + } 1.34 + bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); 1.35 + cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags 1.36 u2 bootstrap_method_index = cfs->get_u2_fast(); 1.37 u2 name_and_type_index = cfs->get_u2_fast(); 1.38 - cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); 1.39 + int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); 1.40 + cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags 1.41 + int argv_offset = constantPoolOopDesc::_indy_argv_offset; 1.42 + int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... 1.43 + int op_base = start_operand_group(operands, op_count, CHECK); 1.44 + assert(argv_offset == 3, "else adjust next 3 assignments"); 1.45 + operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); 1.46 + operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); 1.47 + operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); 1.48 + for (int arg_i = 0; arg_i < argument_count; arg_i++) { 1.49 + int arg = cfs->get_u2_fast(); 1.50 + operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); 1.51 + } 1.52 + cp->invoke_dynamic_at_put(index, op_base, op_count); 1.53 +#ifdef ASSERT 1.54 + // Record the steps just taken for later checking. 1.55 + indy_instructions->append(index); 1.56 + indy_instructions->append(bootstrap_method_index); 1.57 + indy_instructions->append(name_and_type_index); 1.58 + indy_instructions->append(argument_count); 1.59 +#endif //ASSERT 1.60 } 1.61 break; 1.62 case JVM_CONSTANT_Integer : 1.63 @@ -257,6 +290,23 @@ 1.64 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); 1.65 } 1.66 1.67 + if (operands != NULL && operands->length() > 0) { 1.68 + store_operand_array(operands, cp, CHECK); 1.69 + } 1.70 +#ifdef ASSERT 1.71 + // Re-assert the indy structures, now that assertion checking can work. 1.72 + for (int indy_i = 0; indy_i < indy_instructions->length(); ) { 1.73 + int index = indy_instructions->at(indy_i++); 1.74 + int bootstrap_method_index = indy_instructions->at(indy_i++); 1.75 + int name_and_type_index = indy_instructions->at(indy_i++); 1.76 + int argument_count = indy_instructions->at(indy_i++); 1.77 + assert(cp->check_invoke_dynamic_at(index, 1.78 + bootstrap_method_index, name_and_type_index, 1.79 + argument_count), 1.80 + "indy structure is OK"); 1.81 + } 1.82 +#endif //ASSERT 1.83 + 1.84 // Copy _current pointer of local copy back to stream(). 1.85 #ifdef ASSERT 1.86 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); 1.87 @@ -264,6 +314,41 @@ 1.88 cfs0->set_current(cfs1.current()); 1.89 } 1.90 1.91 +int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { 1.92 + if (operands == NULL) { 1.93 + operands = new GrowableArray<int>(THREAD, 100); 1.94 + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.95 + while (operands->length() <= fillp_offset) 1.96 + operands->append(0); // force op_base > 0, for an error check 1.97 + DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); 1.98 + } 1.99 + int cnt_pos = operands->append(op_count); 1.100 + int arg_pos = operands->length(); 1.101 + operands->at_grow(arg_pos + op_count - 1); // grow to include the operands 1.102 + assert(operands->length() == arg_pos + op_count, ""); 1.103 + int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; 1.104 + return op_base; 1.105 +} 1.106 + 1.107 +void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { 1.108 + // Collect the buffer of operands from variable-sized entries into a permanent array. 1.109 + int arraylen = operands->length(); 1.110 + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.111 + assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); 1.112 + operands->at_put(fillp_offset, arraylen); 1.113 + cp->multi_operand_buffer_grow(arraylen, CHECK); 1.114 + typeArrayOop operands_oop = cp->operands(); 1.115 + assert(operands_oop->length() == arraylen, ""); 1.116 + for (int i = 0; i < arraylen; i++) { 1.117 + operands_oop->int_at_put(i, operands->at(i)); 1.118 + } 1.119 + cp->set_operands(operands_oop); 1.120 + // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, 1.121 + // when constant pools need to be merged. Make sure it is sane now. 1.122 + assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); 1.123 +} 1.124 + 1.125 + 1.126 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } 1.127 1.128 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { 1.129 @@ -431,6 +516,8 @@ 1.130 ref_index, CHECK_(nullHandle)); 1.131 } 1.132 break; 1.133 + case JVM_CONSTANT_InvokeDynamicTrans : 1.134 + ShouldNotReachHere(); // this tag does not appear in the heap 1.135 case JVM_CONSTANT_InvokeDynamic : 1.136 { 1.137 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); 1.138 @@ -438,7 +525,7 @@ 1.139 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) 1.140 || 1.141 (valid_cp_range(bootstrap_method_ref_index, length) && 1.142 - cp->tag_at(bootstrap_method_ref_index).is_method_handle()), 1.143 + (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), 1.144 "Invalid constant pool index %u in class file %s", 1.145 bootstrap_method_ref_index, 1.146 CHECK_(nullHandle)); 1.147 @@ -447,6 +534,18 @@ 1.148 "Invalid constant pool index %u in class file %s", 1.149 name_and_type_ref_index, 1.150 CHECK_(nullHandle)); 1.151 + int argc = cp->invoke_dynamic_argument_count_at(index); 1.152 + for (int arg_i = 0; arg_i < argc; arg_i++) { 1.153 + int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); 1.154 + check_property(valid_cp_range(arg, length) && 1.155 + cp->tag_at(arg).is_loadable_constant() || 1.156 + // temporary early forms of string and class: 1.157 + cp->tag_at(arg).is_klass_index() || 1.158 + cp->tag_at(arg).is_string_index(), 1.159 + "Invalid constant pool index %u in class file %s", 1.160 + arg, 1.161 + CHECK_(nullHandle)); 1.162 + } 1.163 break; 1.164 } 1.165 default: