[openjdk-7-jre-dcevm] 03/04: DCEVM patch for Java 7u60

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Mon Sep 1 21:20:17 UTC 2014


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch master
in repository openjdk-7-jre-dcevm.

commit 7da47b300d5a2863119a1e5982719d085a31db39
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Mon Sep 1 19:54:52 2014 +0200

    DCEVM patch for Java 7u60
---
 ...ll-jdk7u55-b13.patch => full-jdk7u60-b09.patch} | 2957 ++++++++++----------
 debian/patches/series                              |    2 +-
 2 files changed, 1547 insertions(+), 1412 deletions(-)

diff --git a/debian/patches/full-jdk7u55-b13.patch b/debian/patches/full-jdk7u60-b09.patch
similarity index 96%
rename from debian/patches/full-jdk7u55-b13.patch
rename to debian/patches/full-jdk7u60-b09.patch
index 20c086d..4c7dedd 100644
--- a/debian/patches/full-jdk7u55-b13.patch
+++ b/debian/patches/full-jdk7u60-b09.patch
@@ -1,6 +1,6 @@
 --- a/make/bsd/makefiles/gcc.make
 +++ b/make/bsd/makefiles/gcc.make
-@@ -116,7 +116,10 @@
+@@ -117,7 +117,10 @@
  CFLAGS += -fno-rtti
  CFLAGS += -fno-exceptions
  CFLAGS += -pthread
@@ -331,25 +331,6 @@
    // Get receiver klass into rdx - also a null check
    __ restore_locals();  // restore r14
    __ null_check(rcx, oopDesc::klass_offset_in_bytes());
---- a/src/os/bsd/vm/attachListener_bsd.cpp
-+++ b/src/os/bsd/vm/attachListener_bsd.cpp
-@@ -460,14 +460,14 @@
- 
- void AttachListener::vm_start() {
-   char fn[UNIX_PATH_MAX];
--  struct stat64 st;
-+  struct stat st;
-   int ret;
- 
-   int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
-            os::get_temp_directory(), os::current_process_id());
-   assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
- 
--  RESTARTABLE(::stat64(fn, &st), ret);
-+  RESTARTABLE(::stat(fn, &st), ret);
-   if (ret == 0) {
-     ret = ::unlink(fn);
-     if (ret == -1) {
 --- a/src/share/vm/c1/c1_Compilation.hpp
 +++ b/src/share/vm/c1/c1_Compilation.hpp
 @@ -242,8 +242,8 @@
@@ -567,7 +548,7 @@
    // Copy byte codes
    m->set_code(code_start);
  
-@@ -2797,6 +2838,15 @@
+@@ -2792,6 +2833,15 @@
            "Invalid Deprecated classfile attribute length %u in class file %s",
            attribute_length, CHECK);
        }
@@ -583,7 +564,7 @@
      } else if (_major_version >= JAVA_1_5_VERSION) {
        if (tag == vmSymbols::tag_signature()) {
          if (attribute_length != 2) {
-@@ -2900,6 +2950,17 @@
+@@ -2895,6 +2945,17 @@
    }
    k->set_inner_classes(_inner_classes());
    k->set_class_annotations(_annotations());
@@ -601,7 +582,7 @@
  }
  
  typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
-@@ -2923,9 +2984,126 @@
+@@ -2918,9 +2979,126 @@
  }
  
  
@@ -728,7 +709,7 @@
                                                      KlassHandle host_klass,
                                                      GrowableArray<Handle>* cp_patches,
                                                      TempNewSymbol& parsed_name,
-@@ -2976,10 +3154,13 @@
+@@ -2971,10 +3149,13 @@
      unsigned char* ptr = cfs->buffer();
      unsigned char* end_ptr = cfs->buffer() + cfs->length();
  
@@ -742,7 +723,7 @@
  
      if (ptr != cfs->buffer()) {
        // JVMTI agent has modified class file data.
-@@ -3135,7 +3316,11 @@
+@@ -3130,7 +3311,11 @@
        // However, make sure it is not an array type.
        bool is_array = false;
        if (cp->tag_at(super_class_index).is_klass()) {
@@ -755,7 +736,7 @@
          if (_need_verify)
            is_array = super_klass->oop_is_array();
        } else if (_need_verify) {
-@@ -3153,7 +3338,7 @@
+@@ -3148,7 +3333,7 @@
      if (itfs_len == 0) {
        local_interfaces = objArrayHandle(THREAD, Universe::the_empty_system_obj_array());
      } else {
@@ -764,7 +745,7 @@
      }
  
      u2 java_fields_count = 0;
-@@ -3207,7 +3392,9 @@
+@@ -3202,7 +3387,9 @@
                                                             protection_domain,
                                                             true,
                                                             CHECK_(nullHandle));
@@ -775,7 +756,7 @@
        KlassHandle kh (THREAD, k);
        super_klass = instanceKlassHandle(THREAD, kh());
      }
-@@ -3596,6 +3783,19 @@
+@@ -3591,6 +3778,19 @@
        rt = REF_NONE;
      } else {
        rt = super_klass->reference_type();
@@ -795,7 +776,7 @@
      }
  
      // We can now create the basic klassOop for this klass
-@@ -3696,7 +3896,7 @@
+@@ -3691,7 +3891,7 @@
      fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
  
      // Fill in has_finalizer, has_vanilla_constructor, and layout_helper
@@ -804,7 +785,7 @@
  
      // reinitialize modifiers, using the InnerClasses attribute
      int computed_modifiers = this_klass->compute_modifier_flags(CHECK_(nullHandle));
-@@ -3719,6 +3919,10 @@
+@@ -3714,6 +3914,10 @@
      // Allocate mirror and initialize static fields
      java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
  
@@ -815,7 +796,7 @@
      ClassLoadingService::notify_class_loaded(instanceKlass::cast(this_klass()),
                                               false /* not shared class */);
  
-@@ -3861,7 +4065,7 @@
+@@ -3856,7 +4060,7 @@
  }
  
  
@@ -824,7 +805,7 @@
    klassOop super = k->super();
  
    // Check if this klass has an empty finalize method (i.e. one with return bytecode only),
-@@ -3869,7 +4073,9 @@
+@@ -3864,7 +4068,9 @@
    if (!_has_empty_finalizer) {
      if (_has_finalizer ||
          (super != NULL && super->klass_part()->has_finalizer())) {
@@ -835,7 +816,7 @@
      }
    }
  
-@@ -3885,7 +4091,7 @@
+@@ -3880,7 +4086,7 @@
  
    // Check if this klass supports the java.lang.Cloneable interface
    if (SystemDictionary::Cloneable_klass_loaded()) {
@@ -1251,7 +1232,7 @@
  
    Handle linkage_exception = Handle(); // null handle
  
-@@ -1612,6 +1647,14 @@
+@@ -1613,6 +1648,14 @@
    Universe::flush_dependents_on(k);
  }
  
@@ -1266,7 +1247,7 @@
  
  // ----------------------------------------------------------------------------
  // GC support
-@@ -1701,6 +1744,24 @@
+@@ -1702,6 +1745,24 @@
  }
  
  
@@ -1291,7 +1272,7 @@
  void SystemDictionary::preloaded_oops_do(OopClosure* f) {
    for (int k = (int)FIRST_WKID; k < (int)WKID_LIMIT; k++) {
      f->do_oop((oop*) &_well_known_klasses[k]);
-@@ -1733,6 +1794,11 @@
+@@ -1734,6 +1795,11 @@
    dictionary()->classes_do(f);
  }
  
@@ -1303,7 +1284,7 @@
  // Added for initialize_itable_for_klass
  //   Just the classes from defining class loaders
  // Don't iterate over placeholders
-@@ -1869,7 +1935,9 @@
+@@ -1870,7 +1936,9 @@
  
    // Preload ref klasses and set reference types
    instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
@@ -1314,7 +1295,7 @@
  
    initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
    instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
-@@ -1955,7 +2023,11 @@
+@@ -1956,7 +2024,11 @@
        // also holds array classes
  
        assert(check->klass_part()->oop_is_instance(), "noninstance in systemdictionary");
@@ -1329,7 +1310,7 @@
        } else {
 --- a/src/share/vm/classfile/systemDictionary.hpp
 +++ b/src/share/vm/classfile/systemDictionary.hpp
-@@ -268,7 +268,7 @@
+@@ -269,7 +269,7 @@
    // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
    static klassOop resolve_from_stream(Symbol* class_name, Handle class_loader,
                                        Handle protection_domain,
@@ -1338,7 +1319,7 @@
  
    // Lookup an already loaded class. If not found NULL is returned.
    static klassOop find(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
-@@ -309,6 +309,8 @@
+@@ -310,6 +310,8 @@
    // Iterate over all klasses in dictionary
    //   Just the classes from defining class loaders
    static void classes_do(void f(klassOop));
@@ -1347,7 +1328,7 @@
    // Added for initialize_itable_for_klass to handle exceptions
    static void classes_do(void f(klassOop, TRAPS), TRAPS);
    //   All classes, and their class loaders
-@@ -415,6 +417,8 @@
+@@ -416,6 +418,8 @@
      initialize_wk_klasses_until((WKID) limit, start_id, THREAD);
    }
  
@@ -1356,7 +1337,7 @@
  public:
    #define WK_KLASS_DECLARE(name, symbol, option) \
      static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); }
-@@ -596,7 +600,7 @@
+@@ -597,11 +601,11 @@
    // after waiting, but before reentering SystemDictionary_lock
    // to preserve lock order semantics.
    static void double_lock_wait(Handle lockObject, TRAPS);
@@ -1365,18 +1346,22 @@
    static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
                                                  Handle class_loader,
                                                  instanceKlassHandle k, TRAPS);
-@@ -615,12 +619,17 @@
+-  static instanceKlassHandle load_shared_class(Symbol* class_name,
++  static instanceKlassHandle load_shared_class(Symbol* class_name, // after waiting, but before reentering SystemDictionary_lock,
+                                                Handle class_loader, TRAPS);
+   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
+                                                Handle class_loader, TRAPS);
+@@ -616,12 +620,16 @@
    // Setup link to hierarchy
    static void add_to_hierarchy(instanceKlassHandle k, TRAPS);
  
 +public:
-+
 +  // Remove link to hierarchy
 +  static void remove_from_hierarchy(instanceKlassHandle k);
 +
 +private:
    // event based tracing
-   static void post_class_load_event(TracingTime start_time, instanceKlassHandle k,
+   static void post_class_load_event(const Ticks& start_time, instanceKlassHandle k,
                                      Handle initiating_loader);
    static void post_class_unload_events(BoolObjectClosure* is_alive);
  
@@ -1513,7 +1498,7 @@
                                                                                                    \
    /* exception klasses: at least all exceptions thrown by the VM have entries here */             \
    template(java_lang_ArithmeticException,             "java/lang/ArithmeticException")            \
-@@ -377,6 +381,10 @@
+@@ -379,6 +383,10 @@
    template(oop_size_name,                             "oop_size")                                 \
    template(static_oop_field_count_name,               "static_oop_field_count")                   \
                                                                                                    \
@@ -1847,7 +1832,7 @@
          // means then there could be a bug here.
 --- a/src/share/vm/interpreter/interpreterRuntime.hpp
 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp
-@@ -140,6 +140,9 @@
+@@ -141,6 +141,9 @@
    static void post_method_entry(JavaThread *thread);
    static void post_method_exit (JavaThread *thread);
    static int  interpreter_contains(address pc);
@@ -2951,9 +2936,9 @@
    // Debugging
    static bool verify_in_progress() { return _verify_in_progress; }
 +  static void set_verify_in_progress(bool b) { _verify_in_progress = b; }
-   static void verify(bool silent, VerifyOption option);
-   static void verify(bool silent) {
-     verify(silent, VerifyOption_Default /* option */);
+   static void verify(VerifyOption option, const char* prefix, bool silent = VerifySilently);
+   static void verify(const char* prefix, bool silent = VerifySilently) {
+     verify(VerifyOption_Default, prefix, silent);
 --- a/src/share/vm/oops/arrayKlass.cpp
 +++ b/src/share/vm/oops/arrayKlass.cpp
 @@ -129,9 +129,9 @@
@@ -3761,7 +3746,7 @@
  #ifdef ASSERT
    tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
    nm->print();
-@@ -2382,6 +2677,9 @@
+@@ -2417,6 +2712,9 @@
      klassOop mirrored_klass = java_lang_Class::as_klassOop(obj);
      st->print(BULLET"fake entry for mirror: ");
      mirrored_klass->print_value_on(st);
@@ -3773,7 +3758,7 @@
      methodOop ctor = java_lang_Class::resolved_constructor(obj);
 --- a/src/share/vm/oops/instanceKlass.hpp
 +++ b/src/share/vm/oops/instanceKlass.hpp
-@@ -101,6 +101,22 @@
+@@ -102,6 +102,22 @@
    virtual void do_field(fieldDescriptor* fd) = 0;
  };
  
@@ -3796,7 +3781,7 @@
  #ifndef PRODUCT
  // Print fields.
  // If "obj" argument to constructor is NULL, prints static fields, otherwise prints non-static fields.
-@@ -285,6 +301,11 @@
+@@ -287,6 +303,11 @@
    // _idnum_allocated_count.
    u1              _init_state;                    // state of class
  
@@ -3808,7 +3793,7 @@
    u1              _reference_type;                // reference type
  
    // embedded Java vtable follows here
-@@ -452,6 +473,7 @@
+@@ -454,6 +475,7 @@
    // initialization (virtuals from Klass)
    bool should_be_initialized() const;  // means that initialize should be called
    void initialize(TRAPS);
@@ -3816,7 +3801,7 @@
    void link_class(TRAPS);
    bool link_class_or_fail(TRAPS); // returns false on failure
    void unlink_class();
-@@ -629,6 +651,7 @@
+@@ -631,6 +653,7 @@
    static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum,
                  size_t *length_p, jmethodID* id_p);
    jmethodID jmethod_id_or_null(methodOop method);
@@ -3824,7 +3809,7 @@
  
    // cached itable index support
    void set_cached_itable_index(size_t idnum, int index);
-@@ -711,6 +734,7 @@
+@@ -713,6 +736,7 @@
  
    // subclass/subinterface checks
    bool implements_interface(klassOop k) const;
@@ -3832,7 +3817,7 @@
  
    // Access to the implementor of an interface.
    klassOop implementor() const
-@@ -760,6 +784,12 @@
+@@ -762,6 +786,12 @@
    void do_local_static_fields(FieldClosure* cl);
    void do_nonstatic_fields(FieldClosure* cl); // including inherited fields
    void do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAPS);
