1.1 --- a/src/share/vm/classfile/classFileParser.cpp Thu Nov 04 16:17:54 2010 -0700 1.2 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Nov 08 14:33:48 2010 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -73,6 +73,12 @@ 1.11 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; 1.12 int names_count = 0; 1.13 1.14 + // Side buffer for operands of variable-sized (InvokeDynamic) entries. 1.15 + GrowableArray<int>* operands = NULL; 1.16 +#ifdef ASSERT 1.17 + GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); 1.18 +#endif 1.19 + 1.20 // parsing Index 0 is unused 1.21 for (int index = 1; index < length; index++) { 1.22 // Each of the following case guarantees one more byte in the stream 1.23 @@ -141,6 +147,7 @@ 1.24 ShouldNotReachHere(); 1.25 } 1.26 break; 1.27 + case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles 1.28 case JVM_CONSTANT_InvokeDynamic : 1.29 { 1.30 if (!EnableInvokeDynamic || 1.31 @@ -151,10 +158,36 @@ 1.32 "Class file version does not support constant tag %u in class file %s"), 1.33 tag, CHECK); 1.34 } 1.35 - cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags 1.36 + if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { 1.37 + classfile_parse_error( 1.38 + "This JVM does not support transitional InvokeDynamic tag %u in class file %s", 1.39 + tag, CHECK); 1.40 + } 1.41 + bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); 1.42 + cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags 1.43 u2 bootstrap_method_index = cfs->get_u2_fast(); 1.44 u2 name_and_type_index = cfs->get_u2_fast(); 1.45 - cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); 1.46 + int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); 1.47 + cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags 1.48 + int argv_offset = constantPoolOopDesc::_indy_argv_offset; 1.49 + int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... 1.50 + int op_base = start_operand_group(operands, op_count, CHECK); 1.51 + assert(argv_offset == 3, "else adjust next 3 assignments"); 1.52 + operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); 1.53 + operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); 1.54 + operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); 1.55 + for (int arg_i = 0; arg_i < argument_count; arg_i++) { 1.56 + int arg = cfs->get_u2_fast(); 1.57 + operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); 1.58 + } 1.59 + cp->invoke_dynamic_at_put(index, op_base, op_count); 1.60 +#ifdef ASSERT 1.61 + // Record the steps just taken for later checking. 1.62 + indy_instructions->append(index); 1.63 + indy_instructions->append(bootstrap_method_index); 1.64 + indy_instructions->append(name_and_type_index); 1.65 + indy_instructions->append(argument_count); 1.66 +#endif //ASSERT 1.67 } 1.68 break; 1.69 case JVM_CONSTANT_Integer : 1.70 @@ -257,6 +290,23 @@ 1.71 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); 1.72 } 1.73 1.74 + if (operands != NULL && operands->length() > 0) { 1.75 + store_operand_array(operands, cp, CHECK); 1.76 + } 1.77 +#ifdef ASSERT 1.78 + // Re-assert the indy structures, now that assertion checking can work. 1.79 + for (int indy_i = 0; indy_i < indy_instructions->length(); ) { 1.80 + int index = indy_instructions->at(indy_i++); 1.81 + int bootstrap_method_index = indy_instructions->at(indy_i++); 1.82 + int name_and_type_index = indy_instructions->at(indy_i++); 1.83 + int argument_count = indy_instructions->at(indy_i++); 1.84 + assert(cp->check_invoke_dynamic_at(index, 1.85 + bootstrap_method_index, name_and_type_index, 1.86 + argument_count), 1.87 + "indy structure is OK"); 1.88 + } 1.89 +#endif //ASSERT 1.90 + 1.91 // Copy _current pointer of local copy back to stream(). 1.92 #ifdef ASSERT 1.93 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); 1.94 @@ -264,6 +314,41 @@ 1.95 cfs0->set_current(cfs1.current()); 1.96 } 1.97 1.98 +int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { 1.99 + if (operands == NULL) { 1.100 + operands = new GrowableArray<int>(THREAD, 100); 1.101 + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.102 + while (operands->length() <= fillp_offset) 1.103 + operands->append(0); // force op_base > 0, for an error check 1.104 + DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); 1.105 + } 1.106 + int cnt_pos = operands->append(op_count); 1.107 + int arg_pos = operands->length(); 1.108 + operands->at_grow(arg_pos + op_count - 1); // grow to include the operands 1.109 + assert(operands->length() == arg_pos + op_count, ""); 1.110 + int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; 1.111 + return op_base; 1.112 +} 1.113 + 1.114 +void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { 1.115 + // Collect the buffer of operands from variable-sized entries into a permanent array. 1.116 + int arraylen = operands->length(); 1.117 + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; 1.118 + assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); 1.119 + operands->at_put(fillp_offset, arraylen); 1.120 + cp->multi_operand_buffer_grow(arraylen, CHECK); 1.121 + typeArrayOop operands_oop = cp->operands(); 1.122 + assert(operands_oop->length() == arraylen, ""); 1.123 + for (int i = 0; i < arraylen; i++) { 1.124 + operands_oop->int_at_put(i, operands->at(i)); 1.125 + } 1.126 + cp->set_operands(operands_oop); 1.127 + // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, 1.128 + // when constant pools need to be merged. Make sure it is sane now. 1.129 + assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); 1.130 +} 1.131 + 1.132 + 1.133 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } 1.134 1.135 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { 1.136 @@ -431,6 +516,8 @@ 1.137 ref_index, CHECK_(nullHandle)); 1.138 } 1.139 break; 1.140 + case JVM_CONSTANT_InvokeDynamicTrans : 1.141 + ShouldNotReachHere(); // this tag does not appear in the heap 1.142 case JVM_CONSTANT_InvokeDynamic : 1.143 { 1.144 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); 1.145 @@ -438,7 +525,7 @@ 1.146 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) 1.147 || 1.148 (valid_cp_range(bootstrap_method_ref_index, length) && 1.149 - cp->tag_at(bootstrap_method_ref_index).is_method_handle()), 1.150 + (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), 1.151 "Invalid constant pool index %u in class file %s", 1.152 bootstrap_method_ref_index, 1.153 CHECK_(nullHandle)); 1.154 @@ -447,6 +534,18 @@ 1.155 "Invalid constant pool index %u in class file %s", 1.156 name_and_type_ref_index, 1.157 CHECK_(nullHandle)); 1.158 + int argc = cp->invoke_dynamic_argument_count_at(index); 1.159 + for (int arg_i = 0; arg_i < argc; arg_i++) { 1.160 + int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); 1.161 + check_property(valid_cp_range(arg, length) && 1.162 + cp->tag_at(arg).is_loadable_constant() || 1.163 + // temporary early forms of string and class: 1.164 + cp->tag_at(arg).is_klass_index() || 1.165 + cp->tag_at(arg).is_string_index(), 1.166 + "Invalid constant pool index %u in class file %s", 1.167 + arg, 1.168 + CHECK_(nullHandle)); 1.169 + } 1.170 break; 1.171 } 1.172 default: 1.173 @@ -2516,18 +2615,6 @@ 1.174 // field. If it is not present, artifically create a field for it. 1.175 // This allows this VM to run on early JDK where the field is not 1.176 // present. 1.177 - 1.178 - // 1.179 - // Increment fac.nonstatic_oop_count so that the start of the 1.180 - // next type of non-static oops leaves room for the fake oop. 1.181 - // Do not increment next_nonstatic_oop_offset so that the 1.182 - // fake oop is place after the java.lang.ref.Reference oop 1.183 - // fields. 1.184 - // 1.185 - // Check the fields in java.lang.ref.Reference for the "discovered" 1.186 - // field. If it is not present, artifically create a field for it. 1.187 - // This allows this VM to run on early JDK where the field is not 1.188 - // present. 1.189 int reference_sig_index = 0; 1.190 int reference_name_index = 0; 1.191 int reference_index = 0; 1.192 @@ -2663,7 +2750,7 @@ 1.193 // Force MethodHandle.vmentry to be an unmanaged pointer. 1.194 // There is no way for a classfile to express this, so we must help it. 1.195 void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, 1.196 - typeArrayHandle* fields_ptr, 1.197 + typeArrayHandle fields, 1.198 FieldAllocationCount *fac_ptr, 1.199 TRAPS) { 1.200 // Add fake fields for java.dyn.MethodHandle instances 1.201 @@ -2687,41 +2774,45 @@ 1.202 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), 1.203 "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); 1.204 1.205 + // Find vmentry field and change the signature. 1.206 bool found_vmentry = false; 1.207 - 1.208 - const int n = (*fields_ptr)()->length(); 1.209 - for (int i = 0; i < n; i += instanceKlass::next_offset) { 1.210 - int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset); 1.211 - int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset); 1.212 - int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset); 1.213 + for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) { 1.214 + int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); 1.215 + int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); 1.216 + int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); 1.217 symbolOop f_name = cp->symbol_at(name_index); 1.218 symbolOop f_sig = cp->symbol_at(sig_index); 1.219 - if (f_sig == vmSymbols::byte_signature() && 1.220 - f_name == vmSymbols::vmentry_name() && 1.221 - (acc_flags & JVM_ACC_STATIC) == 0) { 1.222 - // Adjust the field type from byte to an unmanaged pointer. 1.223 - assert(fac_ptr->nonstatic_byte_count > 0, ""); 1.224 - fac_ptr->nonstatic_byte_count -= 1; 1.225 - 1.226 - (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); 1.227 - assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); 1.228 - if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; 1.229 - else fac_ptr->nonstatic_word_count += 1; 1.230 - 1.231 - FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset); 1.232 - assert(atype == NONSTATIC_BYTE, ""); 1.233 - FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; 1.234 - (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype); 1.235 - 1.236 - found_vmentry = true; 1.237 - break; 1.238 + 1.239 + if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { 1.240 + if (f_sig == vmSymbols::machine_word_signature()) { 1.241 + // If the signature of vmentry is already changed, we're done. 1.242 + found_vmentry = true; 1.243 + break; 1.244 + } 1.245 + else if (f_sig == vmSymbols::byte_signature()) { 1.246 + // Adjust the field type from byte to an unmanaged pointer. 1.247 + assert(fac_ptr->nonstatic_byte_count > 0, ""); 1.248 + fac_ptr->nonstatic_byte_count -= 1; 1.249 + 1.250 + fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); 1.251 + assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); 1.252 + if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; 1.253 + else fac_ptr->nonstatic_word_count += 1; 1.254 + 1.255 + FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); 1.256 + assert(atype == NONSTATIC_BYTE, ""); 1.257 + FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; 1.258 + fields->ushort_at_put(i + instanceKlass::low_offset, new_atype); 1.259 + 1.260 + found_vmentry = true; 1.261 + break; 1.262 + } 1.263 } 1.264 } 1.265 1.266 if (!found_vmentry) 1.267 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), 1.268 "missing vmentry byte field in java.dyn.MethodHandle"); 1.269 - 1.270 } 1.271 1.272 1.273 @@ -3082,7 +3173,7 @@ 1.274 1.275 // adjust the vmentry field declaration in java.dyn.MethodHandle 1.276 if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { 1.277 - java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle)); 1.278 + java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); 1.279 } 1.280 1.281 // Add a fake "discovered" field if it is not present