Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/classFileParser.cpp @ 1913:3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
Summary: Allow CONSTANT_InvokeDynamic nodes to have any number of extra operands.
Reviewed-by: twisti
author | jrose |
---|---|
date | Sat, 30 Oct 2010 13:08:23 -0700 |
parents | d2e35ffae982 |
children | 5caa30ea147b |
comparison
equal
deleted
inserted
replaced
1912:8213b0f5c92d | 1913:3b2dea75431e |
---|---|
71 int lengths[SymbolTable::symbol_alloc_batch_size]; | 71 int lengths[SymbolTable::symbol_alloc_batch_size]; |
72 int indices[SymbolTable::symbol_alloc_batch_size]; | 72 int indices[SymbolTable::symbol_alloc_batch_size]; |
73 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; | 73 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; |
74 int names_count = 0; | 74 int names_count = 0; |
75 | 75 |
76 // Side buffer for operands of variable-sized (InvokeDynamic) entries. | |
77 GrowableArray<int>* operands = NULL; | |
78 #ifdef ASSERT | |
79 GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); | |
80 #endif | |
81 | |
76 // parsing Index 0 is unused | 82 // parsing Index 0 is unused |
77 for (int index = 1; index < length; index++) { | 83 for (int index = 1; index < length; index++) { |
78 // Each of the following case guarantees one more byte in the stream | 84 // Each of the following case guarantees one more byte in the stream |
79 // for the following tag or the access_flags following constant pool, | 85 // for the following tag or the access_flags following constant pool, |
80 // so we don't need bounds-check for reading tag. | 86 // so we don't need bounds-check for reading tag. |
139 cp->method_type_index_at_put(index, signature_index); | 145 cp->method_type_index_at_put(index, signature_index); |
140 } else { | 146 } else { |
141 ShouldNotReachHere(); | 147 ShouldNotReachHere(); |
142 } | 148 } |
143 break; | 149 break; |
150 case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles | |
144 case JVM_CONSTANT_InvokeDynamic : | 151 case JVM_CONSTANT_InvokeDynamic : |
145 { | 152 { |
146 if (!EnableInvokeDynamic || | 153 if (!EnableInvokeDynamic || |
147 _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | 154 _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
148 classfile_parse_error( | 155 classfile_parse_error( |
149 (!EnableInvokeDynamic ? | 156 (!EnableInvokeDynamic ? |
150 "This JVM does not support constant tag %u in class file %s" : | 157 "This JVM does not support constant tag %u in class file %s" : |
151 "Class file version does not support constant tag %u in class file %s"), | 158 "Class file version does not support constant tag %u in class file %s"), |
152 tag, CHECK); | 159 tag, CHECK); |
153 } | 160 } |
154 cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags | 161 if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { |
162 classfile_parse_error( | |
163 "This JVM does not support transitional InvokeDynamic tag %u in class file %s", | |
164 tag, CHECK); | |
165 } | |
166 bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); | |
167 cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags | |
155 u2 bootstrap_method_index = cfs->get_u2_fast(); | 168 u2 bootstrap_method_index = cfs->get_u2_fast(); |
156 u2 name_and_type_index = cfs->get_u2_fast(); | 169 u2 name_and_type_index = cfs->get_u2_fast(); |
157 cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); | 170 int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); |
171 cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags | |
172 int argv_offset = constantPoolOopDesc::_indy_argv_offset; | |
173 int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... | |
174 int op_base = start_operand_group(operands, op_count, CHECK); | |
175 assert(argv_offset == 3, "else adjust next 3 assignments"); | |
176 operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); | |
177 operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); | |
178 operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); | |
179 for (int arg_i = 0; arg_i < argument_count; arg_i++) { | |
180 int arg = cfs->get_u2_fast(); | |
181 operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); | |
182 } | |
183 cp->invoke_dynamic_at_put(index, op_base, op_count); | |
184 #ifdef ASSERT | |
185 // Record the steps just taken for later checking. | |
186 indy_instructions->append(index); | |
187 indy_instructions->append(bootstrap_method_index); | |
188 indy_instructions->append(name_and_type_index); | |
189 indy_instructions->append(argument_count); | |
190 #endif //ASSERT | |
158 } | 191 } |
159 break; | 192 break; |
160 case JVM_CONSTANT_Integer : | 193 case JVM_CONSTANT_Integer : |
161 { | 194 { |
162 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags | 195 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags |
255 // Allocate the remaining symbols | 288 // Allocate the remaining symbols |
256 if (names_count > 0) { | 289 if (names_count > 0) { |
257 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); | 290 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); |
258 } | 291 } |
259 | 292 |
293 if (operands != NULL && operands->length() > 0) { | |
294 store_operand_array(operands, cp, CHECK); | |
295 } | |
296 #ifdef ASSERT | |
297 // Re-assert the indy structures, now that assertion checking can work. | |
298 for (int indy_i = 0; indy_i < indy_instructions->length(); ) { | |
299 int index = indy_instructions->at(indy_i++); | |
300 int bootstrap_method_index = indy_instructions->at(indy_i++); | |
301 int name_and_type_index = indy_instructions->at(indy_i++); | |
302 int argument_count = indy_instructions->at(indy_i++); | |
303 assert(cp->check_invoke_dynamic_at(index, | |
304 bootstrap_method_index, name_and_type_index, | |
305 argument_count), | |
306 "indy structure is OK"); | |
307 } | |
308 #endif //ASSERT | |
309 | |
260 // Copy _current pointer of local copy back to stream(). | 310 // Copy _current pointer of local copy back to stream(). |
261 #ifdef ASSERT | 311 #ifdef ASSERT |
262 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); | 312 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); |
263 #endif | 313 #endif |
264 cfs0->set_current(cfs1.current()); | 314 cfs0->set_current(cfs1.current()); |
265 } | 315 } |
316 | |
317 int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { | |
318 if (operands == NULL) { | |
319 operands = new GrowableArray<int>(THREAD, 100); | |
320 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
321 while (operands->length() <= fillp_offset) | |
322 operands->append(0); // force op_base > 0, for an error check | |
323 DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); | |
324 } | |
325 int cnt_pos = operands->append(op_count); | |
326 int arg_pos = operands->length(); | |
327 operands->at_grow(arg_pos + op_count - 1); // grow to include the operands | |
328 assert(operands->length() == arg_pos + op_count, ""); | |
329 int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; | |
330 return op_base; | |
331 } | |
332 | |
333 void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { | |
334 // Collect the buffer of operands from variable-sized entries into a permanent array. | |
335 int arraylen = operands->length(); | |
336 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
337 assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); | |
338 operands->at_put(fillp_offset, arraylen); | |
339 cp->multi_operand_buffer_grow(arraylen, CHECK); | |
340 typeArrayOop operands_oop = cp->operands(); | |
341 assert(operands_oop->length() == arraylen, ""); | |
342 for (int i = 0; i < arraylen; i++) { | |
343 operands_oop->int_at_put(i, operands->at(i)); | |
344 } | |
345 cp->set_operands(operands_oop); | |
346 // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, | |
347 // when constant pools need to be merged. Make sure it is sane now. | |
348 assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); | |
349 } | |
350 | |
266 | 351 |
267 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } | 352 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } |
268 | 353 |
269 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { | 354 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { |
270 ClassFileStream* cfs = stream(); | 355 ClassFileStream* cfs = stream(); |
429 EnableMethodHandles, | 514 EnableMethodHandles, |
430 "Invalid constant pool index %u in class file %s", | 515 "Invalid constant pool index %u in class file %s", |
431 ref_index, CHECK_(nullHandle)); | 516 ref_index, CHECK_(nullHandle)); |
432 } | 517 } |
433 break; | 518 break; |
519 case JVM_CONSTANT_InvokeDynamicTrans : | |
520 ShouldNotReachHere(); // this tag does not appear in the heap | |
434 case JVM_CONSTANT_InvokeDynamic : | 521 case JVM_CONSTANT_InvokeDynamic : |
435 { | 522 { |
436 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); | 523 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); |
437 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); | 524 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); |
438 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) | 525 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) |
439 || | 526 || |
440 (valid_cp_range(bootstrap_method_ref_index, length) && | 527 (valid_cp_range(bootstrap_method_ref_index, length) && |
441 cp->tag_at(bootstrap_method_ref_index).is_method_handle()), | 528 (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), |
442 "Invalid constant pool index %u in class file %s", | 529 "Invalid constant pool index %u in class file %s", |
443 bootstrap_method_ref_index, | 530 bootstrap_method_ref_index, |
444 CHECK_(nullHandle)); | 531 CHECK_(nullHandle)); |
445 check_property(valid_cp_range(name_and_type_ref_index, length) && | 532 check_property(valid_cp_range(name_and_type_ref_index, length) && |
446 cp->tag_at(name_and_type_ref_index).is_name_and_type(), | 533 cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
447 "Invalid constant pool index %u in class file %s", | 534 "Invalid constant pool index %u in class file %s", |
448 name_and_type_ref_index, | 535 name_and_type_ref_index, |
449 CHECK_(nullHandle)); | 536 CHECK_(nullHandle)); |
537 int argc = cp->invoke_dynamic_argument_count_at(index); | |
538 for (int arg_i = 0; arg_i < argc; arg_i++) { | |
539 int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); | |
540 check_property(valid_cp_range(arg, length) && | |
541 cp->tag_at(arg).is_loadable_constant() || | |
542 // temporary early forms of string and class: | |
543 cp->tag_at(arg).is_klass_index() || | |
544 cp->tag_at(arg).is_string_index(), | |
545 "Invalid constant pool index %u in class file %s", | |
546 arg, | |
547 CHECK_(nullHandle)); | |
548 } | |
450 break; | 549 break; |
451 } | 550 } |
452 default: | 551 default: |
453 fatal(err_msg("bad constant pool tag value %u", | 552 fatal(err_msg("bad constant pool tag value %u", |
454 cp->tag_at(index).value())); | 553 cp->tag_at(index).value())); |