@@ -4736,12 +4721,12 @@
 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
 @@ -1,5 +1,5 @@
  /*
-- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
 + * Copyright (c) 2003, 2011, 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
-@@ -30,498 +30,637 @@
+@@ -30,581 +30,637 @@
  #include "interpreter/rewriter.hpp"
  #include "memory/gcLocker.hpp"
  #include "memory/universe.inline.hpp"
@@ -4753,6 +4738,7 @@
  #include "prims/jvmtiRedefineClasses.hpp"
 +#include "prims/jvmtiClassFileReconstituter.hpp"
  #include "prims/methodComparator.hpp"
+-#include "prims/methodHandles.hpp"
  #include "runtime/deoptimization.hpp"
  #include "runtime/relocator.hpp"
  #include "utilities/bitMap.inline.hpp"
@@ -5115,27 +5101,10 @@
 +    if (_class_defs[i].class_byte_count == 0) RC_ABORT(JVMTI_ERROR_INVALID_CLASS_FORMAT);
 +    if (_class_defs[i].class_bytes == NULL) RC_ABORT(JVMTI_ERROR_NULL_POINTER);
 +  }
- 
--      if (scratch_i != *merge_cp_length_p) {
--        // The new entry in *merge_cp_p is at a different index than
--        // the new entry in scratch_cp so we need to map the index values.
--        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
--      }
--      (*merge_cp_length_p)++;
--    } break;
++
 +  return true;
 +}
- 
--    // this is an indirect CP entry so it needs special handling
--    case JVM_CONSTANT_NameAndType:
--    {
--      int name_ref_i = scratch_cp->name_ref_index_at(scratch_i);
--      int new_name_ref_i = 0;
--      bool match = (name_ref_i < *merge_cp_length_p) &&
--        scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i,
--          THREAD);
--      if (!match) {
--        // forward reference in *merge_cp_p or not a direct match
++
 +jvmtiError VM_RedefineClasses::check_exception() const {
 +  Thread* THREAD = Thread::current();
 +  if (HAS_PENDING_EXCEPTION) {
@@ -5165,25 +5134,7 @@
 +      return JVMTI_ERROR_FAILS_VERIFICATION;
 +    }
 +  }
- 
--        int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p,
--          THREAD);
--        if (found_i != 0) {
--          guarantee(found_i != name_ref_i,
--            "compare_entry_to() and find_matching_entry() do not agree");
--
--          // Found a matching entry somewhere else in *merge_cp_p so
--          // just need a mapping entry.
--          new_name_ref_i = found_i;
--          map_index(scratch_cp, name_ref_i, found_i);
--        } else {
--          // no match found so we have to append this entry to *merge_cp_p
--          append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p,
--            THREAD);
--          // The above call to append_entry() can only append one entry
--          // so the post call query of *merge_cp_length_p is only for
--          // the sake of consistency.
--          new_name_ref_i = *merge_cp_length_p - 1;
++
 +  return JVMTI_ERROR_NONE;
 +}
 +
@@ -5204,7 +5155,11 @@
 +      (int)err));
 +    return err;
 +  }
-+
+ 
+-      if (scratch_i != *merge_cp_length_p) {
+-        // The new entry in *merge_cp_p is at a different index than
+-        // the new entry in scratch_cp so we need to map the index values.
+-        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
 +
 +  JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current());
 +
@@ -5302,40 +5257,82 @@
 +        while (subklass != NULL) {
 +          assert(subklass->new_version() == NULL, "Most recent version of class!");
 +          subklass = subklass->next_sibling();
-         }
++        }
 +      } else {
 +        // This can happen for reflection generated classes.. ?
 +        CLEAR_PENDING_EXCEPTION;
        }
+-      (*merge_cp_length_p)++;
+-    } break;
 +    }
  
+-    // this is an indirect CP entry so it needs special handling
+-    case JVM_CONSTANT_NameAndType:
+-    {
+-      int name_ref_i = scratch_cp->name_ref_index_at(scratch_i);
+-      int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p,
+-                                                         merge_cp_length_p, THREAD);
+-
 -      int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i);
--      int new_signature_ref_i = 0;
--      match = (signature_ref_i < *merge_cp_length_p) &&
--        scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p,
--          signature_ref_i, THREAD);
--      if (!match) {
--        // forward reference in *merge_cp_p or not a direct match
--
--        int found_i = scratch_cp->find_matching_entry(signature_ref_i,
--          *merge_cp_p, THREAD);
--        if (found_i != 0) {
--          guarantee(found_i != signature_ref_i,
--            "compare_entry_to() and find_matching_entry() do not agree");
--
--          // Found a matching entry somewhere else in *merge_cp_p so
--          // just need a mapping entry.
--          new_signature_ref_i = found_i;
--          map_index(scratch_cp, signature_ref_i, found_i);
--        } else {
--          // no match found so we have to append this entry to *merge_cp_p
--          append_entry(scratch_cp, signature_ref_i, merge_cp_p,
--            merge_cp_length_p, THREAD);
--          // The above call to append_entry() can only append one entry
--          // so the post call query of *merge_cp_length_p is only for
--          // the sake of consistency.
--          new_signature_ref_i = *merge_cp_length_p - 1;
--        }
+-      int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i,
+-                                                              merge_cp_p, merge_cp_length_p,
+-                                                              THREAD);
+-
+-      // If the referenced entries already exist in *merge_cp_p, then
+-      // both new_name_ref_i and new_signature_ref_i will both be 0.
+-      // In that case, all we are appending is the current entry.
+-      if (new_name_ref_i != name_ref_i) {
+-        RC_TRACE(0x00080000,
+-          ("NameAndType entry@%d name_ref_index change: %d to %d",
+-          *merge_cp_length_p, name_ref_i, new_name_ref_i));
+-      }
+-      if (new_signature_ref_i != signature_ref_i) {
+-        RC_TRACE(0x00080000,
+-          ("NameAndType entry@%d signature_ref_index change: %d to %d",
+-          *merge_cp_length_p, signature_ref_i, new_signature_ref_i));
+-      }
+-
+-      (*merge_cp_p)->name_and_type_at_put(*merge_cp_length_p,
+-        new_name_ref_i, new_signature_ref_i);
+-      if (scratch_i != *merge_cp_length_p) {
+-        // The new entry in *merge_cp_p is at a different index than
+-        // the new entry in scratch_cp so we need to map the index values.
+-        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+-      }
+-      (*merge_cp_length_p)++;
+-    } break;
+-
+-    // this is a double-indirect CP entry so it needs special handling
+-    case JVM_CONSTANT_Fieldref:           // fall through
+-    case JVM_CONSTANT_InterfaceMethodref: // fall through
+-    case JVM_CONSTANT_Methodref:
+-    {
+-      int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i);
+-      int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i,
+-                                                          merge_cp_p, merge_cp_length_p, THREAD);
+-      int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
+-      int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i,
+-                                                          merge_cp_p, merge_cp_length_p, THREAD);
+-
+-      const char *entry_name;
+-      switch (scratch_cp->tag_at(scratch_i).value()) {
+-      case JVM_CONSTANT_Fieldref:
+-        entry_name = "Fieldref";
+-        (*merge_cp_p)->field_at_put(*merge_cp_length_p, new_klass_ref_i,
+-          new_name_and_type_ref_i);
+-        break;
+-      case JVM_CONSTANT_InterfaceMethodref:
+-        entry_name = "IFMethodref";
+-        (*merge_cp_p)->interface_method_at_put(*merge_cp_length_p,
+-          new_klass_ref_i, new_name_and_type_ref_i);
+-        break;
+-      case JVM_CONSTANT_Methodref:
+-        entry_name = "Methodref";
+-        (*merge_cp_p)->method_at_put(*merge_cp_length_p, new_klass_ref_i,
+-          new_name_and_type_ref_i);
+-        break;
+-      default:
+-        guarantee(false, "bad switch");
 +#endif
 +
 +    if (RC_TRACE_ENABLED(0x00000001)) {
@@ -5344,18 +5341,9 @@
 +         new_class->name()->as_C_string(),
 +         new_class->layout_helper(),
 +         the_class->layout_helper()));
-       }
++      }
 +    }
- 
--      // If the referenced entries already exist in *merge_cp_p, then
--      // both new_name_ref_i and new_signature_ref_i will both be 0.
--      // In that case, all we are appending is the current entry.
--      if (new_name_ref_i == 0) {
--        new_name_ref_i = name_ref_i;
--      } else {
--        RC_TRACE(0x00080000,
--          ("NameAndType entry@%d name_ref_index change: %d to %d",
--          *merge_cp_length_p, name_ref_i, new_name_ref_i));
++
 +    // Set the new version of the class
 +    new_class->set_revision_number(_revision_number);
 +    new_class->set_redefinition_index(i);
@@ -5375,66 +5363,30 @@
 +      if (allowed != JVMTI_ERROR_NONE) {
 +        RC_TRACE(0x00000001, ("Error redefinition not allowed!"));
 +        result = allowed;
-+        break;
+         break;
        }
--      if (new_signature_ref_i == 0) {
--        new_signature_ref_i = signature_ref_i;
--      } else {
++      redefinition_flags = Klass::ModifyClass;
++    }
++
++    if (new_class->super() != NULL) {
++      redefinition_flags = redefinition_flags | new_class->super()->klass_part()->redefinition_flags();
++    }
+ 
+-      if (klass_ref_i != new_klass_ref_i) {
+-        RC_TRACE(0x00080000, ("%s entry@%d class_index changed: %d to %d",
+-          entry_name, *merge_cp_length_p, klass_ref_i, new_klass_ref_i));
+-      }
+-      if (name_and_type_ref_i != new_name_and_type_ref_i) {
 -        RC_TRACE(0x00080000,
--          ("NameAndType entry@%d signature_ref_index change: %d to %d",
--          *merge_cp_length_p, signature_ref_i, new_signature_ref_i));
+-          ("%s entry@%d name_and_type_index changed: %d to %d",
+-          entry_name, *merge_cp_length_p, name_and_type_ref_i,
+-          new_name_and_type_ref_i));
 -      }
 -
--      (*merge_cp_p)->name_and_type_at_put(*merge_cp_length_p,
--        new_name_ref_i, new_signature_ref_i);
 -      if (scratch_i != *merge_cp_length_p) {
 -        // The new entry in *merge_cp_p is at a different index than
 -        // the new entry in scratch_cp so we need to map the index values.
 -        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
--      }
--      (*merge_cp_length_p)++;
--    } break;
--
--    // this is a double-indirect CP entry so it needs special handling
--    case JVM_CONSTANT_Fieldref:           // fall through
--    case JVM_CONSTANT_InterfaceMethodref: // fall through
--    case JVM_CONSTANT_Methodref:
--    {
--      int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i);
--      int new_klass_ref_i = 0;
--      bool match = (klass_ref_i < *merge_cp_length_p) &&
--        scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i,
--          THREAD);
--      if (!match) {
--        // forward reference in *merge_cp_p or not a direct match
-+      redefinition_flags = Klass::ModifyClass;
-+    }
- 
--        int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p,
--          THREAD);
--        if (found_i != 0) {
--          guarantee(found_i != klass_ref_i,
--            "compare_entry_to() and find_matching_entry() do not agree");
--
--          // Found a matching entry somewhere else in *merge_cp_p so
--          // just need a mapping entry.
--          new_klass_ref_i = found_i;
--          map_index(scratch_cp, klass_ref_i, found_i);
--        } else {
--          // no match found so we have to append this entry to *merge_cp_p
--          append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p,
--            THREAD);
--          // The above call to append_entry() can only append one entry
--          // so the post call query of *merge_cp_length_p is only for
--          // the sake of consistency. Without the optimization where we
--          // use JVM_CONSTANT_UnresolvedClass, then up to two entries
--          // could be appended.
--          new_klass_ref_i = *merge_cp_length_p - 1;
--        }
-+    if (new_class->super() != NULL) {
-+      redefinition_flags = redefinition_flags | new_class->super()->klass_part()->redefinition_flags();
-+    }
-+
 +    for (int j=0; j<new_class->local_interfaces()->length(); j++) {
 +      redefinition_flags = redefinition_flags | ((klassOop)new_class->local_interfaces()->obj_at(j))->klass_part()->redefinition_flags();
 +    }
@@ -5456,44 +5408,53 @@
 +        fd_new.initialize(new_class(), fs.index());
 +        fd_old.initialize(new_class->old_version(), fs.index());
 +        transfer_special_access_flags(&fd_old, &fd_new);
-+      }
+       }
+-      (*merge_cp_length_p)++;
+-    } break;
 +    }
-+
+ 
+-    // this is an indirect CP entry so it needs special handling
+-    case JVM_CONSTANT_MethodType:
+-    {
+-      int ref_i = scratch_cp->method_type_index_at(scratch_i);
+-      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+-                                                    merge_cp_length_p, THREAD);
+-      if (new_ref_i != ref_i) {
+-        RC_TRACE(0x00080000,
+-                 ("MethodType entry@%d ref_index change: %d to %d",
+-                  *merge_cp_length_p, ref_i, new_ref_i));
+-      }
+-      (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i);
+-      if (scratch_i != *merge_cp_length_p) {
+-        // The new entry in *merge_cp_p is at a different index than
+-        // the new entry in scratch_cp so we need to map the index values.
+-        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
 +    if (RC_TRACE_ENABLED(0x00000008)) {
 +      if (new_class->super() != NULL) {
 +        RC_TRACE(0x00000008, ("Super class is %s",
 +          new_class->super()->klass_part()->name()->as_C_string()));
        }
+-      (*merge_cp_length_p)++;
+-    } break;
 +    }
  
--      int name_and_type_ref_i =
--        scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
--      int new_name_and_type_ref_i = 0;
--      match = (name_and_type_ref_i < *merge_cp_length_p) &&
--        scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p,
--          name_and_type_ref_i, THREAD);
--      if (!match) {
--        // forward reference in *merge_cp_p or not a direct match
--
--        int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i,
--          *merge_cp_p, THREAD);
--        if (found_i != 0) {
--          guarantee(found_i != name_and_type_ref_i,
--            "compare_entry_to() and find_matching_entry() do not agree");
--
--          // Found a matching entry somewhere else in *merge_cp_p so
--          // just need a mapping entry.
--          new_name_and_type_ref_i = found_i;
--          map_index(scratch_cp, name_and_type_ref_i, found_i);
--        } else {
--          // no match found so we have to append this entry to *merge_cp_p
--          append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p,
--            merge_cp_length_p, THREAD);
--          // The above call to append_entry() can append more than
--          // one entry so the post call query of *merge_cp_length_p
--          // is required in order to get the right index for the
--          // JVM_CONSTANT_NameAndType entry.
--          new_name_and_type_ref_i = *merge_cp_length_p - 1;
+-    // this is an indirect CP entry so it needs special handling
+-    case JVM_CONSTANT_MethodHandle:
+-    {
+-      int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i);
+-      int ref_i = scratch_cp->method_handle_index_at(scratch_i);
+-      int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+-                                                    merge_cp_length_p, THREAD);
+-      if (new_ref_i != ref_i) {
+-        RC_TRACE(0x00080000,
+-                 ("MethodHandle entry@%d ref_index change: %d to %d",
+-                  *merge_cp_length_p, ref_i, new_ref_i));
+-      }
+-      (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i);
+-      if (scratch_i != *merge_cp_length_p) {
+-        // The new entry in *merge_cp_p is at a different index than
+-        // the new entry in scratch_cp so we need to map the index values.
+-        map_index(scratch_cp, scratch_i, *merge_cp_length_p);
 +#ifdef ASSERT
 +    assert(new_class->super() == NULL || new_class->super()->klass_part()->new_version() == NULL, "Super klass must be newest version!");
 +
@@ -5535,60 +5496,34 @@
 +          }
 +
 +          cur_klass = cur_klass->next_sibling();
-         }
-       }
- 
--      // If the referenced entries already exist in *merge_cp_p, then
--      // both new_klass_ref_i and new_name_and_type_ref_i will both be
--      // 0. In that case, all we are appending is the current entry.
--      if (new_klass_ref_i == 0) {
--        new_klass_ref_i = klass_ref_i;
--      }
--      if (new_name_and_type_ref_i == 0) {
--        new_name_and_type_ref_i = name_and_type_ref_i;
--      }
--
--      const char *entry_name;
--      switch (scratch_cp->tag_at(scratch_i).value()) {
--      case JVM_CONSTANT_Fieldref:
--        entry_name = "Fieldref";
--        (*merge_cp_p)->field_at_put(*merge_cp_length_p, new_klass_ref_i,
--          new_name_and_type_ref_i);
--        break;
--      case JVM_CONSTANT_InterfaceMethodref:
--        entry_name = "IFMethodref";
--        (*merge_cp_p)->interface_method_at_put(*merge_cp_length_p,
--          new_klass_ref_i, new_name_and_type_ref_i);
--        break;
--      case JVM_CONSTANT_Methodref:
--        entry_name = "Methodref";
--        (*merge_cp_p)->method_at_put(*merge_cp_length_p, new_klass_ref_i,
--          new_name_and_type_ref_i);
--        break;
--      default:
--        guarantee(false, "bad switch");
--        break;
-+      int new_count = all_affected_klasses.length() - 1 - i;
-+      if (new_count != 0) {
-+
-+        unlock_threads();
-+        RC_TRACE(0x00000001, ("Found new number of affected classes: %d",
-+          new_count));
++        }
        }
-+    }
-+  }
+-      (*merge_cp_length_p)++;
+-    } break;
  
--      if (klass_ref_i != new_klass_ref_i) {
--        RC_TRACE(0x00080000, ("%s entry@%d class_index changed: %d to %d",
--          entry_name, *merge_cp_length_p, klass_ref_i, new_klass_ref_i));
+-    // this is an indirect CP entry so it needs special handling
+-    case JVM_CONSTANT_InvokeDynamic:
+-    {
+-      // Index of the bootstrap specifier in the operands array
+-      int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
+-      int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p,
+-                                                    merge_cp_length_p, THREAD);
+-      // The bootstrap method NameAndType_info index
+-      int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
+-      int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
+-                                                    merge_cp_length_p, THREAD);
+-      if (new_bs_i != old_bs_i) {
+-        RC_TRACE(0x00080000,
+-                 ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d",
+-                  *merge_cp_length_p, old_bs_i, new_bs_i));
 -      }
--      if (name_and_type_ref_i != new_name_and_type_ref_i) {
+-      if (new_ref_i != old_ref_i) {
 -        RC_TRACE(0x00080000,
--          ("%s entry@%d name_and_type_index changed: %d to %d",
--          entry_name, *merge_cp_length_p, name_and_type_ref_i,
--          new_name_and_type_ref_i));
+-                 ("InvokeDynamic entry@%d name_and_type_index change: %d to %d",
+-                  *merge_cp_length_p, old_ref_i, new_ref_i));
 -      }
 -
+-      (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
 -      if (scratch_i != *merge_cp_length_p) {
 -        // The new entry in *merge_cp_p is at a different index than
 -        // the new entry in scratch_cp so we need to map the index values.
@@ -5597,7 +5532,7 @@
 -      (*merge_cp_length_p)++;
 -    } break;
 -
--    // At this stage, Class or UnresolvedClass could be here, but not
+-   // At this stage, Class or UnresolvedClass could be here, but not
 -    // ClassIndex
 -    case JVM_CONSTANT_ClassIndex: // fall through
 -
@@ -5613,10 +5548,8 @@
 -    // At this stage JVM_CONSTANT_UnresolvedClassInError should not be
 -    // here
 -    case JVM_CONSTANT_UnresolvedClassInError: // fall through
-+  if (result != JVMTI_ERROR_NONE) {
-+    rollback();
-+    return result;
-+  }
++      int new_count = all_affected_klasses.length() - 1 - i;
++      if (new_count != 0) {
  
 -    default:
 -    {
@@ -5626,13 +5559,128 @@
 -    } break;
 -  } // end switch tag value
 -} // end append_entry()
+-
+-
+-int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp,
+-      int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+-
+-  int new_ref_i = ref_i;
+-  bool match = (ref_i < *merge_cp_length_p) &&
+-               scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD);
+-
+-  if (!match) {
+-    // forward reference in *merge_cp_p or not a direct match
+-    int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD);
+-    if (found_i != 0) {
+-      guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree");
+-      // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry.
+-      new_ref_i = found_i;
+-      map_index(scratch_cp, ref_i, found_i);
+-    } else {
+-      // no match found so we have to append this entry to *merge_cp_p
+-      append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD);
+-      // The above call to append_entry() can only append one entry
+-      // so the post call query of *merge_cp_length_p is only for
+-      // the sake of consistency.
+-      new_ref_i = *merge_cp_length_p - 1;
+-    }
+-  }
+-
+-  return new_ref_i;
+-} // end find_or_append_indirect_entry()
+-
+-
+-// Append a bootstrap specifier into the merge_cp operands that is semantically equal
+-// to the scratch_cp operands bootstrap specifier passed by the old_bs_i index.
+-// Recursively append new merge_cp entries referenced by the new bootstrap specifier.
+-void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i,
+-       constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+-
+-  int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i);
+-  int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
+-                                                merge_cp_length_p, THREAD);
+-  if (new_ref_i != old_ref_i) {
+-    RC_TRACE(0x00080000,
+-             ("operands entry@%d bootstrap method ref_index change: %d to %d",
+-              _operands_cur_length, old_ref_i, new_ref_i));
+-  }
+-
+-  typeArrayOop merge_ops = (*merge_cp_p)->operands();
+-  int new_bs_i = _operands_cur_length;
+-  // We have _operands_cur_length == 0 when the merge_cp operands is empty yet.
+-  // However, the operand_offset_at(0) was set in the extend_operands() call.
+-  int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0)
+-                                 : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1);
+-  int argc     = scratch_cp->operand_argument_count_at(old_bs_i);
+-
+-  constantPoolOopDesc::operand_offset_at_put(merge_ops, _operands_cur_length, new_base);
+-  merge_ops->short_at_put(new_base++, new_ref_i);
+-  merge_ops->short_at_put(new_base++, argc);
+-
+-  for (int i = 0; i < argc; i++) {
+-    int old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i);
+-    int new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p,
+-                                                      merge_cp_length_p, THREAD);
+-    merge_ops->short_at_put(new_base++, new_arg_ref_i);
+-    if (new_arg_ref_i != old_arg_ref_i) {
+-      RC_TRACE(0x00080000,
+-               ("operands entry@%d bootstrap method argument ref_index change: %d to %d",
+-                _operands_cur_length, old_arg_ref_i, new_arg_ref_i));
+-    }
+-  }
+-  if (old_bs_i != _operands_cur_length) {
+-    // The bootstrap specifier in *merge_cp_p is at a different index than
+-    // that in scratch_cp so we need to map the index values.
+-    map_operand_index(old_bs_i, new_bs_i);
+-  }
+-  _operands_cur_length++;
+-} // end append_operand()
+-
+-
+-int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp,
+-      int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+-
+-  int new_bs_i = old_bs_i; // bootstrap specifier index
+-  bool match = (old_bs_i < _operands_cur_length) &&
+-               scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i, THREAD);
+-
+-  if (!match) {
+-    // forward reference in *merge_cp_p or not a direct match
+-    int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p,
+-                                                    _operands_cur_length, THREAD);
+-    if (found_i != -1) {
+-      guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree");
+-      // found a matching operand somewhere else in *merge_cp_p so just need a mapping
+-      new_bs_i = found_i;
+-      map_operand_index(old_bs_i, found_i);
+-    } else {
+-      // no match found so we have to append this bootstrap specifier to *merge_cp_p
+-      append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD);
+-      new_bs_i = _operands_cur_length - 1;
++        unlock_threads();
++        RC_TRACE(0x00000001, ("Found new number of affected classes: %d",
++          new_count));
++      }
+     }
+   }
+-  return new_bs_i;
+-} // end find_or_append_operand()
+ 
++  if (result != JVMTI_ERROR_NONE) {
++    rollback();
++    return result;
++  }
++
 +  RC_TIMER_STOP(_timer_prologue);
 +  RC_TIMER_START(_timer_class_linking);
 +  // Link and verify new classes _after_ all classes have been updated in the system dictionary!
 +  for (int i=0; i<all_affected_klasses.length(); i++) {
 +    instanceKlassHandle the_class = all_affected_klasses.at(i);
 +    instanceKlassHandle new_class(the_class->new_version());
-+
+ 
+-void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) {
+-  if (merge_cp->operands() == NULL) {
+-    return;
 +    RC_TRACE(0x00000002, ("Linking class %d/%d %s",
 +      i,
 +      all_affected_klasses.length(),
@@ -5641,11 +5689,23 @@
 +
 +    result = check_exception();
 +    if (result != JVMTI_ERROR_NONE) break;
-+  }
+   }
+-  // Shrink the merge_cp operands
+-  merge_cp->shrink_operands(_operands_cur_length, CHECK);
 +  RC_TIMER_STOP(_timer_class_linking);
 +  RC_TIMER_START(_timer_prologue);
-+
-+  if (result != JVMTI_ERROR_NONE) {
+ 
+-  if (RC_TRACE_ENABLED(0x00040000)) {
+-    // don't want to loop unless we are tracing
+-    int count = 0;
+-    for (int i = 1; i < _operands_index_map_p->length(); i++) {
+-      int value = _operands_index_map_p->at(i);
+-      if (value != -1) {
+-        RC_TRACE_WITH_THREAD(0x00040000, THREAD,
+-          ("operands_index_map[%d]: old=%d new=%d", count, i, value));
+-        count++;
+-      }
++  if (result != JVMTI_ERROR_NONE) {
 +    rollback();
 +    return result;
 +  }
@@ -5658,7 +5718,7 @@
 +    assert(the_class->new_version() != NULL, "Must have been redefined");
 +    instanceKlassHandle new_version = instanceKlassHandle(THREAD, the_class->new_version());
 +    assert(new_version->new_version() == NULL, "Must be newest version");
- 
++
 +    if (!(new_version->super() == NULL || new_version->super()->klass_part()->new_version() == NULL)) {
 +      new_version()->print();
 +      new_version->super()->print();
@@ -5706,20 +5766,25 @@
 +  while (javaThread != NULL) {
 +    if (javaThread != Thread::current()) {
 +      javaThread->redefine_classes_mutex()->lock();
-+    }
+     }
 +    javaThread = javaThread->next();
-+  }
-+
-+
+   }
+-  // Clean-up
+-  _operands_index_map_p = NULL;
+-  _operands_cur_length = 0;
+-  _operands_index_map_count = 0;
+-} // end finalize_operands_merge()
+ 
+ 
+-void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class) {
+-  typeArrayOop save;
 +  RC_TRACE(0x00000002, ("Locked %d threads", cnt));
 +
 +  RC_TIMER_STOP(_timer_wait_for_locks);
 +}
 +
 +void VM_RedefineClasses::unlock_threads() {
- 
--void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class) {
--  typeArrayOop save;
++
 +  int cnt = 0;
 +  JavaThread *javaThread = Threads::first();
 +  Thread *thread = Thread::current();
@@ -5789,7 +5854,7 @@
    }
  
    // Check if the number, names and order of directly implemented interfaces are the same.
-@@ -539,8 +678,8 @@
+@@ -622,8 +678,8 @@
    }
    for (i = 0; i < n_intfs; i++) {
      if (Klass::cast((klassOop) k_interfaces->obj_at(i))->name() !=
@@ -5800,7 +5865,7 @@
      }
    }
  
-@@ -689,12 +828,8 @@
+@@ -772,12 +828,8 @@
              idnum_owner->set_method_idnum(new_num);
            }
            k_new_method->set_method_idnum(old_num);
@@ -5813,7 +5878,7 @@
        // advance to next pair of methods
        ++oi;
        ++ni;
-@@ -703,11 +838,11 @@
+@@ -786,11 +838,11 @@
        // method added, see if it is OK
        new_flags = (jushort) k_new_method->access_flags().get_flags();
        if ((new_flags & JVM_ACC_PRIVATE) == 0
@@ -5830,7 +5895,7 @@
        }
        {
          u2 num = the_class->next_method_idnum();
-@@ -722,24 +857,19 @@
+@@ -805,24 +857,19 @@
            idnum_owner->set_method_idnum(new_num);
          }
          k_new_method->set_method_idnum(num);
@@ -5860,7 +5925,7 @@
        ++oi; // advance to next old method
        break;
      default:
-@@ -750,2200 +880,1783 @@
+@@ -833,2254 +880,1783 @@
    return JVMTI_ERROR_NONE;
  }
  
@@ -5881,59 +5946,62 @@
 -    // happen if a corrupt annotation is processed.
 -    return 0;
 -  }
--
++  int result = Klass::NoRedefinition;
+ 
 -  int value = _index_map_p->at(old_index);
 -  if (value == -1) {
 -    // the old_index is not mapped
 -    return 0;
 -  }
-+  int result = Klass::NoRedefinition;
  
 -  return value;
 -} // end find_new_index()
  
- 
--// Returns true if the current mismatch is due to a resolved/unresolved
--// class pair. Otherwise, returns false.
--bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1,
--       int index1, constantPoolHandle cp2, int index2) {
 +  RC_TRACE(0x00000002, ("Comparing different class versions of class %s",
 +    new_class->name()->as_C_string()));
  
--  jbyte t1 = cp1->tag_at(index1).value();
--  if (t1 != JVM_CONSTANT_Class && t1 != JVM_CONSTANT_UnresolvedClass) {
--    return false;  // wrong entry type; not our special case
+-// Find new bootstrap specifier index value for old bootstrap specifier index
+-// value by seaching the index map. Returns zero (-1) if there is no mapped
+-// value for the old bootstrap specifier index.
+-int VM_RedefineClasses::find_new_operand_index(int old_index) {
+-  if (_operands_index_map_count == 0) {
+-    // map is empty so nothing can be found
+-    return -1;
 -  }
 +  assert(new_class->old_version() != NULL, "must have old version");
 +  instanceKlassHandle the_class(new_class->old_version());
  
--  jbyte t2 = cp2->tag_at(index2).value();
--  if (t2 != JVM_CONSTANT_Class && t2 != JVM_CONSTANT_UnresolvedClass) {
--    return false;  // wrong entry type; not our special case
+-  if (old_index == -1 || old_index >= _operands_index_map_p->length()) {
+-    // The old_index is out of range so it is not mapped.
+-    // This should not happen in regular constant pool merging use.
+-    return -1;
 +  // Check whether class is in the error init state.
 +  if (the_class->is_in_error_state()) {
 +    // TBD #5057930: special error code is needed in 1.6
 +    //result = Klass::union_redefinition_level(result, Klass::Invalid);
    }
  
--  if (t1 == t2) {
--    return false;  // not a mismatch; not our special case
--  }
+-  int value = _operands_index_map_p->at(old_index);
+-
+-  return value;
+-} // end find_new_operand_index()
+-
 +  int i;
  
--  char *s1 = cp1->klass_name_at(index1)->as_C_string();
--  char *s2 = cp2->klass_name_at(index2)->as_C_string();
--  if (strcmp(s1, s2) != 0) {
--    return false;  // strings don't match; not our special case
--  }
+-// Returns true if the current mismatch is due to a resolved/unresolved
+-// class pair. Otherwise, returns false.
+-bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1,
+-       int index1, constantPoolHandle cp2, int index2) {
 +  //////////////////////////////////////////////////////////////////////////////////////////////////////////
 +  // Check superclasses
 +  assert(new_class->super() == NULL || new_class->super()->klass_part()->is_newest_version(), "");
 +  if (the_class->super() != new_class->super()) {
 +    // Super class changed
  
--  return true;  // made it through the gauntlet; this is our special case
--} // end is_unresolved_class_mismatch()
+-  jbyte t1 = cp1->tag_at(index1).value();
+-  if (t1 != JVM_CONSTANT_Class && t1 != JVM_CONSTANT_UnresolvedClass) {
+-    return false;  // wrong entry type; not our special case
+-  }
 +    klassOop cur_klass = the_class->super();
 +    while (cur_klass != NULL) {
 +      if (!new_class->is_subclass_of(cur_klass->klass_part()->newest_version())) {
@@ -5941,6 +6009,10 @@
 +          cur_klass->klass_part()->name()->as_C_string()));
 +        result = result | Klass::RemoveSuperType | Klass::ModifyInstances | Klass::ModifyClass;
  
+-  jbyte t2 = cp2->tag_at(index2).value();
+-  if (t2 != JVM_CONSTANT_Class && t2 != JVM_CONSTANT_UnresolvedClass) {
+-    return false;  // wrong entry type; not our special case
+-  }
 +        if (!cur_klass->klass_part()->has_subtype_changed()) {
 +          RC_TRACE(0x00000002, ("Subtype changed of class %s",
 +            cur_klass->klass_part()->name()->as_C_string()));
@@ -5948,16 +6020,16 @@
 +        }
 +      }
  
--// Returns true if the current mismatch is due to a resolved/unresolved
--// string pair. Otherwise, returns false.
--bool VM_RedefineClasses::is_unresolved_string_mismatch(constantPoolHandle cp1,
--       int index1, constantPoolHandle cp2, int index2) {
+-  if (t1 == t2) {
+-    return false;  // not a mismatch; not our special case
+-  }
 +      cur_klass = cur_klass->klass_part()->super();
 +    }
  
--  jbyte t1 = cp1->tag_at(index1).value();
--  if (t1 != JVM_CONSTANT_String && t1 != JVM_CONSTANT_UnresolvedString) {
--    return false;  // wrong entry type; not our special case
+-  char *s1 = cp1->klass_name_at(index1)->as_C_string();
+-  char *s2 = cp2->klass_name_at(index2)->as_C_string();
+-  if (strcmp(s1, s2) != 0) {
+-    return false;  // strings don't match; not our special case
 +    cur_klass = new_class->super();
 +    while (cur_klass != NULL) {
 +      if (!the_class->is_subclass_of(cur_klass->klass_part()->old_version())) {
@@ -5969,15 +6041,20 @@
 +    }
    }
  
--  jbyte t2 = cp2->tag_at(index2).value();
--  if (t2 != JVM_CONSTANT_String && t2 != JVM_CONSTANT_UnresolvedString) {
--    return false;  // wrong entry type; not our special case
--  }
+-  return true;  // made it through the gauntlet; this is our special case
+-} // end is_unresolved_class_mismatch()
+-
 +  //////////////////////////////////////////////////////////////////////////////////////////////////////////
 +  // Check interfaces
  
--  if (t1 == t2) {
--    return false;  // not a mismatch; not our special case
+-// Returns true if the current mismatch is due to a resolved/unresolved
+-// string pair. Otherwise, returns false.
+-bool VM_RedefineClasses::is_unresolved_string_mismatch(constantPoolHandle cp1,
+-       int index1, constantPoolHandle cp2, int index2) {
+-
+-  jbyte t1 = cp1->tag_at(index1).value();
+-  if (t1 != JVM_CONSTANT_String && t1 != JVM_CONSTANT_UnresolvedString) {
+-    return false;  // wrong entry type; not our special case
 +  // Interfaces removed?
 +  objArrayOop old_interfaces = the_class->transitive_interfaces();
 +  for (i = 0; i<old_interfaces->length(); i++) {
@@ -5995,10 +6072,9 @@
 +    }
    }
  
--  char *s1 = cp1->string_at_noresolve(index1);
--  char *s2 = cp2->string_at_noresolve(index2);
--  if (strcmp(s1, s2) != 0) {
--    return false;  // strings don't match; not our special case
+-  jbyte t2 = cp2->tag_at(index2).value();
+-  if (t2 != JVM_CONSTANT_String && t2 != JVM_CONSTANT_UnresolvedString) {
+-    return false;  // wrong entry type; not our special case
 +  // Interfaces added?
 +  objArrayOop new_interfaces = new_class->transitive_interfaces();
 +  for (i = 0; i<new_interfaces->length(); i++) {
@@ -6009,22 +6085,32 @@
 +    }
    }
  
--  return true;  // made it through the gauntlet; this is our special case
--} // end is_unresolved_string_mismatch()
+-  if (t1 == t2) {
+-    return false;  // not a mismatch; not our special case
+-  }
  
+-  char *s1 = cp1->string_at_noresolve(index1);
+-  char *s2 = cp2->string_at_noresolve(index2);
+-  if (strcmp(s1, s2) != 0) {
+-    return false;  // strings don't match; not our special case
 +  // Check whether class modifiers are the same.
 +  jushort old_flags = (jushort) the_class->access_flags().get_flags();
 +  jushort new_flags = (jushort) new_class->access_flags().get_flags();
 +  if (old_flags != new_flags) {
 +    // TODO (tw): Can this have any effects?
-+  }
+   }
  
+-  return true;  // made it through the gauntlet; this is our special case
+-} // end is_unresolved_string_mismatch()
+-
+-
 -jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
 -  // For consistency allocate memory using os::malloc wrapper.
 -  _scratch_classes = (instanceKlassHandle *)
 -    os::malloc(sizeof(instanceKlassHandle) * _class_count, mtInternal);
 -  if (_scratch_classes == NULL) {
 -    return JVMTI_ERROR_OUT_OF_MEMORY;
+-  }
 +  // Check if the number, names, types and order of fields declared in these classes
 +  // are the same.
 +  JavaFieldStream old_fs(the_class);
@@ -6048,7 +6134,7 @@
 +    if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
 +      result = result | Klass::ModifyInstances;
 +    }
-   }
++  }
  
 -  ResourceMark rm(THREAD);
 +  if (!old_fs.done() || !new_fs.done()) {
@@ -6576,93 +6662,23 @@
 -    // old_index is already mapped
 -    return;
 -  }
--
++  public:
+ 
 -  if (old_index == new_index) {
 -    // no mapping is needed
 -    return;
 -  }
--
--  _index_map_p->at_put(old_index, new_index);
--  _index_map_count++;
--
--  RC_TRACE(0x00040000, ("mapped tag %d at index %d to %d",
--    scratch_cp->tag_at(old_index).value(), old_index, new_index));
--} // end map_index()
--
--
--// Merge old_cp and scratch_cp and return the results of the merge via
--// merge_cp_p. The number of entries in *merge_cp_p is returned via
--// merge_cp_length_p. The entries in old_cp occupy the same locations
--// in *merge_cp_p. Also creates a map of indices from entries in
--// scratch_cp to the corresponding entry in *merge_cp_p. Index map
--// entries are only created for entries in scratch_cp that occupy a
--// different location in *merged_cp_p.
--bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp,
--       constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
--       int *merge_cp_length_p, TRAPS) {
--
--  if (merge_cp_p == NULL) {
--    assert(false, "caller must provide scatch constantPool");
--    return false; // robustness
--  }
--  if (merge_cp_length_p == NULL) {
--    assert(false, "caller must provide scatch CP length");
--    return false; // robustness
--  }
--  // Worst case we need old_cp->length() + scratch_cp()->length(),
--  // but the caller might be smart so make sure we have at least
--  // the minimum.
--  if ((*merge_cp_p)->length() < old_cp->length()) {
--    assert(false, "merge area too small");
--    return false; // robustness
--  }
--
--  RC_TRACE_WITH_THREAD(0x00010000, THREAD,
--    ("old_cp_len=%d, scratch_cp_len=%d", old_cp->length(),
--    scratch_cp->length()));
-+  public:
- 
--  {
--    // Pass 0:
--    // The old_cp is copied to *merge_cp_p; this means that any code
--    // using old_cp does not have to change. This work looks like a
--    // perfect fit for constantPoolOop::copy_cp_to(), but we need to
--    // handle one special case:
--    // - revert JVM_CONSTANT_Class to JVM_CONSTANT_UnresolvedClass
--    // This will make verification happy.
--
--    int old_i;  // index into old_cp
--
--    // index zero (0) is not used in constantPools
--    for (old_i = 1; old_i < old_cp->length(); old_i++) {
--      // leave debugging crumb
--      jbyte old_tag = old_cp->tag_at(old_i).value();
--      switch (old_tag) {
--      case JVM_CONSTANT_Class:
--      case JVM_CONSTANT_UnresolvedClass:
--        // revert the copy to JVM_CONSTANT_UnresolvedClass
--        // May be resolving while calling this so do the same for
--        // JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition)
--        (*merge_cp_p)->unresolved_klass_at_put(old_i,
--          old_cp->klass_name_at(old_i));
--        break;
 +    GrowableArray< Pair<int, klassOop> > *_arr;
  
--      case JVM_CONSTANT_Double:
--      case JVM_CONSTANT_Long:
--        // just copy the entry to *merge_cp_p, but double and long take
--        // two constant pool entries
--        constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
--        old_i++;
--        break;
+-  _index_map_p->at_put(old_index, new_index);
+-  _index_map_count++;
 +    MyFieldClosure(GrowableArray< Pair<int, klassOop> > *arr) {
 +      _arr = arr;
 +    }
  
--      default:
--        // just copy the entry to *merge_cp_p
--        constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
--        break;
+-  RC_TRACE(0x00040000, ("mapped tag %d at index %d to %d",
+-    scratch_cp->tag_at(old_index).value(), old_index, new_index));
+-} // end map_index()
 +    virtual void do_field(fieldDescriptor* fd) {
 +      if (fd->field_type() == T_OBJECT) {
 +        Symbol* signature = fd->signature();
@@ -6677,12 +6693,17 @@
 +            _arr->append(Pair<int, klassOop>(fd->offset(), field_klass->klass_part()->newest_version()));
 +          }
 +        }
-+
+ 
 +        // Array fields can never be a problem!
-       }
--    } // end for each old_cp entry
++      }
 +    }
-+
+ 
+-// Map old_index to new_index as needed.
+-void VM_RedefineClasses::map_operand_index(int old_index, int new_index) {
+-  if (find_new_operand_index(old_index) != -1) {
+-    // old_index is already mapped
+-    return;
+-  }
 +    bool is_field_dangerous(Symbol* klass_name, fieldDescriptor *fd, klassOop &field_klass) {
 +      field_klass = SystemDictionary::find(klass_name, fd->field_holder()->klass_part()->class_loader(),
 +              fd->field_holder()->klass_part()->protection_domain(), Thread::current());
@@ -6698,9 +6719,9 @@
 +    }
 +  };
  
--    // We don't need to sanity check that *merge_cp_length_p is within
--    // *merge_cp_p bounds since we have the minimum on-entry check above.
--    (*merge_cp_length_p) = old_i;
+-  if (old_index == new_index) {
+-    // no mapping is needed
+-    return;
 +  MyFieldClosure fieldClosure(&type_check_information);
 +  cur_instance_klass->do_nonstatic_fields(&fieldClosure);
 +
@@ -6710,242 +6731,54 @@
    }
 +}
  
--  // merge_cp_len should be the same as old_cp->length() at this point
--  // so this trace message is really a "warm-and-breathing" message.
--  RC_TRACE_WITH_THREAD(0x00020000, THREAD,
--    ("after pass 0: merge_cp_len=%d", *merge_cp_length_p));
+-  _operands_index_map_p->at_put(old_index, new_index);
+-  _operands_index_map_count++;
 +bool VM_RedefineClasses::check_field_value_types() {
  
--  int scratch_i;  // index into scratch_cp
--  {
--    // Pass 1a:
--    // Compare scratch_cp entries to the old_cp entries that we have
--    // already copied to *merge_cp_p. In this pass, we are eliminating
--    // exact duplicates (matching entry at same index) so we only
--    // compare entries in the common indice range.
--    int increment = 1;
--    int pass1a_length = MIN2(old_cp->length(), scratch_cp->length());
--    for (scratch_i = 1; scratch_i < pass1a_length; scratch_i += increment) {
--      switch (scratch_cp->tag_at(scratch_i).value()) {
--      case JVM_CONSTANT_Double:
--      case JVM_CONSTANT_Long:
--        // double and long take two constant pool entries
--        increment = 2;
--        break;
+-  RC_TRACE(0x00040000, ("mapped bootstrap specifier at index %d to %d", old_index, new_index));
+-} // end map_index()
 +  Thread *THREAD = Thread::current();
 +  class CheckFieldTypesClosure : public ObjectClosure {
  
--      default:
--        increment = 1;
--        break;
--      }
 +  private:
  
--      bool match = scratch_cp->compare_entry_to(scratch_i, *merge_cp_p,
--        scratch_i, CHECK_0);
--      if (match) {
--        // found a match at the same index so nothing more to do
--        continue;
--      } else if (is_unresolved_class_mismatch(scratch_cp, scratch_i,
--                                              *merge_cp_p, scratch_i)) {
--        // The mismatch in compare_entry_to() above is because of a
--        // resolved versus unresolved class entry at the same index
--        // with the same string value. Since Pass 0 reverted any
--        // class entries to unresolved class entries in *merge_cp_p,
--        // we go with the unresolved class entry.
--        continue;
--      } else if (is_unresolved_string_mismatch(scratch_cp, scratch_i,
--                                               *merge_cp_p, scratch_i)) {
--        // The mismatch in compare_entry_to() above is because of a
--        // resolved versus unresolved string entry at the same index
--        // with the same string value. We can live with whichever
--        // happens to be at scratch_i in *merge_cp_p.
--        continue;
--      }
--
--      int found_i = scratch_cp->find_matching_entry(scratch_i, *merge_cp_p,
--        CHECK_0);
--      if (found_i != 0) {
--        guarantee(found_i != scratch_i,
--          "compare_entry_to() and find_matching_entry() do not agree");
--
--        // Found a matching entry somewhere else in *merge_cp_p so
--        // just need a mapping entry.
--        map_index(scratch_cp, scratch_i, found_i);
--        continue;
--      }
--
--      // The find_matching_entry() call above could fail to find a match
--      // due to a resolved versus unresolved class or string entry situation
--      // like we solved above with the is_unresolved_*_mismatch() calls.
--      // However, we would have to call is_unresolved_*_mismatch() over
--      // all of *merge_cp_p (potentially) and that doesn't seem to be
--      // worth the time.
--
--      // No match found so we have to append this entry and any unique
--      // referenced entries to *merge_cp_p.
--      append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p,
--        CHECK_0);
--    }
--  }
--
--  RC_TRACE_WITH_THREAD(0x00020000, THREAD,
--    ("after pass 1a: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
--    *merge_cp_length_p, scratch_i, _index_map_count));
--
--  if (scratch_i < scratch_cp->length()) {
--    // Pass 1b:
--    // old_cp is smaller than scratch_cp so there are entries in
--    // scratch_cp that we have not yet processed. We take care of
--    // those now.
--    int increment = 1;
--    for (; scratch_i < scratch_cp->length(); scratch_i += increment) {
--      switch (scratch_cp->tag_at(scratch_i).value()) {
--      case JVM_CONSTANT_Double:
--      case JVM_CONSTANT_Long:
--        // double and long take two constant pool entries
--        increment = 2;
--        break;
+-// Merge old_cp and scratch_cp and return the results of the merge via
+-// merge_cp_p. The number of entries in *merge_cp_p is returned via
+-// merge_cp_length_p. The entries in old_cp occupy the same locations
+-// in *merge_cp_p. Also creates a map of indices from entries in
+-// scratch_cp to the corresponding entry in *merge_cp_p. Index map
+-// entries are only created for entries in scratch_cp that occupy a
+-// different location in *merged_cp_p.
+-bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp,
+-       constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
+-       int *merge_cp_length_p, TRAPS) {
 +    bool _result;
  
--      default:
--        increment = 1;
--        break;
--      }
-+  public:
- 
--      int found_i =
--        scratch_cp->find_matching_entry(scratch_i, *merge_cp_p, CHECK_0);
--      if (found_i != 0) {
--        // Found a matching entry somewhere else in *merge_cp_p so
--        // just need a mapping entry.
--        map_index(scratch_cp, scratch_i, found_i);
--        continue;
--      }
--
--      // No match found so we have to append this entry and any unique
--      // referenced entries to *merge_cp_p.
--      append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p,
--        CHECK_0);
--    }
--
--    RC_TRACE_WITH_THREAD(0x00020000, THREAD,
--      ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
--      *merge_cp_length_p, scratch_i, _index_map_count));
+-  if (merge_cp_p == NULL) {
+-    assert(false, "caller must provide scatch constantPool");
+-    return false; // robustness
 -  }
+-  if (merge_cp_length_p == NULL) {
+-    assert(false, "caller must provide scatch CP length");
+-    return false; // robustness
++  public:
++
 +    CheckFieldTypesClosure() {
 +      _result = true;
 +    }
- 
--  return true;
--} // end merge_constant_pools()
++
 +    bool result() { return _result; }
- 
++
 +    virtual void do_object(oop obj) {
- 
--// Merge constant pools between the_class and scratch_class and
--// potentially rewrite bytecodes in scratch_class to use the merged
--// constant pool.
--jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
--             instanceKlassHandle the_class, instanceKlassHandle scratch_class,
--             TRAPS) {
--  // worst case merged constant pool length is old and new combined
--  int merge_cp_length = the_class->constants()->length()
--        + scratch_class->constants()->length();
--
--  constantPoolHandle old_cp(THREAD, the_class->constants());
--  constantPoolHandle scratch_cp(THREAD, scratch_class->constants());
--
--  // Constant pools are not easily reused so we allocate a new one
--  // each time.
--  // merge_cp is created unsafe for concurrent GC processing.  It
--  // should be marked safe before discarding it. Even though
--  // garbage,  if it crosses a card boundary, it may be scanned
--  // in order to find the start of the first complete object on the card.
--  constantPoolHandle merge_cp(THREAD,
--    oopFactory::new_constantPool(merge_cp_length,
--                                 oopDesc::IsUnsafeConc,
--                                 THREAD));
--  int orig_length = old_cp->orig_length();
--  if (orig_length == 0) {
--    // This old_cp is an actual original constant pool. We save
--    // the original length in the merged constant pool so that
--    // merge_constant_pools() can be more efficient. If a constant
--    // pool has a non-zero orig_length() value, then that constant
--    // pool was created by a merge operation in RedefineClasses.
--    merge_cp->set_orig_length(old_cp->length());
--  } else {
--    // This old_cp is a merged constant pool from a previous
--    // RedefineClasses() calls so just copy the orig_length()
--    // value.
--    merge_cp->set_orig_length(old_cp->orig_length());
--  }
++
 +      if (!_result) {
 +        return;
 +      }
- 
--  ResourceMark rm(THREAD);
--  _index_map_count = 0;
--  _index_map_p = new intArray(scratch_cp->length(), -1);
++
 +      if (obj->is_objArray()) {
- 
--  bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
--                  &merge_cp_length, THREAD);
--  if (!result) {
--    // The merge can fail due to memory allocation failure or due
--    // to robustness checks.
--    return JVMTI_ERROR_INTERNAL;
--  }
--
--  RC_TRACE_WITH_THREAD(0x00010000, THREAD,
--    ("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count));
--
--  if (_index_map_count == 0) {
--    // there is nothing to map between the new and merged constant pools
--
--    if (old_cp->length() == scratch_cp->length()) {
--      // The old and new constant pools are the same length and the
--      // index map is empty. This means that the three constant pools
--      // are equivalent (but not the same). Unfortunately, the new
--      // constant pool has not gone through link resolution nor have
--      // the new class bytecodes gone through constant pool cache
--      // rewriting so we can't use the old constant pool with the new
--      // class.
--
--      merge_cp()->set_is_conc_safe(true);
--      merge_cp = constantPoolHandle();  // toss the merged constant pool
--    } else if (old_cp->length() < scratch_cp->length()) {
--      // The old constant pool has fewer entries than the new constant
--      // pool and the index map is empty. This means the new constant
--      // pool is a superset of the old constant pool. However, the old
--      // class bytecodes have already gone through constant pool cache
--      // rewriting so we can't use the new constant pool with the old
--      // class.
++
 +        objArrayOop array = objArrayOop(obj);
- 
--      merge_cp()->set_is_conc_safe(true);
--      merge_cp = constantPoolHandle();  // toss the merged constant pool
--    } else {
--      // The old constant pool has more entries than the new constant
--      // pool and the index map is empty. This means that both the old
--      // and merged constant pools are supersets of the new constant
--      // pool.
--
--      // Replace the new constant pool with a shrunken copy of the
--      // merged constant pool; the previous new constant pool will
--      // get GCed.
--      set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true,
--        THREAD);
--      // drop local ref to the merged constant pool
--      merge_cp()->set_is_conc_safe(true);
--      merge_cp = constantPoolHandle();
--    }
--  } else {
--    if (RC_TRACE_ENABLED(0x00040000)) {
--      // don't want to loop unless we are tracing
--      int count = 0;
--      for (int i = 1; i < _index_map_p->length(); i++) {
--        int value = _index_map_p->at(i);
++
 +        klassOop element_klass = objArrayKlass::cast(array->klass())->element_klass();
 +
 +        if (element_klass->klass_part()->has_subtype_changed()) {
@@ -6965,11 +6798,7 @@
 +            }
 +          }
 +        }
- 
--        if (value != -1) {
--          RC_TRACE_WITH_THREAD(0x00040000, THREAD,
--            ("index_map[%d]: old=%d new=%d", count, i, value));
--          count++;
++
 +      } else {
 +        Pair<int, klassOop> *cur = obj->klass()->klass_part()->type_check_information();
 +        if (cur != NULL) {
@@ -6978,14 +6807,10 @@
 +            check_field(obj, (*cur).left(), (*cur).right());
 +            cur++;
 +          }
-         }
-       }
-     }
- 
--    // We have entries mapped between the new and merged constant pools
--    // so we have to rewrite some constant pool references.
--    if (!rewrite_cp_refs(scratch_class, THREAD)) {
--      return JVMTI_ERROR_INTERNAL;
++        }
++      }
++    }
++
 +    void check_field(oop obj, int offset, klassOop static_type) {
 +      oop field_value = obj->obj_field(offset);
 +      if (field_value != NULL) {
@@ -7007,40 +6832,20 @@
 +          _result = false;
 +        }
 +      }
-     }
++    }
 +  };
- 
--    // Replace the new constant pool with a shrunken copy of the
--    // merged constant pool so now the rewritten bytecodes have
--    // valid references; the previous new constant pool will get
--    // GCed.
--    set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true,
--      THREAD);
--    merge_cp()->set_is_conc_safe(true);
--  }
--  assert(old_cp()->is_conc_safe(), "Just checking");
--  assert(scratch_cp()->is_conc_safe(), "Just checking");
--
--  return JVMTI_ERROR_NONE;
--} // end merge_cp_and_rewrite()
++
 +  CheckFieldTypesClosure myObjectClosure;
- 
++
 +  // make sure that heap is parsable (fills TLABs with filler objects)
 +  Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
- 
--// Rewrite constant pool references in klass scratch_class.
--bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class,
--       TRAPS) {
++
 +  // do the iteration
 +  // If this operation encounters a bad object when using CMS,
 +  // consider using safe_object_iterate() which avoids perm gen
 +  // objects that may contain bad references.
 +  Universe::heap()->object_iterate(&myObjectClosure);
- 
--  // rewrite constant pool references in the methods:
--  if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
--    // propagate failure back to caller
--    return false;
++
 +  // when sharing is enabled we must iterate over the shared spaces
 +  if (UseSharedSpaces) {
 +    GenCollectedHeap* gch = GenCollectedHeap::heap();
@@ -7048,41 +6853,62 @@
 +    gen->ro_space()->object_iterate(&myObjectClosure);
 +    gen->rw_space()->object_iterate(&myObjectClosure);
    }
- 
--  // rewrite constant pool references in the class_annotations:
--  if (!rewrite_cp_refs_in_class_annotations(scratch_class, THREAD)) {
--    // propagate failure back to caller
--    return false;
--  }
-+  return myObjectClosure.result();
-+}
- 
--  // rewrite constant pool references in the fields_annotations:
--  if (!rewrite_cp_refs_in_fields_annotations(scratch_class, THREAD)) {
--    // propagate failure back to caller
--    return false;
+-  // Worst case we need old_cp->length() + scratch_cp()->length(),
+-  // but the caller might be smart so make sure we have at least
+-  // the minimum.
+-  if ((*merge_cp_p)->length() < old_cp->length()) {
+-    assert(false, "merge area too small");
+-    return false; // robustness
++
++  return myObjectClosure.result();
++}
++
 +void VM_RedefineClasses::clear_type_check_information(klassOop k) {
 +  if (k->klass_part()->is_redefining()) {
 +    k = k->klass_part()->old_version();
    }
  
--  // rewrite constant pool references in the methods_annotations:
--  if (!rewrite_cp_refs_in_methods_annotations(scratch_class, THREAD)) {
--    // propagate failure back to caller
--    return false;
--  }
+-  RC_TRACE_WITH_THREAD(0x00010000, THREAD,
+-    ("old_cp_len=%d, scratch_cp_len=%d", old_cp->length(),
+-    scratch_cp->length()));
 +  // We found an instance klass!
 +  instanceKlass *cur_instance_klass = instanceKlass::cast(k);
 +  cur_instance_klass->clear_type_check_information();
 +}
  
--  // rewrite constant pool references in the methods_parameter_annotations:
--  if (!rewrite_cp_refs_in_methods_parameter_annotations(scratch_class,
--         THREAD)) {
--    // propagate failure back to caller
--    return false;
+-  {
+-    // Pass 0:
+-    // The old_cp is copied to *merge_cp_p; this means that any code
+-    // using old_cp does not have to change. This work looks like a
+-    // perfect fit for constantPoolOop::copy_cp_to(), but we need to
+-    // handle one special case:
+-    // - revert JVM_CONSTANT_Class to JVM_CONSTANT_UnresolvedClass
+-    // This will make verification happy.
+-
+-    int old_i;  // index into old_cp
+-
+-    // index zero (0) is not used in constantPools
+-    for (old_i = 1; old_i < old_cp->length(); old_i++) {
+-      // leave debugging crumb
+-      jbyte old_tag = old_cp->tag_at(old_i).value();
+-      switch (old_tag) {
+-      case JVM_CONSTANT_Class:
+-      case JVM_CONSTANT_UnresolvedClass:
+-        // revert the copy to JVM_CONSTANT_UnresolvedClass
+-        // May be resolving while calling this so do the same for
+-        // JVM_CONSTANT_UnresolvedClass (klass_name_at() deals with transition)
+-        (*merge_cp_p)->unresolved_klass_at_put(old_i,
+-          old_cp->klass_name_at(old_i));
+-        break;
 +void VM_RedefineClasses::update_active_methods() {
-+
+ 
+-      case JVM_CONSTANT_Double:
+-      case JVM_CONSTANT_Long:
+-        // just copy the entry to *merge_cp_p, but double and long take
+-        // two constant pool entries
+-        constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
+-        old_i++;
+-        break;
 +  RC_TRACE(0x00000002, ("Updating active methods"));
 +  JavaThread *java_thread = Threads::first();
 +  while (java_thread != NULL) {
@@ -7147,7 +6973,11 @@
 +                  cp_new->entry_at(i)->print(tty, i);
 +                }
 +              }
-+
+ 
+-      default:
+-        // just copy the entry to *merge_cp_p
+-        constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
+-        break;
 +              iframe->set_method(jvf->method()->new_version(), bci);
 +              RC_TRACE(0x00000002, ("Updated method to newer version"));
 +              assert(jvf->method()->new_version() == NULL, "must be latest version");
@@ -7156,21 +6986,22 @@
 +          } 
 +        }
 +        vf = vf->sender();
-+      }
+       }
+-    } // end for each old_cp entry
 +    }
 +
 +    // Advance to next thread
 +    java_thread = java_thread->next();
-   }
++  }
 +}
  
--  // rewrite constant pool references in the methods_default_annotations:
--  if (!rewrite_cp_refs_in_methods_default_annotations(scratch_class,
--         THREAD)) {
--    // propagate failure back to caller
--    return false;
+-    constantPoolOopDesc::copy_operands(old_cp, *merge_cp_p, CHECK_0);
+-    (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0);
 +void VM_RedefineClasses::method_forwarding() {
-+
+ 
+-    // We don't need to sanity check that *merge_cp_length_p is within
+-    // *merge_cp_p bounds since we have the minimum on-entry check above.
+-    (*merge_cp_length_p) = old_i;
 +  int forwarding_count = 0;
 +  JavaThread *java_thread = Threads::first();
 +  while (java_thread != NULL) {
@@ -7256,28 +7087,110 @@
 +    java_thread = java_thread->next();
    }
  
--  return true;
--} // end rewrite_cp_refs()
+-  // merge_cp_len should be the same as old_cp->length() at this point
+-  // so this trace message is really a "warm-and-breathing" message.
+-  RC_TRACE_WITH_THREAD(0x00020000, THREAD,
+-    ("after pass 0: merge_cp_len=%d", *merge_cp_length_p));
 +  RC_TRACE(0x00000001, ("Method forwarding applied to %d methods",
 +    forwarding_count));
 +}
  
+-  int scratch_i;  // index into scratch_cp
+-  {
+-    // Pass 1a:
+-    // Compare scratch_cp entries to the old_cp entries that we have
+-    // already copied to *merge_cp_p. In this pass, we are eliminating
+-    // exact duplicates (matching entry at same index) so we only
+-    // compare entries in the common indice range.
+-    int increment = 1;
+-    int pass1a_length = MIN2(old_cp->length(), scratch_cp->length());
+-    for (scratch_i = 1; scratch_i < pass1a_length; scratch_i += increment) {
+-      switch (scratch_cp->tag_at(scratch_i).value()) {
+-      case JVM_CONSTANT_Double:
+-      case JVM_CONSTANT_Long:
+-        // double and long take two constant pool entries
+-        increment = 2;
+-        break;
 +bool VM_RedefineClasses::check_method_stacks() {
  
--// Rewrite constant pool references in the methods.
--bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
--       instanceKlassHandle scratch_class, TRAPS) {
+-      default:
+-        increment = 1;
+-        break;
+-      }
 +  JavaThread *java_thread = Threads::first();
 +  while (java_thread != NULL) {
  
--  objArrayHandle methods(THREAD, scratch_class->methods());
+-      bool match = scratch_cp->compare_entry_to(scratch_i, *merge_cp_p,
+-        scratch_i, CHECK_0);
+-      if (match) {
+-        // found a match at the same index so nothing more to do
+-        continue;
+-      } else if (is_unresolved_class_mismatch(scratch_cp, scratch_i,
+-                                              *merge_cp_p, scratch_i)) {
+-        // The mismatch in compare_entry_to() above is because of a
+-        // resolved versus unresolved class entry at the same index
+-        // with the same string value. Since Pass 0 reverted any
+-        // class entries to unresolved class entries in *merge_cp_p,
+-        // we go with the unresolved class entry.
+-        continue;
+-      } else if (is_unresolved_string_mismatch(scratch_cp, scratch_i,
+-                                               *merge_cp_p, scratch_i)) {
+-        // The mismatch in compare_entry_to() above is because of a
+-        // resolved versus unresolved string entry at the same index
+-        // with the same string value. We can live with whichever
+-        // happens to be at scratch_i in *merge_cp_p.
+-        continue;
+-      }
+-
+-      int found_i = scratch_cp->find_matching_entry(scratch_i, *merge_cp_p,
+-        CHECK_0);
+-      if (found_i != 0) {
+-        guarantee(found_i != scratch_i,
+-          "compare_entry_to() and find_matching_entry() do not agree");
+-
+-        // Found a matching entry somewhere else in *merge_cp_p so
+-        // just need a mapping entry.
+-        map_index(scratch_cp, scratch_i, found_i);
+-        continue;
+-      }
+-
+-      // The find_matching_entry() call above could fail to find a match
+-      // due to a resolved versus unresolved class or string entry situation
+-      // like we solved above with the is_unresolved_*_mismatch() calls.
+-      // However, we would have to call is_unresolved_*_mismatch() over
+-      // all of *merge_cp_p (potentially) and that doesn't seem to be
+-      // worth the time.
+-
+-      // No match found so we have to append this entry and any unique
+-      // referenced entries to *merge_cp_p.
+-      append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p,
+-        CHECK_0);
+-    }
+-  }
+-
+-  RC_TRACE_WITH_THREAD(0x00020000, THREAD,
+-    ("after pass 1a: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
+-    *merge_cp_length_p, scratch_i, _index_map_count));
+-
+-  if (scratch_i < scratch_cp->length()) {
+-    // Pass 1b:
+-    // old_cp is smaller than scratch_cp so there are entries in
+-    // scratch_cp that we have not yet processed. We take care of
+-    // those now.
+-    int increment = 1;
+-    for (; scratch_i < scratch_cp->length(); scratch_i += increment) {
+-      switch (scratch_cp->tag_at(scratch_i).value()) {
+-      case JVM_CONSTANT_Double:
+-      case JVM_CONSTANT_Long:
+-        // double and long take two constant pool entries
+-        increment = 2;
+-        break;
 +    int stack_depth = 0;
 +    if (java_thread->has_last_Java_frame()) {
  
--  if (methods.is_null() || methods->length() == 0) {
--    // no methods so nothing to do
--    return true;
--  }
+-      default:
+-        increment = 1;
+-        break;
 +      RC_TRACE(0x00000400, ("checking stack of Java thread %s", java_thread->name()));
 +
 +      // vframes are resource allocated
@@ -7382,32 +7295,527 @@
 +                    Thread::current()->clear_pending_exception();
 +                    return false;
 +                  } 
- 
--  // rewrite constant pool references in the methods:
--  for (int i = methods->length() - 1; i >= 0; i--) {
--    methodHandle method(THREAD, (methodOop)methods->obj_at(i));
--    methodHandle new_method;
--    rewrite_cp_refs_in_method(method, &new_method, CHECK_false);
--    if (!new_method.is_null()) {
--      // the method has been replaced so save the new method version
--      methods->obj_at_put(i, new_method());
++
 +                }
 +              }
 +            }
 +          } 
 +        }
-+        vf = vf->sender();
++        vf = vf->sender();
+       }
++    }
+ 
+-      int found_i =
+-        scratch_cp->find_matching_entry(scratch_i, *merge_cp_p, CHECK_0);
+-      if (found_i != 0) {
+-        // Found a matching entry somewhere else in *merge_cp_p so
+-        // just need a mapping entry.
+-        map_index(scratch_cp, scratch_i, found_i);
+-        continue;
+-      }
+-
+-      // No match found so we have to append this entry and any unique
+-      // referenced entries to *merge_cp_p.
+-      append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p,
+-        CHECK_0);
+-    }
+-
+-    RC_TRACE_WITH_THREAD(0x00020000, THREAD,
+-      ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
+-      *merge_cp_length_p, scratch_i, _index_map_count));
++    // Advance to next thread
++    java_thread = java_thread->next();
+   }
+-  finalize_operands_merge(*merge_cp_p, THREAD);
+ 
+   return true;
+-} // end merge_constant_pools()
++}
+ 
++bool VM_RedefineClasses::check_method(methodOop method) {
+ 
+-// Merge constant pools between the_class and scratch_class and
+-// potentially rewrite bytecodes in scratch_class to use the merged
+-// constant pool.
+-jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
+-             instanceKlassHandle the_class, instanceKlassHandle scratch_class,
+-             TRAPS) {
+-  // worst case merged constant pool length is old and new combined
+-  int merge_cp_length = the_class->constants()->length()
+-        + scratch_class->constants()->length();
+-
+-  constantPoolHandle old_cp(THREAD, the_class->constants());
+-  constantPoolHandle scratch_cp(THREAD, scratch_class->constants());
+-
+-  // Constant pools are not easily reused so we allocate a new one
+-  // each time.
+-  // merge_cp is created unsafe for concurrent GC processing.  It
+-  // should be marked safe before discarding it. Even though
+-  // garbage,  if it crosses a card boundary, it may be scanned
+-  // in order to find the start of the first complete object on the card.
+-  constantPoolHandle merge_cp(THREAD,
+-    oopFactory::new_constantPool(merge_cp_length,
+-                                 oopDesc::IsUnsafeConc,
+-                                 THREAD));
+-  int orig_length = old_cp->orig_length();
+-  if (orig_length == 0) {
+-    // This old_cp is an actual original constant pool. We save
+-    // the original length in the merged constant pool so that
+-    // merge_constant_pools() can be more efficient. If a constant
+-    // pool has a non-zero orig_length() value, then that constant
+-    // pool was created by a merge operation in RedefineClasses.
+-    merge_cp->set_orig_length(old_cp->length());
+-  } else {
+-    // This old_cp is a merged constant pool from a previous
+-    // RedefineClasses() calls so just copy the orig_length()
+-    // value.
+-    merge_cp->set_orig_length(old_cp->orig_length());
+-  }
+ 
+-  ResourceMark rm(THREAD);
+-  _index_map_count = 0;
+-  _index_map_p = new intArray(scratch_cp->length(), -1);
++  return true;
++}
+ 
+-  _operands_cur_length = constantPoolOopDesc::operand_array_length(old_cp->operands());
+-  _operands_index_map_count = 0;
+-  _operands_index_map_p = new intArray(
+-    constantPoolOopDesc::operand_array_length(scratch_cp->operands()), -1);
+-
+-  // reference to the cp holder is needed for copy_operands()
+-  merge_cp->set_pool_holder(scratch_class());
+-  bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
+-                  &merge_cp_length, THREAD);
+-  merge_cp->set_pool_holder(NULL);
++// Warning: destroys redefinition level values of klasses.
++bool VM_RedefineClasses::check_loaded_methods() {
+ 
+-  if (!result) {
+-    // The merge can fail due to memory allocation failure or due
+-    // to robustness checks.
+-    return JVMTI_ERROR_INTERNAL;
+-  }
+-
+-  RC_TRACE_WITH_THREAD(0x00010000, THREAD,
+-    ("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count));
+-
+-  if (_index_map_count == 0) {
+-    // there is nothing to map between the new and merged constant pools
+-
+-    if (old_cp->length() == scratch_cp->length()) {
+-      // The old and new constant pools are the same length and the
+-      // index map is empty. This means that the three constant pools
+-      // are equivalent (but not the same). Unfortunately, the new
+-      // constant pool has not gone through link resolution nor have
+-      // the new class bytecodes gone through constant pool cache
+-      // rewriting so we can't use the old constant pool with the new
+-      // class.
+-
+-      merge_cp()->set_is_conc_safe(true);
+-      merge_cp = constantPoolHandle();  // toss the merged constant pool
+-    } else if (old_cp->length() < scratch_cp->length()) {
+-      // The old constant pool has fewer entries than the new constant
+-      // pool and the index map is empty. This means the new constant
+-      // pool is a superset of the old constant pool. However, the old
+-      // class bytecodes have already gone through constant pool cache
+-      // rewriting so we can't use the new constant pool with the old
+-      // class.
++  class CheckLoadedMethodsClosure : public ObjectClosure {
+ 
+-      merge_cp()->set_is_conc_safe(true);
+-      merge_cp = constantPoolHandle();  // toss the merged constant pool
+-    } else {
+-      // The old constant pool has more entries than the new constant
+-      // pool and the index map is empty. This means that both the old
+-      // and merged constant pools are supersets of the new constant
+-      // pool.
+-
+-      // Replace the new constant pool with a shrunken copy of the
+-      // merged constant pool; the previous new constant pool will
+-      // get GCed.
+-      set_new_constant_pool(scratch_class, merge_cp, merge_cp_length,
+-        THREAD);
+-      // drop local ref to the merged constant pool
+-      merge_cp()->set_is_conc_safe(true);
+-      merge_cp = constantPoolHandle();
++  private:
++    
++    bool _result;
++    GrowableArray<klassOop> *_dangerous_klasses;
++
++  public:
++    CheckLoadedMethodsClosure(GrowableArray<klassOop> *dangerous_klasses) {
++      _result = true;
++      _dangerous_klasses = dangerous_klasses;
++    }
++
++    bool result() {
++      return _result;
++    }
++
++    bool is_class_dangerous(klassOop k) {
++      return k->klass_part()->newest_version()->klass_part()->check_redefinition_flag(Klass::RemoveSuperType);
++    }
++
++    bool can_be_affected(instanceKlass *klass) {
++
++      constantPoolOop cp = klass->constants();
++
++      Thread *THREAD = Thread::current();
++      klassOop k;
++      Symbol* symbol;
++
++      for (int i=1; i<cp->length(); i++) {
++        jbyte tag = cp->tag_at(i).value();
++        switch(tag) {
++          case JVM_CONSTANT_Long:
++          case JVM_CONSTANT_Double:
++            i++;
++            break;
++
++          case JVM_CONSTANT_Utf8:
++          case JVM_CONSTANT_Unicode:
++          case JVM_CONSTANT_Integer:
++          case JVM_CONSTANT_Float:
++          case JVM_CONSTANT_String:
++          case JVM_CONSTANT_Fieldref:
++          case JVM_CONSTANT_Methodref:
++          case JVM_CONSTANT_InterfaceMethodref:
++          case JVM_CONSTANT_ClassIndex:
++          case JVM_CONSTANT_UnresolvedString:
++          case JVM_CONSTANT_StringIndex:
++          case JVM_CONSTANT_UnresolvedClassInError:
++          case JVM_CONSTANT_Object:
++            // do nothing
++            break;
++
++          case JVM_CONSTANT_Class:
++            k = cp->klass_at(i, CHECK_(true));
++            if (is_class_dangerous(k)) {
++              RC_TRACE(0x00000002, ("Class %s is potentially affected, because at cp[%d] references class %s",
++                klass->name()->as_C_string(),
++                i,
++                k->klass_part()->name()->as_C_string()));
++              return true;
++            }
++            break;
++          
++          case JVM_CONSTANT_NameAndType:
++            symbol = cp->symbol_at(cp->signature_ref_index_at(i));
++            if (symbol->byte_at(0) == '(') {
++              // This must be a method
++              SignatureStream signatureStream(symbol);
++              while (true) {
++
++                if (signatureStream.is_array()) {
++                  Symbol* cur_signature = signatureStream.as_symbol(Thread::current());
++                  if (is_type_signature_dangerous(cur_signature)) {
++                    return true;
++                  }
++                } else if (signatureStream.is_object()) {
++                  if (is_symbol_dangerous(signatureStream.as_symbol(Thread::current()))) {
++                    return true;
++                  }
++                } 
++
++                if (signatureStream.at_return_type()) {
++                  break;
++                }
++
++                signatureStream.next();
++              }
++
++            } else if (is_type_signature_dangerous(symbol)) {
++              return true;
++            }
++            break;
++
++          case JVM_CONSTANT_UnresolvedClass:
++            symbol = cp->unresolved_klass_at(i);
++            if (is_symbol_dangerous(symbol)) {
++              return true;
++            }
++            break;
++
++          default:
++            ShouldNotReachHere();
++        }
++      }
++
++      return false;
+     }
+-  } else {
+-    if (RC_TRACE_ENABLED(0x00040000)) {
+-      // don't want to loop unless we are tracing
+-      int count = 0;
+-      for (int i = 1; i < _index_map_p->length(); i++) {
+-        int value = _index_map_p->at(i);
+ 
+-        if (value != -1) {
+-          RC_TRACE_WITH_THREAD(0x00040000, THREAD,
+-            ("index_map[%d]: old=%d new=%d", count, i, value));
+-          count++;
++    bool is_type_signature_dangerous(Symbol* signature) {
++      // This must be a field type
++      if (FieldType::is_obj(signature)) {
++        Symbol* name = signature_to_class_name(signature);
++        if (is_symbol_dangerous(name)) {
++          return true;
++        }
++      } else if (FieldType::is_array(signature)) {
++        //jint dimension;
++        //Symbol* object_key;
++        FieldArrayInfo fd;
++        FieldType::get_array_info(signature, fd, Thread::current());
++        if (is_symbol_dangerous(fd.object_key())) {
++          return true;
+         }
+       }
++      return false;
+     }
+ 
+-    // We have entries mapped between the new and merged constant pools
+-    // so we have to rewrite some constant pool references.
+-    if (!rewrite_cp_refs(scratch_class, THREAD)) {
+-      return JVMTI_ERROR_INTERNAL;
++    bool is_symbol_dangerous(Symbol* symbol) {
++      for (int i=0; i<_dangerous_klasses->length(); i++) {
++        if(_dangerous_klasses->at(i)->klass_part()->name() == symbol) {
++          RC_TRACE(0x00000002, ("Found constant pool index %d references class %s",
++            i,
++            symbol->as_C_string()));
++          return true;
++        }
++      }
++      return false;
+     }
+ 
+-    // Replace the new constant pool with a shrunken copy of the
+-    // merged constant pool so now the rewritten bytecodes have
+-    // valid references; the previous new constant pool will get
+-    // GCed.
+-    set_new_constant_pool(scratch_class, merge_cp, merge_cp_length,
+-      THREAD);
+-    merge_cp()->set_is_conc_safe(true);
+-  }
+-  assert(old_cp()->is_conc_safe(), "Just checking");
+-  assert(scratch_cp()->is_conc_safe(), "Just checking");
++    virtual void do_object(oop obj) {
+ 
+-  return JVMTI_ERROR_NONE;
+-} // end merge_cp_and_rewrite()
++      if (!_result) return;
+ 
++      klassOop klassObj = (klassOop)obj;
++      Thread *THREAD = Thread::current();
+ 
+-// Rewrite constant pool references in klass scratch_class.
+-bool VM_RedefineClasses::rewrite_cp_refs(instanceKlassHandle scratch_class,
+-       TRAPS) {
++      // We found an instance klass!
++      instanceKlass *klass = instanceKlass::cast(klassObj);
++      instanceKlassHandle handle(klassObj);
+ 
+-  // rewrite constant pool references in the methods:
+-  if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
+-    // propagate failure back to caller
+-    return false;
+-  }
++      RC_TRACE(0x00000400, ("Check if verification is necessary for class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
+ 
+-  // rewrite constant pool references in the class_annotations:
+-  if (!rewrite_cp_refs_in_class_annotations(scratch_class, THREAD)) {
+-    // propagate failure back to caller
+-    return false;
+-  }
++      if (!can_be_affected(klass)) {
++        RC_TRACE(0x00000400, ("Skipping verification of class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
++        return;
++      }
+ 
+-  // rewrite constant pool references in the fields_annotations:
+-  if (!rewrite_cp_refs_in_fields_annotations(scratch_class, THREAD)) {
+-    // propagate failure back to caller
+-    return false;
++      if (handle->major_version() < Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
++        RC_TRACE(0x00000001, ("Failing because cannot verify class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
++        _result = false;
++        return;
++      }
++
++      RC_TRACE(0x00000001, ("Verifying class %s", handle->name()->as_C_string()));
++
++      if (!Verifier::verify(handle, Verifier::NoException, true, false, Thread::current())) {
++        
++        RC_TRACE(0x00000001, ("Verification of class %s failed", handle->name()->as_C_string()));
++        //Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
++        //RC_TRACE(0x00000002, ("exception when verifying class: '%s'", ex_name->as_C_string());
++        //PENDING_EXCEPTION->print();
++        CLEAR_PENDING_EXCEPTION;
++        _result = false;
++      } 
++
++      /*int method_count = klass->methods()->length();
++      for (int i=0; i<method_count; i++) {
++        methodOop cur_method = (methodOop)klass->methods()->obj_at(i);
++        if (!check_method(cur_method)) {
++          RC_TRACE(0x00000001, ("Failed to verify consistency of method %s of klass %s", cur_method->name()->as_C_string(), klass->name()->as_C_string());
++        }
++      }*/
++    }
++  };
++
++  // TODO: Check bytecodes in case of interface => class or class => interface etc..
++
++  GrowableArray<klassOop> dangerous_klasses;
++  for (int i=0; i<_new_classes->length(); i++) {
++    instanceKlassHandle handle = _new_classes->at(i);
++    if (handle->check_redefinition_flag(Klass::RemoveSuperType)) {
++      dangerous_klasses.append(handle());
++    }
+   }
+ 
+-  // rewrite constant pool references in the methods_annotations:
+-  if (!rewrite_cp_refs_in_methods_annotations(scratch_class, THREAD)) {
+-    // propagate failure back to caller
++  CheckLoadedMethodsClosure checkLoadedMethodsClosure(&dangerous_klasses);
++  Thread::current()->set_pretend_new_universe(true);
++  SystemDictionary::classes_do(&checkLoadedMethodsClosure);
++  Thread::current()->set_pretend_new_universe(false);
++
++
++  return checkLoadedMethodsClosure.result();
++}
++
++bool VM_RedefineClasses::check_type_consistency() {
++
++  Universe::set_verify_in_progress(true);
++
++  SystemDictionary::classes_do(calculate_type_check_information);
++  bool result = check_field_value_types();
++  SystemDictionary::classes_do(clear_type_check_information);
++  if (!result) {
++    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong field or array element value!"));
++    Universe::set_verify_in_progress(false);
+     return false;
+   }
+ 
+-  // rewrite constant pool references in the methods_parameter_annotations:
+-  if (!rewrite_cp_refs_in_methods_parameter_annotations(scratch_class,
+-         THREAD)) {
+-    // propagate failure back to caller
++  result = check_method_stacks();
++  if (!result) {
++    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong value on the stack"));
++    Universe::set_verify_in_progress(false);
+     return false;
+   }
+ 
+-  // rewrite constant pool references in the methods_default_annotations:
+-  if (!rewrite_cp_refs_in_methods_default_annotations(scratch_class,
+-         THREAD)) {
+-    // propagate failure back to caller
++  result = check_loaded_methods();
++  if (!result) {
++    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong loaded method"));
++    Universe::set_verify_in_progress(false);
+     return false;
+   }
+ 
++  RC_TRACE(0x00000001, ("Verification passed => hierarchy change is valid!"));
++  Universe::set_verify_in_progress(false);
+   return true;
+-} // end rewrite_cp_refs()
+-
+-
+-// Rewrite constant pool references in the methods.
+-bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
+-       instanceKlassHandle scratch_class, TRAPS) {
++}
+ 
+-  objArrayHandle methods(THREAD, scratch_class->methods());
++void VM_RedefineClasses::rollback() {
++  RC_TRACE(0x00000001, ("Rolling back redefinition!"));
++  SystemDictionary::rollback_redefinition();
++
++  RC_TRACE(0x00000001, ("After rolling back system dictionary!"));
++  for (int i=0; i<_new_classes->length(); i++) {
++    SystemDictionary::remove_from_hierarchy(_new_classes->at(i));
++  }
+ 
+-  if (methods.is_null() || methods->length() == 0) {
+-    // no methods so nothing to do
+-    return true;
++  for (int i=0; i<_new_classes->length(); i++) {
++    instanceKlassHandle new_class = _new_classes->at(i);
++    new_class->set_redefining(false);
++    new_class->old_version()->klass_part()->set_new_version(NULL);
++    new_class->set_old_version(NULL);
+   }
+ 
+-  // rewrite constant pool references in the methods:
+-  for (int i = methods->length() - 1; i >= 0; i--) {
+-    methodHandle method(THREAD, (methodOop)methods->obj_at(i));
+-    methodHandle new_method;
+-    rewrite_cp_refs_in_method(method, &new_method, CHECK_false);
+-    if (!new_method.is_null()) {
+-      // the method has been replaced so save the new method version
+-      methods->obj_at_put(i, new_method());
++}
++
++template <class T> void VM_RedefineClasses::do_oop_work(T* p) {
++  T heap_oop = oopDesc::load_heap_oop(p);
++  if (!oopDesc::is_null(heap_oop)) {
++    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
++    if (obj->is_instanceKlass()) {
++      klassOop klass = (klassOop)obj;
++      // DCEVM: note: can overwrite owner of old_klass constants pool with new_klass, so we need to fix it back later
++      if (klass->new_version() != NULL && klass->new_version()->klass_part()->is_redefining()) {
++        obj = klass->klass_part()->new_version();
++        oopDesc::encode_store_heap_oop_not_null(p, obj);
++      }
++    } else if (obj->blueprint()->newest_version() == SystemDictionary::Class_klass()->klass_part()->newest_version()) {
++      // update references to java.lang.Class to point to newest version. Only update references to non-primitive
++      // java.lang.Class instances.
++      klassOop klass_oop = java_lang_Class::as_klassOop(obj);
++      if (klass_oop != NULL) {
++        if (klass_oop->new_version() != NULL && klass_oop->new_version()->klass_part()->is_redefining()) {
++          obj = klass_oop->new_version()->java_mirror();
++        } else if (klass_oop->klass_part()->is_redefining()) {
++          obj = klass_oop->java_mirror();
++        }
++        oopDesc::encode_store_heap_oop_not_null(p, obj);
++
++
++        // FIXME: DCEVM: better implementation?
++        // Starting from JDK 7 java_mirror can be kept in the regular heap. Therefore, it is possible
++        // that new java_mirror is in the young generation whereas p is in tenured generation. In that
++        // case we need to run write barrier to make sure card table is properly updated. This will
++        // allow JVM to detect reference in tenured generation properly during young generation GC.
++        if (Universe::heap()->is_in_reserved(p)) {
++          if (GenCollectedHeap::heap()->is_in_young(obj)) {
++            GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
++            assert(rs->rs_kind() == GenRemSet::CardTable, "Wrong rem set kind.");
++            CardTableRS* _rs = (CardTableRS*)rs;
++            _rs->inline_write_ref_field_gc(p, obj);
++          }
++        }
 +      }
      }
-+
-+    // Advance to next thread
-+    java_thread = java_thread->next();
    }
++}
  
-   return true;
+-  return true;
++void VM_RedefineClasses::swap_marks(oop first, oop second) {
++  markOop first_mark = first->mark();
++  markOop second_mark = second->mark();
++  first->set_mark(second_mark);
++  second->set_mark(first_mark);
  }
  
-+bool VM_RedefineClasses::check_method(methodOop method) {
++void VM_RedefineClasses::doit() {
++  Thread *thread = Thread::current();
  
 -// Rewrite constant pool references in the specific method. This code
 -// was adapted from Rewriter::rewrite_method().
@@ -7437,39 +7845,17 @@
 -      // More complicated bytecodes report a length of zero so
 -      // we have to try again a slightly different way.
 -      bc_length = Bytecodes::length_at(method(), bcp);
-+
-+  return true;
-+}
-+
-+// Warning: destroys redefinition level values of klasses.
-+bool VM_RedefineClasses::check_loaded_methods() {
-+
-+  class CheckLoadedMethodsClosure : public ObjectClosure {
-+
-+  private:
-+    
-+    bool _result;
-+    GrowableArray<klassOop> *_dangerous_klasses;
-+
-+  public:
-+    CheckLoadedMethodsClosure(GrowableArray<klassOop> *dangerous_klasses) {
-+      _result = true;
-+      _dangerous_klasses = dangerous_klasses;
-     }
+-    }
++  RC_TRACE(0x00000001, ("Entering doit!"));
  
 -    assert(bc_length != 0, "impossible bytecode length");
-+    bool result() {
-+      return _result;
-+    }
  
 -    switch (c) {
 -      case Bytecodes::_ldc:
 -      {
 -        int cp_index = *(bcp + 1);
 -        int new_index = find_new_index(cp_index);
-+    bool is_class_dangerous(klassOop k) {
-+      return k->klass_part()->newest_version()->klass_part()->check_redefinition_flag(Klass::RemoveSuperType);
-+    }
++  if ((_max_redefinition_flags & Klass::RemoveSuperType) != 0) {
  
 -        if (StressLdcRewrite && new_index == 0) {
 -          // If we are stressing ldc -> ldc_w rewriting, then we
@@ -7509,78 +7895,9 @@
 -              m = rc.insert_space_at(bci, 3, inst_buffer, THREAD);
 -              if (m.is_null() || HAS_PENDING_EXCEPTION) {
 -                guarantee(false, "insert_space_at() failed");
-+    bool can_be_affected(instanceKlass *klass) {
-+
-+      constantPoolOop cp = klass->constants();
-+
-+      Thread *THREAD = Thread::current();
-+      klassOop k;
-+      Symbol* symbol;
-+
-+      for (int i=1; i<cp->length(); i++) {
-+        jbyte tag = cp->tag_at(i).value();
-+        switch(tag) {
-+          case JVM_CONSTANT_Long:
-+          case JVM_CONSTANT_Double:
-+            i++;
-+            break;
-+
-+          case JVM_CONSTANT_Utf8:
-+          case JVM_CONSTANT_Unicode:
-+          case JVM_CONSTANT_Integer:
-+          case JVM_CONSTANT_Float:
-+          case JVM_CONSTANT_String:
-+          case JVM_CONSTANT_Fieldref:
-+          case JVM_CONSTANT_Methodref:
-+          case JVM_CONSTANT_InterfaceMethodref:
-+          case JVM_CONSTANT_ClassIndex:
-+          case JVM_CONSTANT_UnresolvedString:
-+          case JVM_CONSTANT_StringIndex:
-+          case JVM_CONSTANT_UnresolvedClassInError:
-+          case JVM_CONSTANT_Object:
-+            // do nothing
-+            break;
-+
-+          case JVM_CONSTANT_Class:
-+            k = cp->klass_at(i, CHECK_(true));
-+            if (is_class_dangerous(k)) {
-+              RC_TRACE(0x00000002, ("Class %s is potentially affected, because at cp[%d] references class %s",
-+                klass->name()->as_C_string(),
-+                i,
-+                k->klass_part()->name()->as_C_string()));
-+              return true;
-+            }
-+            break;
-+          
-+          case JVM_CONSTANT_NameAndType:
-+            symbol = cp->symbol_at(cp->signature_ref_index_at(i));
-+            if (symbol->byte_at(0) == '(') {
-+              // This must be a method
-+              SignatureStream signatureStream(symbol);
-+              while (true) {
-+
-+                if (signatureStream.is_array()) {
-+                  Symbol* cur_signature = signatureStream.as_symbol(Thread::current());
-+                  if (is_type_signature_dangerous(cur_signature)) {
-+                    return true;
-+                  }
-+                } else if (signatureStream.is_object()) {
-+                  if (is_symbol_dangerous(signatureStream.as_symbol(Thread::current()))) {
-+                    return true;
-+                  }
-+                } 
-+
-+                if (signatureStream.at_return_type()) {
-+                  break;
-+                }
-+
-+                signatureStream.next();
-               }
-+
-+            } else if (is_type_signature_dangerous(symbol)) {
-+              return true;
-             }
-+            break;
+-              }
+-            }
++    RC_TIMER_START(_timer_check_type);
  
 -            // return the new method so that the caller can update
 -            // the containing class
@@ -7603,6 +7920,7 @@
 -      case Bytecodes::_getfield       : // fall through
 -      case Bytecodes::_getstatic      : // fall through
 -      case Bytecodes::_instanceof     : // fall through
+-      case Bytecodes::_invokedynamic  : // fall through
 -      case Bytecodes::_invokeinterface: // fall through
 -      case Bytecodes::_invokespecial  : // fall through
 -      case Bytecodes::_invokestatic   : // fall through
@@ -7618,153 +7936,52 @@
 -        int cp_index = Bytes::get_Java_u2(p);
 -        int new_index = find_new_index(cp_index);
 -        if (new_index != 0) {
--          // the original index is mapped so update w/ new value
--          RC_TRACE_WITH_THREAD(0x00080000, THREAD,
--            ("%s@" INTPTR_FORMAT " old=%d, new=%d", Bytecodes::name(c),
--            bcp, cp_index, new_index));
--          // Rewriter::rewrite_method() uses put_native_u2() in this
--          // situation because it is reusing the constant pool index
--          // location for a native index into the constantPoolCache.
--          // Since we are updating the constant pool index prior to
--          // verification and constantPoolCache initialization, we
--          // need to keep the new index in Java byte order.
--          Bytes::put_Java_u2(p, new_index);
--        }
--      } break;
--    }
--  } // end for each bytecode
--} // end rewrite_cp_refs_in_method()
--
--
--// Rewrite constant pool references in the class_annotations field.
--bool VM_RedefineClasses::rewrite_cp_refs_in_class_annotations(
--       instanceKlassHandle scratch_class, TRAPS) {
--
--  typeArrayHandle class_annotations(THREAD,
--    scratch_class->class_annotations());
--  if (class_annotations.is_null() || class_annotations->length() == 0) {
--    // no class_annotations so nothing to do
--    return true;
--  }
--
--  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
--    ("class_annotations length=%d", class_annotations->length()));
--
--  int byte_i = 0;  // byte index into class_annotations
--  return rewrite_cp_refs_in_annotations_typeArray(class_annotations, byte_i,
--           THREAD);
-+          case JVM_CONSTANT_UnresolvedClass:
-+            symbol = cp->unresolved_klass_at(i);
-+            if (is_symbol_dangerous(symbol)) {
-+              return true;
-+            }
-+            break;
-+
-+          default:
-+            ShouldNotReachHere();
-+        }
-+      }
-+
-+      return false;
-+    }
-+
-+    bool is_type_signature_dangerous(Symbol* signature) {
-+      // This must be a field type
-+      if (FieldType::is_obj(signature)) {
-+        Symbol* name = signature_to_class_name(signature);
-+        if (is_symbol_dangerous(name)) {
-+          return true;
-+        }
-+      } else if (FieldType::is_array(signature)) {
-+        //jint dimension;
-+        //Symbol* object_key;
-+        FieldArrayInfo fd;
-+        FieldType::get_array_info(signature, fd, Thread::current());
-+        if (is_symbol_dangerous(fd.object_key())) {
-+          return true;
-+        }
-+      }
-+      return false;
-+    }
-+
-+    bool is_symbol_dangerous(Symbol* symbol) {
-+      for (int i=0; i<_dangerous_klasses->length(); i++) {
-+        if(_dangerous_klasses->at(i)->klass_part()->name() == symbol) {
-+          RC_TRACE(0x00000002, ("Found constant pool index %d references class %s",
-+            i,
-+            symbol->as_C_string()));
-+          return true;
-+        }
-+      }
-+      return false;
-+    }
-+
-+    virtual void do_object(oop obj) {
-+
-+      if (!_result) return;
-+
-+      klassOop klassObj = (klassOop)obj;
-+      Thread *THREAD = Thread::current();
-+
-+      // We found an instance klass!
-+      instanceKlass *klass = instanceKlass::cast(klassObj);
-+      instanceKlassHandle handle(klassObj);
-+
-+      RC_TRACE(0x00000400, ("Check if verification is necessary for class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
-+
-+      if (!can_be_affected(klass)) {
-+        RC_TRACE(0x00000400, ("Skipping verification of class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
-+        return;
-+      }
-+
-+      if (handle->major_version() < Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
-+        RC_TRACE(0x00000001, ("Failing because cannot verify class %s major_version=%d", handle->name()->as_C_string(), handle->major_version()));
-+        _result = false;
-+        return;
-+      }
-+
-+      RC_TRACE(0x00000001, ("Verifying class %s", handle->name()->as_C_string()));
-+
-+      if (!Verifier::verify(handle, Verifier::NoException, true, false, Thread::current())) {
-+        
-+        RC_TRACE(0x00000001, ("Verification of class %s failed", handle->name()->as_C_string()));
-+        //Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
-+        //RC_TRACE(0x00000002, ("exception when verifying class: '%s'", ex_name->as_C_string());
-+        //PENDING_EXCEPTION->print();
-+        CLEAR_PENDING_EXCEPTION;
-+        _result = false;
-+      } 
-+
-+      /*int method_count = klass->methods()->length();
-+      for (int i=0; i<method_count; i++) {
-+        methodOop cur_method = (methodOop)klass->methods()->obj_at(i);
-+        if (!check_method(cur_method)) {
-+          RC_TRACE(0x00000001, ("Failed to verify consistency of method %s of klass %s", cur_method->name()->as_C_string(), klass->name()->as_C_string());
-+        }
-+      }*/
-+    }
-+  };
-+
-+  // TODO: Check bytecodes in case of interface => class or class => interface etc..
-+
-+  GrowableArray<klassOop> dangerous_klasses;
-+  for (int i=0; i<_new_classes->length(); i++) {
-+    instanceKlassHandle handle = _new_classes->at(i);
-+    if (handle->check_redefinition_flag(Klass::RemoveSuperType)) {
-+      dangerous_klasses.append(handle());
+-          // the original index is mapped so update w/ new value
+-          RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+-            ("%s@" INTPTR_FORMAT " old=%d, new=%d", Bytecodes::name(c),
+-            bcp, cp_index, new_index));
+-          // Rewriter::rewrite_method() uses put_native_u2() in this
+-          // situation because it is reusing the constant pool index
+-          // location for a native index into the constantPoolCache.
+-          // Since we are updating the constant pool index prior to
+-          // verification and constantPoolCache initialization, we
+-          // need to keep the new index in Java byte order.
+-          Bytes::put_Java_u2(p, new_index);
+-        }
+-      } break;
+-    }
+-  } // end for each bytecode
+-} // end rewrite_cp_refs_in_method()
+-
+-
+-// Rewrite constant pool references in the class_annotations field.
+-bool VM_RedefineClasses::rewrite_cp_refs_in_class_annotations(
+-       instanceKlassHandle scratch_class, TRAPS) {
+-
+-  typeArrayHandle class_annotations(THREAD,
+-    scratch_class->class_annotations());
+-  if (class_annotations.is_null() || class_annotations->length() == 0) {
+-    // no class_annotations so nothing to do
+-    return true;
+-  }
+-
+-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+-    ("class_annotations length=%d", class_annotations->length()));
+-
+-  int byte_i = 0;  // byte index into class_annotations
+-  return rewrite_cp_refs_in_annotations_typeArray(class_annotations, byte_i,
+-           THREAD);
+-}
++    if (!check_type_consistency()) {
++      // (tw) TODO: Rollback the class redefinition
++      rollback();
++      RC_TRACE(0x00000001, ("Detected type inconsistency!"));
++      _result = JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
++      RC_TIMER_STOP(_timer_check_type);
++      return;
 +    }
-+  }
-+
-+  CheckLoadedMethodsClosure checkLoadedMethodsClosure(&dangerous_klasses);
-+  Thread::current()->set_pretend_new_universe(true);
-+  SystemDictionary::classes_do(&checkLoadedMethodsClosure);
-+  Thread::current()->set_pretend_new_universe(false);
-+
-+
-+  return checkLoadedMethodsClosure.result();
- }
  
-+bool VM_RedefineClasses::check_type_consistency() {
++    RC_TIMER_STOP(_timer_check_type);
  
 -// Rewrite constant pool references in an annotations typeArray. This
 -// "structure" is adapted from the RuntimeVisibleAnnotations_attribute
@@ -7777,19 +7994,18 @@
 -//
 -bool VM_RedefineClasses::rewrite_cp_refs_in_annotations_typeArray(
 -       typeArrayHandle annotations_typeArray, int &byte_i_ref, TRAPS) {
-+  Universe::set_verify_in_progress(true);
++  } else {
++    RC_TRACE(0x00000001, ("No type narrowing => skipping check for type inconsistency"));
++  }
  
 -  if ((byte_i_ref + 2) > annotations_typeArray->length()) {
 -    // not enough room for num_annotations field
 -    RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -      ("length() is too small for num_annotations field"));
-+  SystemDictionary::classes_do(calculate_type_check_information);
-+  bool result = check_field_value_types();
-+  SystemDictionary::classes_do(clear_type_check_information);
-+  if (!result) {
-+    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong field or array element value!"));
-+    Universe::set_verify_in_progress(false);
-     return false;
+-    return false;
++  if (UseMethodForwardPoints) {
++    RC_TRACE(0x00000001, ("Check stack for forwarding methods to new version"));
++    method_forwarding();
    }
  
 -  u2 num_annotations = Bytes::get_Java_u2((address)
@@ -7807,37 +8023,23 @@
 -        ("bad annotation_struct at %d", calc_num_annotations));
 -      // propagate failure back to caller
 -      return false;
--    }
-+  result = check_method_stacks();
-+  if (!result) {
-+    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong value on the stack"));
-+    Universe::set_verify_in_progress(false);
-+    return false;
-+  }
-+
-+  result = check_loaded_methods();
-+  if (!result) {
-+    RC_TRACE(0x00000001, ("Aborting redefinition because of wrong loaded method"));
-+    Universe::set_verify_in_progress(false);
-+    return false;
++  if (UseSharedSpaces) {
++    // Sharing is enabled so we remap the shared readonly space to
++    // shared readwrite, private just in case we need to redefine
++    // a shared class. We do the remap during the doit() phase of
++    // the safepoint to be safer.
++    if (!CompactingPermGenGen::remap_shared_readonly_as_readwrite()) {
++      RC_TRACE(0x00000001, ("failed to remap shared readonly space to readwrite, private"));
++      _result = JVMTI_ERROR_INTERNAL;
++      return;
+     }
    }
 -  assert(num_annotations == calc_num_annotations, "sanity check");
  
-+  RC_TRACE(0x00000001, ("Verification passed => hierarchy change is valid!"));
-+  Universe::set_verify_in_progress(false);
-   return true;
+-  return true;
 -} // end rewrite_cp_refs_in_annotations_typeArray()
-+}
- 
-+void VM_RedefineClasses::rollback() {
-+  RC_TRACE(0x00000001, ("Rolling back redefinition!"));
-+  SystemDictionary::rollback_redefinition();
-+
-+  RC_TRACE(0x00000001, ("After rolling back system dictionary!"));
-+  for (int i=0; i<_new_classes->length(); i++) {
-+    SystemDictionary::remove_from_hierarchy(_new_classes->at(i));
-+  }
- 
+-
+-
 -// Rewrite constant pool references in the annotation struct portion of
 -// an annotations_typeArray. This "structure" is from section 4.8.15 of
 -// the 2nd-edition of the VM spec:
@@ -7858,17 +8060,14 @@
 -    RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -      ("length() is too small for annotation_struct"));
 -    return false;
-+  for (int i=0; i<_new_classes->length(); i++) {
-+    instanceKlassHandle new_class = _new_classes->at(i);
-+    new_class->set_redefining(false);
-+    new_class->old_version()->klass_part()->set_new_version(NULL);
-+    new_class->set_old_version(NULL);
++  RC_TIMER_START(_timer_prepare_redefinition);
++  for (int i = 0; i < _new_classes->length(); i++) {
++    redefine_single_class(_new_classes->at(i), thread);
    }
  
 -  u2 type_index = rewrite_cp_ref_in_annotation_data(annotations_typeArray,
 -                    byte_i_ref, "mapped old type_index=%d", THREAD);
-+}
- 
+-
 -  u2 num_element_value_pairs = Bytes::get_Java_u2((address)
 -                                 annotations_typeArray->byte_at_addr(
 -                                 byte_i_ref));
@@ -7887,47 +8086,9 @@
 -      RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -        ("length() is too small for element_name_index"));
 -      return false;
