src/share/vm/prims/jvmtiRedefineClasses.cpp

changeset 4983
15a99ca4ee34
parent 4965
6337ca4dcad8
child 5084
712a1e9c91f3
     1.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Apr 24 15:57:17 2013 -0700
     1.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Apr 25 03:58:53 2013 -0700
     1.3 @@ -415,20 +415,26 @@
     1.4      // this is an indirect CP entry so it needs special handling
     1.5      case JVM_CONSTANT_InvokeDynamic:
     1.6      {
     1.7 -      // TBD: cross-checks and possible extra appends into CP and bsm operands
     1.8 -      // are needed as well. This issue is tracked by a separate bug 8007037.
     1.9 -      int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
    1.10 -
    1.11 -      int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
    1.12 -      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
    1.13 +      // Index of the bootstrap specifier in the operands array
    1.14 +      int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
    1.15 +      int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p,
    1.16 +                                            merge_cp_length_p, THREAD);
    1.17 +      // The bootstrap method NameAndType_info index
    1.18 +      int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
    1.19 +      int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
    1.20                                                      merge_cp_length_p, THREAD);
    1.21 -      if (new_ref_i != ref_i) {
    1.22 +      if (new_bs_i != old_bs_i) {
    1.23          RC_TRACE(0x00080000,
    1.24 -                 ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d",
    1.25 -                  *merge_cp_length_p, ref_i, new_ref_i));
    1.26 +                 ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d",
    1.27 +                  *merge_cp_length_p, old_bs_i, new_bs_i));
    1.28        }
    1.29 -
    1.30 -      (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i);
    1.31 +      if (new_ref_i != old_ref_i) {
    1.32 +        RC_TRACE(0x00080000,
    1.33 +                 ("InvokeDynamic entry@%d name_and_type_index change: %d to %d",
    1.34 +                  *merge_cp_length_p, old_ref_i, new_ref_i));
    1.35 +      }
    1.36 +
    1.37 +      (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
    1.38        if (scratch_i != *merge_cp_length_p) {
    1.39          // The new entry in *merge_cp_p is at a different index than
    1.40          // the new entry in scratch_cp so we need to map the index values.
    1.41 @@ -492,6 +498,105 @@
    1.42  } // end find_or_append_indirect_entry()
    1.43  
    1.44  
    1.45 +// Append a bootstrap specifier into the merge_cp operands that is semantically equal
    1.46 +// to the scratch_cp operands bootstrap specifier passed by the old_bs_i index.
    1.47 +// Recursively append new merge_cp entries referenced by the new bootstrap specifier.
    1.48 +void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i,
    1.49 +       constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
    1.50 +
    1.51 +  int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i);
    1.52 +  int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
    1.53 +                                                merge_cp_length_p, THREAD);
    1.54 +  if (new_ref_i != old_ref_i) {
    1.55 +    RC_TRACE(0x00080000,
    1.56 +             ("operands entry@%d bootstrap method ref_index change: %d to %d",
    1.57 +              _operands_cur_length, old_ref_i, new_ref_i));
    1.58 +  }
    1.59 +
    1.60 +  Array<u2>* merge_ops = (*merge_cp_p)->operands();
    1.61 +  int new_bs_i = _operands_cur_length;
    1.62 +  // We have _operands_cur_length == 0 when the merge_cp operands is empty yet.
    1.63 +  // However, the operand_offset_at(0) was set in the extend_operands() call.
    1.64 +  int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0)
    1.65 +                                 : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1);
    1.66 +  int argc     = scratch_cp->operand_argument_count_at(old_bs_i);
    1.67 +
    1.68 +  ConstantPool::operand_offset_at_put(merge_ops, _operands_cur_length, new_base);
    1.69 +  merge_ops->at_put(new_base++, new_ref_i);
    1.70 +  merge_ops->at_put(new_base++, argc);
    1.71 +
    1.72 +  for (int i = 0; i < argc; i++) {
    1.73 +    int old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i);
    1.74 +    int new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p,
    1.75 +                                                      merge_cp_length_p, THREAD);
    1.76 +    merge_ops->at_put(new_base++, new_arg_ref_i);
    1.77 +    if (new_arg_ref_i != old_arg_ref_i) {
    1.78 +      RC_TRACE(0x00080000,
    1.79 +               ("operands entry@%d bootstrap method argument ref_index change: %d to %d",
    1.80 +                _operands_cur_length, old_arg_ref_i, new_arg_ref_i));
    1.81 +    }
    1.82 +  }
    1.83 +  if (old_bs_i != _operands_cur_length) {
    1.84 +    // The bootstrap specifier in *merge_cp_p is at a different index than
    1.85 +    // that in scratch_cp so we need to map the index values.
    1.86 +    map_operand_index(old_bs_i, new_bs_i);
    1.87 +  }
    1.88 +  _operands_cur_length++;
    1.89 +} // end append_operand()
    1.90 +
    1.91 +
    1.92 +int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp,
    1.93 +      int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
    1.94 +
    1.95 +  int new_bs_i = old_bs_i; // bootstrap specifier index
    1.96 +  bool match = (old_bs_i < _operands_cur_length) &&
    1.97 +               scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i, THREAD);
    1.98 +
    1.99 +  if (!match) {
   1.100 +    // forward reference in *merge_cp_p or not a direct match
   1.101 +    int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p,
   1.102 +                                                    _operands_cur_length, THREAD);
   1.103 +    if (found_i != -1) {
   1.104 +      guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree");
   1.105 +      // found a matching operand somewhere else in *merge_cp_p so just need a mapping
   1.106 +      new_bs_i = found_i;
   1.107 +      map_operand_index(old_bs_i, found_i);
   1.108 +    } else {
   1.109 +      // no match found so we have to append this bootstrap specifier to *merge_cp_p
   1.110 +      append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD);
   1.111 +      new_bs_i = _operands_cur_length - 1;
   1.112 +    }
   1.113 +  }
   1.114 +  return new_bs_i;
   1.115 +} // end find_or_append_operand()
   1.116 +
   1.117 +
   1.118 +void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) {
   1.119 +  if (merge_cp->operands() == NULL) {
   1.120 +    return;
   1.121 +  }
   1.122 +  // Shrink the merge_cp operands
   1.123 +  merge_cp->shrink_operands(_operands_cur_length, CHECK);
   1.124 +
   1.125 +  if (RC_TRACE_ENABLED(0x00040000)) {
   1.126 +    // don't want to loop unless we are tracing
   1.127 +    int count = 0;
   1.128 +    for (int i = 1; i < _operands_index_map_p->length(); i++) {
   1.129 +      int value = _operands_index_map_p->at(i);
   1.130 +      if (value != -1) {
   1.131 +        RC_TRACE_WITH_THREAD(0x00040000, THREAD,
   1.132 +          ("operands_index_map[%d]: old=%d new=%d", count, i, value));
   1.133 +        count++;
   1.134 +      }
   1.135 +    }
   1.136 +  }
   1.137 +  // Clean-up
   1.138 +  _operands_index_map_p = NULL;
   1.139 +  _operands_cur_length = 0;
   1.140 +  _operands_index_map_count = 0;
   1.141 +} // end finalize_operands_merge()
   1.142 +
   1.143 +
   1.144  jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
   1.145               instanceKlassHandle the_class,
   1.146               instanceKlassHandle scratch_class) {
   1.147 @@ -765,6 +870,31 @@
   1.148  } // end find_new_index()
   1.149  
   1.150  
   1.151 +// Find new bootstrap specifier index value for old bootstrap specifier index
   1.152 +// value by seaching the index map. Returns unused index (-1) if there is
   1.153 +// no mapped value for the old bootstrap specifier index.
   1.154 +int VM_RedefineClasses::find_new_operand_index(int old_index) {
   1.155 +  if (_operands_index_map_count == 0) {
   1.156 +    // map is empty so nothing can be found
   1.157 +    return -1;
   1.158 +  }
   1.159 +
   1.160 +  if (old_index == -1 || old_index >= _operands_index_map_p->length()) {
   1.161 +    // The old_index is out of range so it is not mapped.
   1.162 +    // This should not happen in regular constant pool merging use.
   1.163 +    return -1;
   1.164 +  }
   1.165 +
   1.166 +  int value = _operands_index_map_p->at(old_index);
   1.167 +  if (value == -1) {
   1.168 +    // the old_index is not mapped
   1.169 +    return -1;
   1.170 +  }
   1.171 +
   1.172 +  return value;
   1.173 +} // end find_new_operand_index()
   1.174 +
   1.175 +
   1.176  // Returns true if the current mismatch is due to a resolved/unresolved
   1.177  // class pair. Otherwise, returns false.
   1.178  bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1,
   1.179 @@ -1014,6 +1144,25 @@
   1.180  } // end map_index()
   1.181  
   1.182  
   1.183 +// Map old_index to new_index as needed.
   1.184 +void VM_RedefineClasses::map_operand_index(int old_index, int new_index) {
   1.185 +  if (find_new_operand_index(old_index) != -1) {
   1.186 +    // old_index is already mapped
   1.187 +    return;
   1.188 +  }
   1.189 +
   1.190 +  if (old_index == new_index) {
   1.191 +    // no mapping is needed
   1.192 +    return;
   1.193 +  }
   1.194 +
   1.195 +  _operands_index_map_p->at_put(old_index, new_index);
   1.196 +  _operands_index_map_count++;
   1.197 +
   1.198 +  RC_TRACE(0x00040000, ("mapped bootstrap specifier at index %d to %d", old_index, new_index));
   1.199 +} // end map_index()
   1.200 +
   1.201 +
   1.202  // Merge old_cp and scratch_cp and return the results of the merge via
   1.203  // merge_cp_p. The number of entries in *merge_cp_p is returned via
   1.204  // merge_cp_length_p. The entries in old_cp occupy the same locations
   1.205 @@ -1086,6 +1235,7 @@
   1.206      } // end for each old_cp entry
   1.207  
   1.208      ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0);
   1.209 +    (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0);
   1.210  
   1.211      // We don't need to sanity check that *merge_cp_length_p is within
   1.212      // *merge_cp_p bounds since we have the minimum on-entry check above.
   1.213 @@ -1198,6 +1348,8 @@
   1.214          CHECK_0);
   1.215      }
   1.216  
   1.217 +    finalize_operands_merge(*merge_cp_p, THREAD);
   1.218 +
   1.219      RC_TRACE_WITH_THREAD(0x00020000, THREAD,
   1.220        ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
   1.221        *merge_cp_length_p, scratch_i, _index_map_count));
   1.222 @@ -1270,6 +1422,11 @@
   1.223    _index_map_count = 0;
   1.224    _index_map_p = new intArray(scratch_cp->length(), -1);
   1.225  
   1.226 +  _operands_cur_length = ConstantPool::operand_array_length(old_cp->operands());
   1.227 +  _operands_index_map_count = 0;
   1.228 +  _operands_index_map_p = new intArray(
   1.229 +    ConstantPool::operand_array_length(scratch_cp->operands()), -1);
   1.230 +
   1.231    // reference to the cp holder is needed for copy_operands()
   1.232    merge_cp->set_pool_holder(scratch_class());
   1.233    bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
   1.234 @@ -1400,7 +1557,6 @@
   1.235    return true;
   1.236  } // end rewrite_cp_refs()
   1.237  
   1.238 -
   1.239  // Rewrite constant pool references in the methods.
   1.240  bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
   1.241         instanceKlassHandle scratch_class, TRAPS) {

mercurial