Mercurial > hg > graal-jvmci-8
diff src/share/vm/classfile/classFileParser.cpp @ 1922:5caa30ea147b
Merge
author | iveresov |
---|---|
date | Mon, 08 Nov 2010 14:33:48 -0800 |
parents | 6412b3805cd6 3b2dea75431e |
children | f95d63e2154a |
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp Thu Nov 04 16:17:54 2010 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Nov 08 14:33:48 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,6 +73,12 @@ unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; int names_count = 0; + // Side buffer for operands of variable-sized (InvokeDynamic) entries. + GrowableArray<int>* operands = NULL; +#ifdef ASSERT + GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); +#endif + // parsing Index 0 is unused for (int index = 1; index < length; index++) { // Each of the following case guarantees one more byte in the stream @@ -141,6 +147,7 @@ ShouldNotReachHere(); } break; + case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles case JVM_CONSTANT_InvokeDynamic : { if (!EnableInvokeDynamic || @@ -151,10 +158,36 @@ "Class file version does not support constant tag %u in class file %s"), tag, CHECK); } - cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags + if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { + classfile_parse_error( + "This JVM does not support transitional InvokeDynamic tag %u in class file %s", + tag, CHECK); + } + bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); + cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags u2 bootstrap_method_index = cfs->get_u2_fast(); u2 name_and_type_index = cfs->get_u2_fast(); - cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); + int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); + cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags + int argv_offset = constantPoolOopDesc::_indy_argv_offset; + int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... + int op_base = start_operand_group(operands, op_count, CHECK); + assert(argv_offset == 3, "else adjust next 3 assignments"); + operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); + operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); + operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); + for (int arg_i = 0; arg_i < argument_count; arg_i++) { + int arg = cfs->get_u2_fast(); + operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); + } + cp->invoke_dynamic_at_put(index, op_base, op_count); +#ifdef ASSERT + // Record the steps just taken for later checking. + indy_instructions->append(index); + indy_instructions->append(bootstrap_method_index); + indy_instructions->append(name_and_type_index); + indy_instructions->append(argument_count); +#endif //ASSERT } break; case JVM_CONSTANT_Integer : @@ -257,6 +290,23 @@ oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); } + if (operands != NULL && operands->length() > 0) { + store_operand_array(operands, cp, CHECK); + } +#ifdef ASSERT + // Re-assert the indy structures, now that assertion checking can work. + for (int indy_i = 0; indy_i < indy_instructions->length(); ) { + int index = indy_instructions->at(indy_i++); + int bootstrap_method_index = indy_instructions->at(indy_i++); + int name_and_type_index = indy_instructions->at(indy_i++); + int argument_count = indy_instructions->at(indy_i++); + assert(cp->check_invoke_dynamic_at(index, + bootstrap_method_index, name_and_type_index, + argument_count), + "indy structure is OK"); + } +#endif //ASSERT + // Copy _current pointer of local copy back to stream(). #ifdef ASSERT assert(cfs0->current() == old_current, "non-exclusive use of stream()"); @@ -264,6 +314,41 @@ cfs0->set_current(cfs1.current()); } +int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { + if (operands == NULL) { + operands = new GrowableArray<int>(THREAD, 100); + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; + while (operands->length() <= fillp_offset) + operands->append(0); // force op_base > 0, for an error check + DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); + } + int cnt_pos = operands->append(op_count); + int arg_pos = operands->length(); + operands->at_grow(arg_pos + op_count - 1); // grow to include the operands + assert(operands->length() == arg_pos + op_count, ""); + int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; + return op_base; +} + +void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { + // Collect the buffer of operands from variable-sized entries into a permanent array. + int arraylen = operands->length(); + int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; + assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); + operands->at_put(fillp_offset, arraylen); + cp->multi_operand_buffer_grow(arraylen, CHECK); + typeArrayOop operands_oop = cp->operands(); + assert(operands_oop->length() == arraylen, ""); + for (int i = 0; i < arraylen; i++) { + operands_oop->int_at_put(i, operands->at(i)); + } + cp->set_operands(operands_oop); + // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, + // when constant pools need to be merged. Make sure it is sane now. + assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); +} + + bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { @@ -431,6 +516,8 @@ ref_index, CHECK_(nullHandle)); } break; + case JVM_CONSTANT_InvokeDynamicTrans : + ShouldNotReachHere(); // this tag does not appear in the heap case JVM_CONSTANT_InvokeDynamic : { int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); @@ -438,7 +525,7 @@ check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) || (valid_cp_range(bootstrap_method_ref_index, length) && - cp->tag_at(bootstrap_method_ref_index).is_method_handle()), + (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), "Invalid constant pool index %u in class file %s", bootstrap_method_ref_index, CHECK_(nullHandle)); @@ -447,6 +534,18 @@ "Invalid constant pool index %u in class file %s", name_and_type_ref_index, CHECK_(nullHandle)); + int argc = cp->invoke_dynamic_argument_count_at(index); + for (int arg_i = 0; arg_i < argc; arg_i++) { + int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); + check_property(valid_cp_range(arg, length) && + cp->tag_at(arg).is_loadable_constant() || + // temporary early forms of string and class: + cp->tag_at(arg).is_klass_index() || + cp->tag_at(arg).is_string_index(), + "Invalid constant pool index %u in class file %s", + arg, + CHECK_(nullHandle)); + } break; } default: @@ -2516,18 +2615,6 @@ // field. If it is not present, artifically create a field for it. // This allows this VM to run on early JDK where the field is not // present. - - // - // Increment fac.nonstatic_oop_count so that the start of the - // next type of non-static oops leaves room for the fake oop. - // Do not increment next_nonstatic_oop_offset so that the - // fake oop is place after the java.lang.ref.Reference oop - // fields. - // - // Check the fields in java.lang.ref.Reference for the "discovered" - // field. If it is not present, artifically create a field for it. - // This allows this VM to run on early JDK where the field is not - // present. int reference_sig_index = 0; int reference_name_index = 0; int reference_index = 0; @@ -2663,7 +2750,7 @@ // Force MethodHandle.vmentry to be an unmanaged pointer. // There is no way for a classfile to express this, so we must help it. void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, - typeArrayHandle* fields_ptr, + typeArrayHandle fields, FieldAllocationCount *fac_ptr, TRAPS) { // Add fake fields for java.dyn.MethodHandle instances @@ -2687,41 +2774,45 @@ THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); + // Find vmentry field and change the signature. bool found_vmentry = false; - - const int n = (*fields_ptr)()->length(); - for (int i = 0; i < n; i += instanceKlass::next_offset) { - int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset); - int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset); - int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset); + for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) { + int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); + int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); + int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); symbolOop f_name = cp->symbol_at(name_index); symbolOop f_sig = cp->symbol_at(sig_index); - if (f_sig == vmSymbols::byte_signature() && - f_name == vmSymbols::vmentry_name() && - (acc_flags & JVM_ACC_STATIC) == 0) { - // Adjust the field type from byte to an unmanaged pointer. - assert(fac_ptr->nonstatic_byte_count > 0, ""); - fac_ptr->nonstatic_byte_count -= 1; - - (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); - assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); - if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; - else fac_ptr->nonstatic_word_count += 1; - - FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset); - assert(atype == NONSTATIC_BYTE, ""); - FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; - (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype); - - found_vmentry = true; - break; + + if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { + if (f_sig == vmSymbols::machine_word_signature()) { + // If the signature of vmentry is already changed, we're done. + found_vmentry = true; + break; + } + else if (f_sig == vmSymbols::byte_signature()) { + // Adjust the field type from byte to an unmanaged pointer. + assert(fac_ptr->nonstatic_byte_count > 0, ""); + fac_ptr->nonstatic_byte_count -= 1; + + fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); + assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); + if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; + else fac_ptr->nonstatic_word_count += 1; + + FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); + assert(atype == NONSTATIC_BYTE, ""); + FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; + fields->ushort_at_put(i + instanceKlass::low_offset, new_atype); + + found_vmentry = true; + break; + } } } if (!found_vmentry) THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "missing vmentry byte field in java.dyn.MethodHandle"); - } @@ -3082,7 +3173,7 @@ // adjust the vmentry field declaration in java.dyn.MethodHandle if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { - java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle)); + java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); } // Add a fake "discovered" field if it is not present