-+template <class T> void VM_RedefineClasses::do_oop_work(T* p) {
-+  T heap_oop = oopDesc::load_heap_oop(p);
-+  if (!oopDesc::is_null(heap_oop)) {
-+    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-+    if (obj->is_instanceKlass()) {
-+      klassOop klass = (klassOop)obj;
-+      // DCEVM: note: can overwrite owner of old_klass constants pool with new_klass, so we need to fix it back later
-+      if (klass->new_version() != NULL && klass->new_version()->klass_part()->is_redefining()) {
-+        obj = klass->klass_part()->new_version();
-+        oopDesc::encode_store_heap_oop_not_null(p, obj);
-+      }
-+    } else if (obj->blueprint()->newest_version() == SystemDictionary::Class_klass()->klass_part()->newest_version()) {
-+      // update references to java.lang.Class to point to newest version. Only update references to non-primitive
-+      // java.lang.Class instances.
-+      klassOop klass_oop = java_lang_Class::as_klassOop(obj);
-+      if (klass_oop != NULL) {
-+        if (klass_oop->new_version() != NULL && klass_oop->new_version()->klass_part()->is_redefining()) {
-+          obj = klass_oop->new_version()->java_mirror();
-+        } else if (klass_oop->klass_part()->is_redefining()) {
-+          obj = klass_oop->java_mirror();
-+        }
-+        oopDesc::encode_store_heap_oop_not_null(p, obj);
-+
-+
-+        // FIXME: DCEVM: better implementation?
-+        // Starting from JDK 7 java_mirror can be kept in the regular heap. Therefore, it is possible
-+        // that new java_mirror is in the young generation whereas p is in tenured generation. In that
-+        // case we need to run write barrier to make sure card table is properly updated. This will
-+        // allow JVM to detect reference in tenured generation properly during young generation GC.
-+        if (Universe::heap()->is_in_reserved(p)) {
-+          if (GenCollectedHeap::heap()->is_in_young(obj)) {
-+            GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
-+            assert(rs->rs_kind() == GenRemSet::CardTable, "Wrong rem set kind.");
-+            CardTableRS* _rs = (CardTableRS*)rs;
-+            _rs->inline_write_ref_field_gc(p, obj);
-+          }
-+        }
-+      }
-     }
-+  }
-+}
+-    }
++  // Deoptimize all compiled code that depends on this class
++  flush_dependent_code(instanceKlassHandle(Thread::current(), (klassOop)NULL), Thread::current());
  
 -    u2 element_name_index = rewrite_cp_ref_in_annotation_data(
 -                              annotations_typeArray, byte_i_ref,
@@ -7946,19 +8107,19 @@
 -  } // end for each component
 -  assert(num_element_value_pairs == calc_num_element_value_pairs,
 -    "sanity check");
-+void VM_RedefineClasses::swap_marks(oop first, oop second) {
-+  markOop first_mark = first->mark();
-+  markOop second_mark = second->mark();
-+  first->set_mark(second_mark);
-+  second->set_mark(first_mark);
-+}
++  // Adjust constantpool caches and vtables for all classes
++  // that reference methods of the evolved class.
++  SystemDictionary::classes_do(adjust_cpool_cache, Thread::current());
  
 -  return true;
 -} // end rewrite_cp_refs_in_annotation_struct()
-+void VM_RedefineClasses::doit() {
-+  Thread *thread = Thread::current();
++  RC_TIMER_STOP(_timer_prepare_redefinition);
++  RC_TIMER_START(_timer_redefinition);
  
-+  RC_TRACE(0x00000001, ("Entering doit!"));
++    class ChangePointersOopClosure : public OopClosure {
++      virtual void do_oop(oop* o) {
++        do_oop_work(o);
++      }
  
 -// Rewrite a constant pool reference at the current position in
 -// annotations_typeArray if needed. Returns the original constant
@@ -7980,8 +8141,12 @@
 -  byte_i_ref += 2;
 -  return old_cp_index;
 -}
++      virtual void do_oop(narrowOop* o) {
++        do_oop_work(o);
++      }
++    };
  
-+  if ((_max_redefinition_flags & Klass::RemoveSuperType) != 0) {
++    class ChangePointersObjectClosure : public ObjectClosure {
  
 -// Rewrite constant pool references in the element_value portion of an
 -// annotations_typeArray. This "structure" is from section 4.8.15.1 of
@@ -8006,27 +8171,17 @@
 -//
 -bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
 -       typeArrayHandle annotations_typeArray, int &byte_i_ref, TRAPS) {
-+    RC_TIMER_START(_timer_check_type);
++    private:
  
 -  if ((byte_i_ref + 1) > annotations_typeArray->length()) {
 -    // not enough room for a tag let alone the rest of an element_value
 -    RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -      ("length() is too small for a tag"));
 -    return false;
-+    if (!check_type_consistency()) {
-+      // (tw) TODO: Rollback the class redefinition
-+      rollback();
-+      RC_TRACE(0x00000001, ("Detected type inconsistency!"));
-+      _result = JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
-+      RC_TIMER_STOP(_timer_check_type);
-+      return;
-+    }
-+
-+    RC_TIMER_STOP(_timer_check_type);
-+
-+  } else {
-+    RC_TRACE(0x00000001, ("No type narrowing => skipping check for type inconsistency"));
-   }
+-  }
++      OopClosure *_closure;
++      bool _needs_instance_update;
++      GrowableArray<oop> *_updated_oops;
  
 -  u1 tag = annotations_typeArray->byte_at(byte_i_ref);
 -  byte_i_ref++;
@@ -8049,88 +8204,68 @@
 -    {
 -      // For the above tag values (including the BaseType values),
 -      // value.const_value_index is right union field.
-+  if (UseMethodForwardPoints) {
-+    RC_TRACE(0x00000001, ("Check stack for forwarding methods to new version"));
-+    method_forwarding();
-+  }
++    public:
++      ChangePointersObjectClosure(OopClosure *closure) : _closure(closure), _needs_instance_update(false), _updated_oops(NULL) {}
  
 -      if ((byte_i_ref + 2) > annotations_typeArray->length()) {
 -        // not enough room for a const_value_index
 -        RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -          ("length() is too small for a const_value_index"));
 -        return false;
--      }
-+  if (UseSharedSpaces) {
-+    // Sharing is enabled so we remap the shared readonly space to
-+    // shared readwrite, private just in case we need to redefine
-+    // a shared class. We do the remap during the doit() phase of
-+    // the safepoint to be safer.
-+    if (!CompactingPermGenGen::remap_shared_readonly_as_readwrite()) {
-+      RC_TRACE(0x00000001, ("failed to remap shared readonly space to readwrite, private"));
-+      _result = JVMTI_ERROR_INTERNAL;
-+      return;
-+    }
-+  }
++      bool needs_instance_update() {
++        return _needs_instance_update;
+       }
  
 -      u2 const_value_index = rewrite_cp_ref_in_annotation_data(
 -                               annotations_typeArray, byte_i_ref,
 -                               "mapped old const_value_index=%d", THREAD);
-+  RC_TIMER_START(_timer_prepare_redefinition);
-+  for (int i = 0; i < _new_classes->length(); i++) {
-+    redefine_single_class(_new_classes->at(i), thread);
-+  }
- 
+-
 -      RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -        ("const_value_index=%d", const_value_index));
 -    } break;
-+  // Deoptimize all compiled code that depends on this class
-+  flush_dependent_code(instanceKlassHandle(Thread::current(), (klassOop)NULL), Thread::current());
++      GrowableArray<oop> *updated_oops() { return _updated_oops; }
  
 -    case 'e':
 -    {
 -      // for the above tag value, value.enum_const_value is right union field
-+  // Adjust constantpool caches and vtables for all classes
-+  // that reference methods of the evolved class.
-+  SystemDictionary::classes_do(adjust_cpool_cache, Thread::current());
-+
-+  RC_TIMER_STOP(_timer_prepare_redefinition);
-+  RC_TIMER_START(_timer_redefinition);
- 
+-
 -      if ((byte_i_ref + 4) > annotations_typeArray->length()) {
--        // not enough room for a enum_const_value
--        RC_TRACE_WITH_THREAD(0x02000000, THREAD,
--          ("length() is too small for a enum_const_value"));
--        return false;
-+    class ChangePointersOopClosure : public OopClosure {
-+      virtual void do_oop(oop* o) {
-+        do_oop_work(o);
-       }
- 
+-        // not enough room for a enum_const_value
+-        RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+-          ("length() is too small for a enum_const_value"));
+-        return false;
+-      }
+-
 -      u2 type_name_index = rewrite_cp_ref_in_annotation_data(
 -                             annotations_typeArray, byte_i_ref,
 -                             "mapped old type_name_index=%d", THREAD);
-+      virtual void do_oop(narrowOop* o) {
-+        do_oop_work(o);
-+      }
-+    };
++      virtual void do_object(oop obj) {
++        if (!obj->is_instanceKlass()) {
++          obj->oop_iterate(_closure);
++          
++          if (obj->blueprint()->is_redefining()) {
  
 -      u2 const_name_index = rewrite_cp_ref_in_annotation_data(
 -                              annotations_typeArray, byte_i_ref,
 -                              "mapped old const_name_index=%d", THREAD);
-+    class ChangePointersObjectClosure : public ObjectClosure {
++            if (obj->blueprint()->check_redefinition_flag(Klass::HasInstanceTransformer)) {
++              if (_updated_oops == NULL) {
++                _updated_oops = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(100, true);
++              }
++              _updated_oops->append(obj);
++            }
  
 -      RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -        ("type_name_index=%d  const_name_index=%d", type_name_index,
 -        const_name_index));
 -    } break;
-+    private:
++            if(obj->blueprint()->update_information() != NULL || obj->is_perm()) {
  
 -    case 'c':
 -    {
 -      // for the above tag value, value.class_info_index is right union field
-+      OopClosure *_closure;
-+      bool _needs_instance_update;
-+      GrowableArray<oop> *_updated_oops;
++              assert(obj->blueprint()->old_version() != NULL, "must have old version");
++              obj->set_klass_no_check(obj->blueprint()->old_version());
  
 -      if ((byte_i_ref + 2) > annotations_typeArray->length()) {
 -        // not enough room for a class_info_index
@@ -8156,8 +8291,16 @@
 -        return false;
 -      }
 -      break;
-+    public:
-+      ChangePointersObjectClosure(OopClosure *closure) : _closure(closure), _needs_instance_update(false), _updated_oops(NULL) {}
++              if (obj->size() != obj->size_given_klass(obj->blueprint()->new_version()->klass_part()) || obj->is_perm()) {
++                // We need an instance update => set back to old klass
++                _needs_instance_update = true;
++
++              } else {
++                MarkSweep::update_fields(obj, obj);
++                assert(obj->blueprint()->is_redefining(), "update fields resets the klass");
++              }
++            }
++          }
  
 -    case '[':
 -    {
@@ -8183,59 +8326,6 @@
 -            ("bad nested element_value at %d", calc_num_values));
 -          // propagate failure back to caller
 -          return false;
--        }
-+      bool needs_instance_update() {
-+        return _needs_instance_update;
-       }
--      assert(num_values == calc_num_values, "sanity check");
--    } break;
- 
--    default:
--      RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("bad tag=0x%x", tag));
--      return false;
--  } // end decode tag field
-+      GrowableArray<oop> *updated_oops() { return _updated_oops; }
- 
--  return true;
--} // end rewrite_cp_refs_in_element_value()
-+      virtual void do_object(oop obj) {
-+        if (!obj->is_instanceKlass()) {
-+          obj->oop_iterate(_closure);
-+          
-+          if (obj->blueprint()->is_redefining()) {
-+
-+            if (obj->blueprint()->check_redefinition_flag(Klass::HasInstanceTransformer)) {
-+              if (_updated_oops == NULL) {
-+                _updated_oops = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(100, true);
-+              }
-+              _updated_oops->append(obj);
-+            }
- 
-+            if(obj->blueprint()->update_information() != NULL || obj->is_perm()) {
- 
--// Rewrite constant pool references in a fields_annotations field.
--bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
--       instanceKlassHandle scratch_class, TRAPS) {
-+              assert(obj->blueprint()->old_version() != NULL, "must have old version");
-+              obj->set_klass_no_check(obj->blueprint()->old_version());
- 
--  objArrayHandle fields_annotations(THREAD,
--    scratch_class->fields_annotations());
-+              if (obj->size() != obj->size_given_klass(obj->blueprint()->new_version()->klass_part()) || obj->is_perm()) {
-+                // We need an instance update => set back to old klass
-+                _needs_instance_update = true;
-+
-+              } else {
-+                MarkSweep::update_fields(obj, obj);
-+                assert(obj->blueprint()->is_redefining(), "update fields resets the klass");
-+              }
-+            }
-+          }
- 
--  if (fields_annotations.is_null() || fields_annotations->length() == 0) {
--    // no fields_annotations so nothing to do
--    return true;
--  }
 +        } else {
 +          instanceKlass *klass = instanceKlass::cast((klassOop)obj);
 +          if (klass->is_redefining()) {
@@ -8252,51 +8342,46 @@
 +          // idubrov: need to check if there is a test to verify that fields referencing class being updated
 +          // idubrov: will get new version of that class
 +          //klass->iterate_static_fields(_closure);
-+        }
-+      }
+         }
+       }
+-      assert(num_values == calc_num_values, "sanity check");
+-    } break;
 +    };
  
--  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
--    ("fields_annotations length=%d", fields_annotations->length()));
+-    default:
+-      RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("bad tag=0x%x", tag));
+-      return false;
+-  } // end decode tag field
 +    ChangePointersOopClosure oopClosure;
 +    ChangePointersObjectClosure objectClosure(&oopClosure);
  
--  for (int i = 0; i < fields_annotations->length(); i++) {
--    typeArrayHandle field_annotations(THREAD,
--      (typeArrayOop)fields_annotations->obj_at(i));
--    if (field_annotations.is_null() || field_annotations->length() == 0) {
--      // this field does not have any annotations so skip it
--      continue;
+-  return true;
+-} // end rewrite_cp_refs_in_element_value()
 +    {
 +      SharedHeap::heap()->gc_prologue(true);
 +      Universe::root_oops_do(&oopClosure);
 +      Universe::heap()->object_iterate(&objectClosure);
 +      SharedHeap::heap()->gc_epilogue(false);
-     }
++    }
  
--    int byte_i = 0;  // byte index into field_annotations
--    if (!rewrite_cp_refs_in_annotations_typeArray(field_annotations, byte_i,
--           THREAD)) {
--      RC_TRACE_WITH_THREAD(0x02000000, THREAD,
--        ("bad field_annotations at %d", i));
--      // propagate failure back to caller
--      return false;
 +    // Swap marks to have same hashcodes
 +    for (int i=0; i<_new_classes->length(); i++) {
 +      swap_marks(_new_classes->at(i)(), _new_classes->at(i)->old_version());
 +      swap_marks(_new_classes->at(i)->java_mirror(), _new_classes->at(i)->old_version()->java_mirror());
-     }
--  }
++    }
  
--  return true;
--} // end rewrite_cp_refs_in_fields_annotations()
+-// Rewrite constant pool references in a fields_annotations field.
+-bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
+-       instanceKlassHandle scratch_class, TRAPS) {
 +    _updated_oops = objectClosure.updated_oops();
  
+-  objArrayHandle fields_annotations(THREAD,
+-    scratch_class->fields_annotations());
 +  if (objectClosure.needs_instance_update()){
  
--// Rewrite constant pool references in a methods_annotations field.
--bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
--       instanceKlassHandle scratch_class, TRAPS) {
+-  if (fields_annotations.is_null() || fields_annotations->length() == 0) {
+-    // no fields_annotations so nothing to do
+-    return true;
 +    // Do a full garbage collection to update the instance sizes accordingly
 +    RC_TRACE(0x00000001, ("Before performing full GC!"));
 +    Universe::set_redefining_gc_run(true);
@@ -8306,24 +8391,36 @@
 +    notify_gc_end();
 +    Universe::set_redefining_gc_run(false);
 +    RC_TRACE(0x00000001, ("GC done!"));
-+  }
+   }
  
--  objArrayHandle methods_annotations(THREAD,
--    scratch_class->methods_annotations());
+-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+-    ("fields_annotations length=%d", fields_annotations->length()));
+-
+-  for (int i = 0; i < fields_annotations->length(); i++) {
+-    typeArrayHandle field_annotations(THREAD,
+-      (typeArrayOop)fields_annotations->obj_at(i));
+-    if (field_annotations.is_null() || field_annotations->length() == 0) {
+-      // this field does not have any annotations so skip it
+-      continue;
+-    }
  
--  if (methods_annotations.is_null() || methods_annotations->length() == 0) {
--    // no methods_annotations so nothing to do
--    return true;
+-    int byte_i = 0;  // byte index into field_annotations
+-    if (!rewrite_cp_refs_in_annotations_typeArray(field_annotations, byte_i,
+-           THREAD)) {
+-      RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+-        ("bad field_annotations at %d", i));
+-      // propagate failure back to caller
+-      return false;
 +  if (RC_TRACE_ENABLED(0x00000001)) {
 +    if (_updated_oops != NULL) {
 +      RC_TRACE(0x00000001, ("%d object(s) updated!", _updated_oops->length()));
 +    } else {
 +      RC_TRACE(0x00000001, ("No objects updated!"));
-+    }
+     }
    }
  
--  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
--    ("methods_annotations length=%d", methods_annotations->length()));
+-  return true;
+-} // end rewrite_cp_refs_in_fields_annotations()
 +  // Unmark klassOops as "redefining"
 +  for (int i=0; i<_new_classes->length(); i++) {
 +    klassOop cur = _new_classes->at(i)();
@@ -8331,6 +8428,35 @@
 +    _new_classes->at(i)->clear_update_information();
 +    _new_classes->at(i)->update_supers_to_newest_version();
  
++    if (((instanceKlass *)cur->klass_part()->old_version()->klass_part())->array_klasses() != NULL) {
++      update_array_classes_to_newest_version(((instanceKlass *)cur->klass_part()->old_version()->klass_part())->array_klasses());
+ 
+-// Rewrite constant pool references in a methods_annotations field.
+-bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
+-       instanceKlassHandle scratch_class, TRAPS) {
++      // Transfer the array classes, otherwise we might get cast exceptions when casting array types.
++      ((instanceKlass*)cur->klass_part())->set_array_klasses(((instanceKlass*)cur->klass_part()->old_version()->klass_part())->array_klasses());
+ 
+-  objArrayHandle methods_annotations(THREAD,
+-    scratch_class->methods_annotations());
++      oop new_mirror = _new_classes->at(i)->java_mirror();
++      oop old_mirror = _new_classes->at(i)->old_version()->java_mirror();
++      java_lang_Class::set_array_klass(new_mirror, java_lang_Class::array_klass(old_mirror));
++    }
++  }
+ 
+-  if (methods_annotations.is_null() || methods_annotations->length() == 0) {
+-    // no methods_annotations so nothing to do
+-    return true;
++  for (int i=T_BOOLEAN; i<=T_LONG; i++) {
++    update_array_classes_to_newest_version(Universe::typeArrayKlassObj((BasicType)i));
+   }
+ 
+-  RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+-    ("methods_annotations length=%d", methods_annotations->length()));
++  // Disable any dependent concurrent compilations
++  SystemDictionary::notice_modification();
+ 
 -  for (int i = 0; i < methods_annotations->length(); i++) {
 -    typeArrayHandle method_annotations(THREAD,
 -      (typeArrayOop)methods_annotations->obj_at(i));
@@ -8338,8 +8464,9 @@
 -      // this method does not have any annotations so skip it
 -      continue;
 -    }
-+    if (((instanceKlass *)cur->klass_part()->old_version()->klass_part())->array_klasses() != NULL) {
-+      update_array_classes_to_newest_version(((instanceKlass *)cur->klass_part()->old_version()->klass_part())->array_klasses());
++  // Set flag indicating that some invariants are no longer true.
++  // See jvmtiExport.hpp for detailed explanation.
++  JvmtiExport::set_has_redefined_a_class();
  
 -    int byte_i = 0;  // byte index into method_annotations
 -    if (!rewrite_cp_refs_in_annotations_typeArray(method_annotations, byte_i,
@@ -8348,23 +8475,17 @@
 -        ("bad method_annotations at %d", i));
 -      // propagate failure back to caller
 -      return false;
-+      // Transfer the array classes, otherwise we might get cast exceptions when casting array types.
-+      ((instanceKlass*)cur->klass_part())->set_array_klasses(((instanceKlass*)cur->klass_part()->old_version()->klass_part())->array_klasses());
-+
-+      oop new_mirror = _new_classes->at(i)->java_mirror();
-+      oop old_mirror = _new_classes->at(i)->old_version()->java_mirror();
-+      java_lang_Class::set_array_klass(new_mirror, java_lang_Class::array_klass(old_mirror));
-     }
-   }
+-    }
+-  }
++  // Clean up caches in the compiler interface and compiler threads
++  CompileBroker::cleanup_after_redefinition();
  
 -  return true;
 -} // end rewrite_cp_refs_in_methods_annotations()
-+  for (int i=T_BOOLEAN; i<=T_LONG; i++) {
-+    update_array_classes_to_newest_version(Universe::typeArrayKlassObj((BasicType)i));
-+  }
++#ifdef ASSERT
  
-+  // Disable any dependent concurrent compilations
-+  SystemDictionary::notice_modification();
++  // Universe::verify();
++  // JNIHandles::verify();
  
 -// Rewrite constant pool references in a methods_parameter_annotations
 -// field. This "structure" is adapted from the
@@ -8381,14 +8502,13 @@
 -//
 -bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
 -       instanceKlassHandle scratch_class, TRAPS) {
-+  // Set flag indicating that some invariants are no longer true.
-+  // See jvmtiExport.hpp for detailed explanation.
-+  JvmtiExport::set_has_redefined_a_class();
++  SystemDictionary::classes_do(check_class, thread);
++#endif
  
 -  objArrayHandle methods_parameter_annotations(THREAD,
 -    scratch_class->methods_parameter_annotations());
-+  // Clean up caches in the compiler interface and compiler threads
-+  CompileBroker::cleanup_after_redefinition();
++  update_active_methods();
++  RC_TIMER_STOP(_timer_redefinition);
  
 -  if (methods_parameter_annotations.is_null()
 -      || methods_parameter_annotations->length() == 0) {
@@ -8415,21 +8535,18 @@
 -        ("length() is too small for a num_parameters field at %d", i));
 -      return false;
 -    }
-+#ifdef ASSERT
++}
  
 -    int byte_i = 0;  // byte index into method_parameter_annotations
-+  // Universe::verify();
-+  // JNIHandles::verify();
++void VM_RedefineClasses::update_array_classes_to_newest_version(klassOop smallest_dimension) {
  
 -    u1 num_parameters = method_parameter_annotations->byte_at(byte_i);
 -    byte_i++;
-+  SystemDictionary::classes_do(check_class, thread);
-+#endif
++  arrayKlass *curArrayKlass = arrayKlass::cast(smallest_dimension);
++  assert(curArrayKlass->lower_dimension() == NULL, "argument must be smallest dimension");
  
 -    RC_TRACE_WITH_THREAD(0x02000000, THREAD,
 -      ("num_parameters=%d", num_parameters));
-+  update_active_methods();
-+  RC_TIMER_STOP(_timer_redefinition);
  
 -    int calc_num_parameters = 0;
 -    for (; calc_num_parameters < num_parameters; calc_num_parameters++) {
@@ -8440,17 +8557,23 @@
 -        // propagate failure back to caller
 -        return false;
 -      }
--    }
--    assert(num_parameters == calc_num_parameters, "sanity check");
--  }
-+}
++  while (curArrayKlass != NULL) {
++    klassOop higher_dimension = curArrayKlass->higher_dimension();
++    klassOop lower_dimension = curArrayKlass->lower_dimension();
++    curArrayKlass->update_supers_to_newest_version();
++
++    curArrayKlass = NULL;
++    if (higher_dimension != NULL) {
++      curArrayKlass = arrayKlass::cast(higher_dimension);
+     }
+-    assert(num_parameters == calc_num_parameters, "sanity check");
+   }
  
 -  return true;
 -} // end rewrite_cp_refs_in_methods_parameter_annotations()
-+void VM_RedefineClasses::update_array_classes_to_newest_version(klassOop smallest_dimension) {
++}
  
-+  arrayKlass *curArrayKlass = arrayKlass::cast(smallest_dimension);
-+  assert(curArrayKlass->lower_dimension() == NULL, "argument must be smallest dimension");
++void VM_RedefineClasses::doit_epilogue() {
  
 -// Rewrite constant pool references in a methods_default_annotations
 -// field. This "structure" is adapted from the AnnotationDefault_attribute
@@ -8462,13 +8585,11 @@
 -//
 -bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
 -       instanceKlassHandle scratch_class, TRAPS) {
++  RC_TIMER_START(_timer_vm_op_epilogue);
  
 -  objArrayHandle methods_default_annotations(THREAD,
 -    scratch_class->methods_default_annotations());
-+  while (curArrayKlass != NULL) {
-+    klassOop higher_dimension = curArrayKlass->higher_dimension();
-+    klassOop lower_dimension = curArrayKlass->lower_dimension();
-+    curArrayKlass->update_supers_to_newest_version();
++  unlock_threads();
  
 -  if (methods_default_annotations.is_null()
 -      || methods_default_annotations->length() == 0) {
@@ -8497,16 +8618,16 @@
 -        ("bad default element_value at %d", i));
 -      // propagate failure back to caller
 -      return false;
-+    curArrayKlass = NULL;
-+    if (higher_dimension != NULL) {
-+      curArrayKlass = arrayKlass::cast(higher_dimension);
-     }
-   }
+-    }
+-  }
++  ResourceMark mark;
  
 -  return true;
 -} // end rewrite_cp_refs_in_methods_default_annotations()
--
-+}
++  VM_GC_Operation::doit_epilogue();
++  RC_TRACE(0x00000001, ("GC Operation epilogue finished! "));
+ 
++  GrowableArray<methodHandle> instanceTransformerMethods;
  
 -// Rewrite constant pool references in the method's stackmap table.
 -// These "structures" are adapted from the StackMapTable_attribute that
@@ -8521,12 +8642,23 @@
 -//
 -void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table(
 -       methodHandle method, TRAPS) {
-+void VM_RedefineClasses::doit_epilogue() {
++  // Call static transformers
++  for (int i=0; i<_new_classes->length(); i++) {
++    
++    instanceKlassHandle klass = _new_classes->at(i);
  
 -  if (!method->has_stackmap_table()) {
 -    return;
 -  }
-+  RC_TIMER_START(_timer_vm_op_epilogue);
++    // Transfer init state
++    if (klass->old_version() != NULL) {
++      instanceKlass::ClassState state = instanceKlass::cast(klass->old_version())->init_state();
++      if (state > instanceKlass::linked) {
++        klass->initialize(Thread::current());
++      }
++    }
++    
++    // Find instance transformer method
  
 -  typeArrayOop stackmap_data = method->stackmap_data();
 -  address stackmap_p = (address)stackmap_data->byte_at_addr(0);
@@ -8731,7 +8863,7 @@
 -  case ITEM_UninitializedThis:
 -    // nothing more to do for the above tag types
 -    break;
-+  unlock_threads();
++    if (klass->check_redefinition_flag(Klass::HasInstanceTransformer)) {
  
 -  // Object_variable_info {
 -  //   u1 tag = ITEM_Object; /* 7 */
@@ -8763,7 +8895,23 @@
 -    assert(stackmap_p_ref + 2 <= stackmap_end, "no room for offset");
 -    stackmap_p_ref += 2;
 -    break;
-+  ResourceMark mark;
++      RC_TRACE(0x00008000, ("Call instance transformer of %s instance", klass->name()->as_C_string()));
++      klassOop cur_klass = klass();
++      while (cur_klass != NULL) {
++        methodOop method = ((instanceKlass*)cur_klass->klass_part())->find_method(vmSymbols::transformer_name(), vmSymbols::void_method_signature());
++        if (method != NULL) {
++          methodHandle instanceTransformerMethod(method);
++          instanceTransformerMethods.append(instanceTransformerMethod);
++          break;
++        } else {
++          cur_klass = cur_klass->klass_part()->super();
++        }
++      }
++      assert(cur_klass != NULL, "must have instance transformer method");
++    } else {
++      instanceTransformerMethods.append(methodHandle(Thread::current(), NULL));
++    }
++  }
  
 -  default:
 -    RC_TRACE_WITH_THREAD(0x04000000, THREAD,
@@ -8772,10 +8920,9 @@
 -    break;
 -  } // end switch (tag)
 -} // end rewrite_cp_refs_in_verification_type_info()
-+  VM_GC_Operation::doit_epilogue();
-+  RC_TRACE(0x00000001, ("GC Operation epilogue finished! "));
  
-+  GrowableArray<methodHandle> instanceTransformerMethods;
++  // Call instance transformers
++  if (_updated_oops != NULL) {
  
 -// Change the constant pool associated with klass scratch_class to
 -// scratch_cp. If shrink is true, then scratch_cp_length elements
@@ -8783,30 +8930,30 @@
 -// smaller constant pool is associated with scratch_class.
 -void VM_RedefineClasses::set_new_constant_pool(
 -       instanceKlassHandle scratch_class, constantPoolHandle scratch_cp,
--       int scratch_cp_length, bool shrink, TRAPS) {
--  assert(!shrink || scratch_cp->length() >= scratch_cp_length, "sanity check");
--
--  if (shrink) {
--    // scratch_cp is a merged constant pool and has enough space for a
--    // worst case merge situation. We want to associate the minimum
--    // sized constant pool with the klass to save space.
--    constantPoolHandle smaller_cp(THREAD,
--      oopFactory::new_constantPool(scratch_cp_length,
--                                   oopDesc::IsUnsafeConc,
--                                   THREAD));
--    // preserve orig_length() value in the smaller copy
--    int orig_length = scratch_cp->orig_length();
--    assert(orig_length != 0, "sanity check");
--    smaller_cp->set_orig_length(orig_length);
--    scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
--    scratch_cp = smaller_cp;
--    smaller_cp()->set_is_conc_safe(true);
--  }
--
--  // attach new constant pool to klass
--  scratch_cp->set_pool_holder(scratch_class());
+-       int scratch_cp_length, TRAPS) {
+-  assert(scratch_cp->length() >= scratch_cp_length, "sanity check");
+-
+-  // scratch_cp is a merged constant pool and has enough space for a
+-  // worst case merge situation. We want to associate the minimum
+-  // sized constant pool with the klass to save space.
+-  constantPoolHandle smaller_cp(THREAD,
+-    oopFactory::new_constantPool(scratch_cp_length,
+-                                 oopDesc::IsUnsafeConc,
+-                                 THREAD));
+-  // preserve orig_length() value in the smaller copy
+-  int orig_length = scratch_cp->orig_length();
+-  assert(orig_length != 0, "sanity check");
+-  smaller_cp->set_orig_length(orig_length);
 -
 -  // attach klass to new constant pool
+-  // reference to the cp holder is needed for copy_operands()
+-  smaller_cp->set_pool_holder(scratch_class());
+-
+-  scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
+-  scratch_cp = smaller_cp;
+-  smaller_cp()->set_is_conc_safe(true);
+-
+-  // attach new constant pool to klass
 -  scratch_class->set_constants(scratch_cp());
 -
 -  int i;  // for portability
@@ -8977,20 +9124,12 @@
 -  } // end for each method
 -  assert(scratch_cp()->is_conc_safe(), "Just checking");
 -} // end set_new_constant_pool()
-+  // Call static transformers
-+  for (int i=0; i<_new_classes->length(); i++) {
-+    
-+    instanceKlassHandle klass = _new_classes->at(i);
++    for (int i=0; i<_updated_oops->length(); i++) {
++      assert(_updated_oops->at(i) != NULL, "must not be null!");
++      Handle cur(_updated_oops->at(i));
++      instanceKlassHandle klass(cur->klass());
  
-+    // Transfer init state
-+    if (klass->old_version() != NULL) {
-+      instanceKlass::ClassState state = instanceKlass::cast(klass->old_version())->init_state();
-+      if (state > instanceKlass::linked) {
-+        klass->initialize(Thread::current());
-+      }
-+    }
-+    
-+    // Find instance transformer method
++      if (klass->check_redefinition_flag(Klass::HasInstanceTransformer)) {
  
 -// Unevolving classes may point to methods of the_class directly
 -// from their constant pool caches, itables, and/or vtables. We
@@ -9005,7 +9144,7 @@
 -  if (k->oop_is_instance()) {
 -    HandleMark hm(THREAD);
 -    instanceKlass *ik = (instanceKlass *) k;
-+    if (klass->check_redefinition_flag(Klass::HasInstanceTransformer)) {
++        methodHandle method = instanceTransformerMethods.at(klass->redefinition_index());
  
 -    // HotSpot specific optimization! HotSpot does not currently
 -    // support delegation from the bootstrap class loader to a
@@ -9023,23 +9162,16 @@
 -           instanceKlass::cast(_the_class_oop)->class_loader() != NULL;
 -    if (is_user_defined && ik->class_loader() == NULL) {
 -      return;
-+      RC_TRACE(0x00008000, ("Call instance transformer of %s instance", klass->name()->as_C_string()));
-+      klassOop cur_klass = klass();
-+      while (cur_klass != NULL) {
-+        methodOop method = ((instanceKlass*)cur_klass->klass_part())->find_method(vmSymbols::transformer_name(), vmSymbols::void_method_signature());
-+        if (method != NULL) {
-+          methodHandle instanceTransformerMethod(method);
-+          instanceTransformerMethods.append(instanceTransformerMethod);
-+          break;
-+        } else {
-+          cur_klass = cur_klass->klass_part()->super();
-+        }
-+      }
-+      assert(cur_klass != NULL, "must have instance transformer method");
-+    } else {
-+      instanceTransformerMethods.append(methodHandle(Thread::current(), NULL));
-     }
-+  }
+-    }
++        RC_TRACE(0x00008000, ("executing transformer method"));
++        
++        Thread *__the_thread__ = Thread::current();
++        JavaValue result(T_VOID);
++        JavaCallArguments args(cur);
++        JavaCalls::call(&result,
++          method,
++          &args,
++          THREAD);
  
 -    // This is a very busy routine. We don't want too much tracing
 -    // printed out.
@@ -9064,7 +9196,15 @@
 -                                          _matching_new_methods,
 -                                          _matching_methods_length,
 -                                          &trace_name_printed);
--    }
++        // TODO: What to do with an exception here?
++        if (HAS_PENDING_EXCEPTION) {
++          Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
++          RC_TRACE(0x00000002, ("exception when executing transformer: '%s'",
++            ex_name->as_C_string()));
++          CLEAR_PENDING_EXCEPTION;
++        }
++      }
+     }
  
 -    // If the current class has an itable and we are either redefining an
 -    // interface or if the current class is a subclass of the_class, then
@@ -9097,8 +9237,9 @@
 -    // that case.
 -    constantPoolHandle other_cp;
 -    constantPoolCacheOop cp_cache;
-+  // Call instance transformers
-+  if (_updated_oops != NULL) {
++    delete _updated_oops;
++    _updated_oops = NULL;
++  }
  
 -    if (k_oop != _the_class_oop) {
 -      // this klass' constant pool cache may need adjustment
@@ -9109,34 +9250,8 @@
 -                                        _matching_new_methods,
 -                                        _matching_methods_length,
 -                                        &trace_name_printed);
-+    for (int i=0; i<_updated_oops->length(); i++) {
-+      assert(_updated_oops->at(i) != NULL, "must not be null!");
-+      Handle cur(_updated_oops->at(i));
-+      instanceKlassHandle klass(cur->klass());
-+
-+      if (klass->check_redefinition_flag(Klass::HasInstanceTransformer)) {
-+
-+        methodHandle method = instanceTransformerMethods.at(klass->redefinition_index());
-+
-+        RC_TRACE(0x00008000, ("executing transformer method"));
-+        
-+        Thread *__the_thread__ = Thread::current();
-+        JavaValue result(T_VOID);
-+        JavaCallArguments args(cur);
-+        JavaCalls::call(&result,
-+          method,
-+          &args,
-+          THREAD);
-+
-+        // TODO: What to do with an exception here?
-+        if (HAS_PENDING_EXCEPTION) {
-+          Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
-+          RC_TRACE(0x00000002, ("exception when executing transformer: '%s'",
-+            ex_name->as_C_string()));
-+          CLEAR_PENDING_EXCEPTION;
-+        }
-       }
-     }
+-      }
+-    }
 -    {
 -      ResourceMark rm(THREAD);
 -      // PreviousVersionInfo objects returned via PreviousVersionWalker
@@ -9159,17 +9274,25 @@
 -        }
 -      } // pvw is cleaned up
 -    } // rm is cleaned up
-+
-+    delete _updated_oops;
-+    _updated_oops = NULL;
-   }
-+
 +  // Free the array of scratch classes
 +  delete _new_classes;
 +  _new_classes = NULL;
 +  RC_TRACE(0x00000001, ("Redefinition finished!"));
 +
 +  RC_TIMER_STOP(_timer_vm_op_epilogue);
++}
++
++bool VM_RedefineClasses::is_modifiable_class(oop klass_mirror) {
++  // classes for primitives cannot be redefined
++  if (java_lang_Class::is_primitive(klass_mirror)) {
++    return false;
++  }
++  klassOop the_class_oop = java_lang_Class::as_klassOop(klass_mirror);
++  // classes for arrays cannot be redefined
++  if (the_class_oop == NULL || !Klass::cast(the_class_oop)->oop_is_instance()) {
++    return false;
+   }
++  return true;
  }
  
 -void VM_RedefineClasses::update_jmethod_ids() {
@@ -9183,17 +9306,16 @@
 -      assert(JNIHandles::resolve_jmethod_id(jmid) == _matching_new_methods[j],
 -             "should be replaced");
 -    }
-+bool VM_RedefineClasses::is_modifiable_class(oop klass_mirror) {
-+  // classes for primitives cannot be redefined
-+  if (java_lang_Class::is_primitive(klass_mirror)) {
-+    return false;
++#ifdef ASSERT
++
++void VM_RedefineClasses::verify_classes(klassOop k_oop_latest, oop initiating_loader, TRAPS) {
++  klassOop k_oop = k_oop_latest;
++  while (k_oop != NULL) {
++
++    instanceKlassHandle k_handle(THREAD, k_oop);
++    Verifier::verify(k_handle, Verifier::ThrowException, true, true, THREAD);
++    k_oop = k_oop->klass_part()->old_version();
    }
-+  klassOop the_class_oop = java_lang_Class::as_klassOop(klass_mirror);
-+  // classes for arrays cannot be redefined
-+  if (the_class_oop == NULL || !Klass::cast(the_class_oop)->oop_is_instance()) {
-+    return false;
-+  }
-+  return true;
  }
  
 -void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
@@ -9289,7 +9411,7 @@
 -      // mark obsolete methods as such
 -      old_method->set_is_obsolete();
 -      obsolete_count++;
-+#ifdef ASSERT
++#endif
  
 -      // obsolete methods need a unique idnum
 -      u2 num = instanceKlass::cast(_the_class_oop)->next_method_idnum();
@@ -9297,31 +9419,6 @@
 -//      u2 old_num = old_method->method_idnum();
 -        old_method->set_method_idnum(num);
 -// TO DO: attach obsolete annotations to obsolete method's new idnum
--      }
--      // With tracing we try not to "yack" too much. The position of
--      // this trace assumes there are fewer obsolete methods than
--      // EMCP methods.
--      RC_TRACE(0x00000100, ("mark %s(%s) as obsolete",
--        old_method->name()->as_C_string(),
--        old_method->signature()->as_C_string()));
--    }
--    old_method->set_is_old();
-+void VM_RedefineClasses::verify_classes(klassOop k_oop_latest, oop initiating_loader, TRAPS) {
-+  klassOop k_oop = k_oop_latest;
-+  while (k_oop != NULL) {
-+
-+    instanceKlassHandle k_handle(THREAD, k_oop);
-+    Verifier::verify(k_handle, Verifier::ThrowException, true, true, THREAD);
-+    k_oop = k_oop->klass_part()->old_version();
-   }
--  for (int i = 0; i < _deleted_methods_length; ++i) {
--    methodOop old_method = _deleted_methods[i];
-+}
- 
--    assert(old_method->vtable_index() < 0,
--           "cannot delete methods with vtable entries");;
-+#endif
-+
 +// Rewrite faster byte-codes back to their slower equivalent. Undoes rewriting happening in templateTable_xxx.cpp
 +// The reason is that once we zero cpool caches, we need to re-resolve all entries again. Faster bytecodes do not
 +// do that, they assume that cache entry is resolved already.
@@ -9351,8 +9448,21 @@
 +            java_code == Bytecodes::_putfield ||
 +            java_code == Bytecodes::_aload_0)) {
 +        *bcp = java_code;
-+      }
-+    }
+       }
+-      // With tracing we try not to "yack" too much. The position of
+-      // this trace assumes there are fewer obsolete methods than
+-      // EMCP methods.
+-      RC_TRACE(0x00000100, ("mark %s(%s) as obsolete",
+-        old_method->name()->as_C_string(),
+-        old_method->signature()->as_C_string()));
+     }
+-    old_method->set_is_old();
+-  }
+-  for (int i = 0; i < _deleted_methods_length; ++i) {
+-    methodOop old_method = _deleted_methods[i];
+-
+-    assert(old_method->vtable_index() < 0,
+-           "cannot delete methods with vtable entries");;
  
 -    // Mark all deleted methods as old and obsolete
 -    old_method->set_is_old();
@@ -9598,7 +9708,7 @@
  // Deoptimize all compiled code that depends on this class.
  //
  // If the can_redefine_classes capability is obtained in the onload
-@@ -2964,7 +2677,10 @@
+@@ -3101,7 +2677,10 @@
  
    // All dependencies have been recorded from startup or this is a second or
    // subsequent use of RedefineClasses
@@ -9610,7 +9720,7 @@
      Universe::flush_evol_dependents_on(k_h);
    } else {
      CodeCache::mark_all_nmethods_for_deoptimization();
-@@ -2987,10 +2703,10 @@
+@@ -3124,10 +2703,10 @@
    methodOop old_method;
    methodOop new_method;
  
@@ -9625,7 +9735,7 @@
  
    _matching_methods_length = 0;
    _deleted_methods_length  = 0;
-@@ -3005,36 +2721,36 @@
+@@ -3142,36 +2721,36 @@
        }
        // New method at the end
        new_method = (methodOop) _new_methods->obj_at(nj);
@@ -9669,7 +9779,7 @@
            ++oj;
          }
        }
-@@ -3042,6 +2758,8 @@
+@@ -3179,6 +2758,8 @@
    }
    assert(_matching_methods_length + _deleted_methods_length == _old_methods->length(), "sanity");
    assert(_matching_methods_length + _added_methods_length == _new_methods->length(), "sanity");
@@ -9678,7 +9788,7 @@
  }
  
  
-@@ -3049,287 +2767,184 @@
+@@ -3186,297 +2767,184 @@
  // Install the redefinition of a class:
  //    - house keeping (flushing breakpoints and caches, deoptimizing
  //      dependent compiled code)
@@ -9979,6 +10089,16 @@
 +  assert(the_new_class->old_version() != NULL, "Must not be null");
 +  assert(the_new_class->old_version()->klass_part()->new_version() == the_new_class(), "Must equal");
  
+-  // JSR-292 support
+-  MemberNameTable* mnt = the_class->member_names();
+-  if (mnt != NULL) {
+-    bool trace_name_printed = false;
+-    mnt->adjust_method_entries(_matching_old_methods,
+-                               _matching_new_methods,
+-                               _matching_methods_length,
+-                               &trace_name_printed);
+-  }
+-
 -  if (the_class->oop_map_cache() != NULL) {
 -    // Flush references to any obsolete methods from the oop map cache
 -    // so that obsolete methods are not pinned.
@@ -10111,7 +10231,7 @@
  
  // Increment the classRedefinedCount field in the specific instanceKlass
  // and in all direct and indirect subclasses.
-@@ -3338,134 +2953,324 @@
+@@ -3485,134 +2953,324 @@
    klassOop class_oop = java_lang_Class::as_klassOop(class_mirror);
    int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
    java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
@@ -10948,10 +11068,17 @@
    // The instance fields are used to pass information from
    // doit_prologue() to doit() and doit_epilogue().
    jint                        _class_count;
-@@ -370,36 +70,29 @@
+@@ -370,43 +70,29 @@
    // _index_map_p contains any entries.
    int                         _index_map_count;
    intArray *                  _index_map_p;
+-
+-  // _operands_index_map_count is just an optimization for knowing if
+-  // _operands_index_map_p contains any entries.
+-  int                         _operands_cur_length;
+-  int                         _operands_index_map_count;
+-  intArray *                  _operands_index_map_p;
+-
 -  // ptr to _class_count scratch_classes
 -  instanceKlassHandle *       _scratch_classes;
 -  jvmtiError                  _res;
@@ -11002,7 +11129,7 @@
    // Figure out which new methods match old methods in name and signature,
    // which methods have been added, and which are no longer present
    void compute_added_deleted_matching_methods();
-@@ -407,95 +100,100 @@
+@@ -414,103 +100,100 @@
    // Change jmethodIDs to point to the new methods
    void update_jmethod_ids();
  
@@ -11044,16 +11171,24 @@
    // and in all direct and indirect subclasses.
    void increment_class_counter(instanceKlass *ik, TRAPS);
  
--  // Support for constant pool merging (these routines are in alpha
--  // order):
+-  // Support for constant pool merging (these routines are in alpha order):
 -  void append_entry(constantPoolHandle scratch_cp, int scratch_i,
 -    constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+-  void append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+-    constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+-  void finalize_operands_merge(constantPoolHandle merge_cp, TRAPS);
+-  int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i,
+-    constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+-  int find_or_append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+-    constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
 -  int find_new_index(int old_index);
+-  int find_new_operand_index(int old_bootstrap_spec_index);
 -  bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1,
 -    constantPoolHandle cp2, int index2);
 -  bool is_unresolved_string_mismatch(constantPoolHandle cp1, int index1,
 -    constantPoolHandle cp2, int index2);
 -  void map_index(constantPoolHandle scratch_cp, int old_index, int new_index);
+-  void map_operand_index(int old_bootstrap_spec_index, int new_bootstrap_spec_index);
 -  bool merge_constant_pools(constantPoolHandle old_cp,
 -    constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
 -    int *merge_cp_length_p, TRAPS);
@@ -11087,7 +11222,7 @@
 -         address& stackmap_addr_ref, address stackmap_end, u2 frame_i,
 -         u1 frame_size, TRAPS);
 -  void set_new_constant_pool(instanceKlassHandle scratch_class,
--    constantPoolHandle scratch_cp, int scratch_cp_length, bool shrink, TRAPS);
+-    constantPoolHandle scratch_cp, int scratch_cp_length, TRAPS);
  
    void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
  
@@ -11252,7 +11387,7 @@
    KlassHandle   klass (THREAD, SystemDictionary::ClassLoader_klass());
 --- a/src/share/vm/runtime/arguments.cpp
 +++ b/src/share/vm/runtime/arguments.cpp
-@@ -1792,6 +1792,15 @@
+@@ -1831,6 +1831,15 @@
      status = false;
    }
  
@@ -11311,7 +11446,7 @@
      ResourceMark res_mark;
 --- a/src/share/vm/runtime/frame.cpp
 +++ b/src/share/vm/runtime/frame.cpp
-@@ -407,6 +407,12 @@
+@@ -408,6 +408,12 @@
    *interpreter_frame_method_addr() = method;
  }
  
@@ -11324,7 +11459,7 @@
  void frame::interpreter_frame_set_bcx(intptr_t bcx) {
    assert(is_interpreted_frame(), "Not an interpreted frame");
    if (ProfileInterpreter) {
-@@ -422,19 +428,27 @@
+@@ -423,19 +429,27 @@
            // The bcx was just converted from bci to bcp.
            // Convert the mdx in parallel.
            methodDataOop mdo = interpreter_frame_method()->method_data();
@@ -11480,7 +11615,7 @@
  Monitor* SystemDictionary_lock        = NULL;
  Mutex*   PackageTable_lock            = NULL;
  Mutex*   CompiledIC_lock              = NULL;
-@@ -90,6 +91,7 @@
+@@ -91,6 +92,7 @@
  Mutex*   DirtyCardQ_FL_lock           = NULL;
  Monitor* DirtyCardQ_CBL_mon           = NULL;
  Mutex*   Shared_DirtyCardQ_lock       = NULL;
@@ -11488,7 +11623,7 @@
  Mutex*   ParGCRareEvent_lock          = NULL;
  Mutex*   EvacFailureStack_lock        = NULL;
  Mutex*   DerivedPointerTableGC_lock   = NULL;
-@@ -207,6 +209,7 @@
+@@ -208,6 +210,7 @@
      def(HotCardCache_lock          , Mutex  , special  ,   true );
      def(EvacFailureStack_lock      , Mutex  , nonleaf  ,   true );
    }
@@ -11496,7 +11631,7 @@
    def(ParGCRareEvent_lock          , Mutex  , leaf     ,   true );
    def(DerivedPointerTableGC_lock   , Mutex,   leaf,        true );
    def(CodeCache_lock               , Mutex  , special,     true );
-@@ -281,6 +284,7 @@
+@@ -283,6 +286,7 @@
    def(Debug3_lock                  , Mutex  , nonleaf+4,   true );
    def(CompileThread_lock           , Monitor, nonleaf+5,   false);
    def(PeriodicTask_lock            , Monitor, nonleaf+5,   true);
diff --git a/debian/patches/series b/debian/patches/series
index 2aa4e5c..bdb102e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,2 @@
 distro-name.patch
-full-jdk7u55-b13.patch
+full-jdk7u60-b09.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/openjdk-7-jre-dcevm.git



More information about the pkg-java-commits mailing list