8055008: Clean up code that saves the previous versions of redefined classes

Mon, 08 Jan 2018 08:32:04 -0800

author
kevinw
date
Mon, 08 Jan 2018 08:32:04 -0800
changeset 9286
2c4cecfa5ce5
parent 9285
b955bd18e8fe
child 9287
aadefd24f38f

8055008: Clean up code that saves the previous versions of redefined classes
8156137: SIGSEGV in ReceiverTypeData::clean_weak_klass_links
8057570: RedefineClasses() tests fail assert(((Metadata*)obj)->is_valid()) failed: obj is valid
Reviewed-by: coleenp

src/share/vm/classfile/metadataOnStackMark.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/metadataOnStackMark.hpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/klass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/method.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/method.hpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiImpl.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiRedefineClasses.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiRedefineClasses.hpp file | annotate | diff | comparison | revisions
test/runtime/RedefineFinalizer/RedefineFinalizer.java file | annotate | diff | comparison | revisions
test/runtime/RedefineTests/RedefineFinalizer.java file | annotate | diff | comparison | revisions
test/runtime/RedefineTests/RedefineRunningMethods.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/metadataOnStackMark.cpp	Tue Apr 08 09:51:25 2014 +0200
     1.2 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp	Mon Jan 08 08:32:04 2018 -0800
     1.3 @@ -41,13 +41,13 @@
     1.4  // Walk metadata on the stack and mark it so that redefinition doesn't delete
     1.5  // it.  Class unloading also walks the previous versions and might try to
     1.6  // delete it, so this class is used by class unloading also.
     1.7 -MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) {
     1.8 +MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
     1.9    assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    1.10    assert(_used_buffers == NULL, "sanity check");
    1.11    NOT_PRODUCT(_is_active = true;)
    1.12  
    1.13    Threads::metadata_do(Metadata::mark_on_stack);
    1.14 -  if (visit_code_cache) {
    1.15 +  if (has_redefined_a_class) {
    1.16      CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
    1.17    }
    1.18    CompileBroker::mark_on_stack();
     2.1 --- a/src/share/vm/classfile/metadataOnStackMark.hpp	Tue Apr 08 09:51:25 2014 +0200
     2.2 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp	Mon Jan 08 08:32:04 2018 -0800
     2.3 @@ -47,7 +47,7 @@
     2.4    static void retire_buffer(MetadataOnStackBuffer* buffer);
     2.5  
     2.6   public:
     2.7 -  MetadataOnStackMark(bool visit_code_cache);
     2.8 +  MetadataOnStackMark(bool has_redefined_a_class);
     2.9     ~MetadataOnStackMark();
    2.10  
    2.11    static void record(Metadata* m, Thread* thread);
     3.1 --- a/src/share/vm/code/nmethod.cpp	Tue Apr 08 09:51:25 2014 +0200
     3.2 +++ b/src/share/vm/code/nmethod.cpp	Mon Jan 08 08:32:04 2018 -0800
     3.3 @@ -2173,7 +2173,7 @@
     3.4                 "metadata must be found in exactly one place");
     3.5          if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
     3.6            Metadata* md = r->metadata_value();
     3.7 -          f(md);
     3.8 +          if (md != _method) f(md);
     3.9          }
    3.10        } else if (iter.type() == relocInfo::virtual_call_type) {
    3.11          // Check compiledIC holders associated with this nmethod
    3.12 @@ -2199,7 +2199,7 @@
    3.13      f(md);
    3.14    }
    3.15  
    3.16 -  // Visit metadata not embedded in the other places.
    3.17 +  // Call function Method*, not embedded in these other places.
    3.18    if (_method != NULL) f(_method);
    3.19  }
    3.20  
     4.1 --- a/src/share/vm/oops/instanceKlass.cpp	Tue Apr 08 09:51:25 2014 +0200
     4.2 +++ b/src/share/vm/oops/instanceKlass.cpp	Mon Jan 08 08:32:04 2018 -0800
     4.3 @@ -2582,16 +2582,6 @@
     4.4      assert(breakpoints() == 0x0, "should have cleared breakpoints");
     4.5    }
     4.6  
     4.7 -  // deallocate information about previous versions
     4.8 -  if (_previous_versions != NULL) {
     4.9 -    for (int i = _previous_versions->length() - 1; i >= 0; i--) {
    4.10 -      PreviousVersionNode * pv_node = _previous_versions->at(i);
    4.11 -      delete pv_node;
    4.12 -    }
    4.13 -    delete _previous_versions;
    4.14 -    _previous_versions = NULL;
    4.15 -  }
    4.16 -
    4.17    // deallocate the cached class file
    4.18    if (_cached_class_file != NULL) {
    4.19      os::free(_cached_class_file, mtClass);
    4.20 @@ -3187,16 +3177,17 @@
    4.21    st->print(BULLET"field type annotations:  "); fields_type_annotations()->print_value_on(st); st->cr();
    4.22    {
    4.23      bool have_pv = false;
    4.24 -    PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
    4.25 -    for (PreviousVersionNode * pv_node = pvw.next_previous_version();
    4.26 -         pv_node != NULL; pv_node = pvw.next_previous_version()) {
    4.27 +    // previous versions are linked together through the InstanceKlass
    4.28 +    for (InstanceKlass* pv_node = _previous_versions;
    4.29 +         pv_node != NULL;
    4.30 +         pv_node = pv_node->previous_versions()) {
    4.31        if (!have_pv)
    4.32          st->print(BULLET"previous version:  ");
    4.33        have_pv = true;
    4.34 -      pv_node->prev_constant_pool()->print_value_on(st);
    4.35 +      pv_node->constants()->print_value_on(st);
    4.36      }
    4.37      if (have_pv) st->cr();
    4.38 -  } // pvw is cleaned up
    4.39 +  }
    4.40  
    4.41    if (generic_signature() != NULL) {
    4.42      st->print(BULLET"generic signature: ");
    4.43 @@ -3610,92 +3601,93 @@
    4.44  // RedefineClasses() support for previous versions:
    4.45  
    4.46  // Purge previous versions
    4.47 -static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) {
    4.48 +void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
    4.49    if (ik->previous_versions() != NULL) {
    4.50      // This klass has previous versions so see what we can cleanup
    4.51      // while it is safe to do so.
    4.52  
    4.53      int deleted_count = 0;    // leave debugging breadcrumbs
    4.54      int live_count = 0;
    4.55 -    ClassLoaderData* loader_data = ik->class_loader_data() == NULL ?
    4.56 -                       ClassLoaderData::the_null_class_loader_data() :
    4.57 -                       ik->class_loader_data();
    4.58 +    ClassLoaderData* loader_data = ik->class_loader_data();
    4.59 +    assert(loader_data != NULL, "should never be null");
    4.60  
    4.61      // RC_TRACE macro has an embedded ResourceMark
    4.62 -    RC_TRACE(0x00000200, ("purge: %s: previous version length=%d",
    4.63 -      ik->external_name(), ik->previous_versions()->length()));
    4.64 -
    4.65 -    for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
    4.66 -      // check the previous versions array
    4.67 -      PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
    4.68 -      ConstantPool* cp_ref = pv_node->prev_constant_pool();
    4.69 -      assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
    4.70 -
    4.71 -      ConstantPool* pvcp = cp_ref;
    4.72 +    RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
    4.73 +
    4.74 +    // previous versions are linked together through the InstanceKlass
    4.75 +    InstanceKlass* pv_node = ik->previous_versions();
    4.76 +    InstanceKlass* last = ik;
    4.77 +    int version = 0;
    4.78 +
    4.79 +    // check the previous versions list
    4.80 +    for (; pv_node != NULL; ) {
    4.81 +
    4.82 +      ConstantPool* pvcp = pv_node->constants();
    4.83 +      assert(pvcp != NULL, "cp ref was unexpectedly cleared");
    4.84 +
    4.85 +
    4.86        if (!pvcp->on_stack()) {
    4.87          // If the constant pool isn't on stack, none of the methods
    4.88 -        // are executing.  Delete all the methods, the constant pool and
    4.89 -        // and this previous version node.
    4.90 -        GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
    4.91 -        if (method_refs != NULL) {
    4.92 -          for (int j = method_refs->length() - 1; j >= 0; j--) {
    4.93 -            Method* method = method_refs->at(j);
    4.94 -            assert(method != NULL, "method ref was unexpectedly cleared");
    4.95 -            method_refs->remove_at(j);
    4.96 -            // method will be freed with associated class.
    4.97 -          }
    4.98 -        }
    4.99 -        // Remove the constant pool
   4.100 -        delete pv_node;
   4.101 -        // Since we are traversing the array backwards, we don't have to
   4.102 -        // do anything special with the index.
   4.103 -        ik->previous_versions()->remove_at(i);
   4.104 +        // are executing.  Unlink this previous_version.
   4.105 +        // The previous version InstanceKlass is on the ClassLoaderData deallocate list
   4.106 +        // so will be deallocated during the next phase of class unloading.
   4.107 +        pv_node = pv_node->previous_versions();
   4.108 +        last->link_previous_versions(pv_node);
   4.109          deleted_count++;
   4.110 +        version++;
   4.111          continue;
   4.112        } else {
   4.113 -        RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i));
   4.114 +        RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
   4.115 +                              pv_node));
   4.116          assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
   4.117          guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
   4.118          live_count++;
   4.119        }
   4.120  
   4.121 -      // At least one method is live in this previous version, clean out
   4.122 -      // the others or mark them as obsolete.
   4.123 -      GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
   4.124 +      // At least one method is live in this previous version so clean its MethodData.
   4.125 +      // Reset dead EMCP methods not to get breakpoints.
   4.126 +      // All methods are deallocated when all of the methods for this class are no
   4.127 +      // longer running.
   4.128 +      Array<Method*>* method_refs = pv_node->methods();
   4.129        if (method_refs != NULL) {
   4.130          RC_TRACE(0x00000200, ("purge: previous methods length=%d",
   4.131            method_refs->length()));
   4.132 -        for (int j = method_refs->length() - 1; j >= 0; j--) {
   4.133 +        for (int j = 0; j < method_refs->length(); j++) {
   4.134            Method* method = method_refs->at(j);
   4.135 -          assert(method != NULL, "method ref was unexpectedly cleared");
   4.136 -
   4.137 -          // Remove the emcp method if it's not executing
   4.138 -          // If it's been made obsolete by a redefinition of a non-emcp
   4.139 -          // method, mark it as obsolete but leave it to clean up later.
   4.140 +
   4.141            if (!method->on_stack()) {
   4.142 -            method_refs->remove_at(j);
   4.143 -          } else if (emcp_method_count == 0) {
   4.144 -            method->set_is_obsolete();
   4.145 +            // no breakpoints for non-running methods
   4.146 +            if (method->is_running_emcp()) {
   4.147 +              method->set_running_emcp(false);
   4.148 +            }
   4.149            } else {
   4.150 +            assert (method->is_obsolete() || method->is_running_emcp(),
   4.151 +                    "emcp method cannot run after emcp bit is cleared");
   4.152              // RC_TRACE macro has an embedded ResourceMark
   4.153              RC_TRACE(0x00000200,
   4.154                ("purge: %s(%s): prev method @%d in version @%d is alive",
   4.155                method->name()->as_C_string(),
   4.156 -              method->signature()->as_C_string(), j, i));
   4.157 +              method->signature()->as_C_string(), j, version));
   4.158              if (method->method_data() != NULL) {
   4.159 -              // Clean out any weak method links
   4.160 +              // Clean out any weak method links for running methods
   4.161 +              // (also should include not EMCP methods)
   4.162                method->method_data()->clean_weak_method_links();
   4.163              }
   4.164            }
   4.165          }
   4.166        }
   4.167 +      // next previous version
   4.168 +      last = pv_node;
   4.169 +      pv_node = pv_node->previous_versions();
   4.170 +      version++;
   4.171      }
   4.172 -    assert(ik->previous_versions()->length() == live_count, "sanity check");
   4.173      RC_TRACE(0x00000200,
   4.174        ("purge: previous version stats: live=%d, deleted=%d", live_count,
   4.175        deleted_count));
   4.176    }
   4.177  
   4.178 +  // Clean MethodData of this class's methods so they don't refer to
   4.179 +  // old methods that are no longer running.
   4.180    Array<Method*>* methods = ik->methods();
   4.181    int num_methods = methods->length();
   4.182    for (int index2 = 0; index2 < num_methods; ++index2) {
   4.183 @@ -3705,122 +3697,30 @@
   4.184    }
   4.185  }
   4.186  
   4.187 -// External interface for use during class unloading.
   4.188 -void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
   4.189 -  // Call with >0 emcp methods since they are not currently being redefined.
   4.190 -  purge_previous_versions_internal(ik, 1);
   4.191 -}
   4.192 -
   4.193 -
   4.194 -// Potentially add an information node that contains pointers to the
   4.195 -// interesting parts of the previous version of the_class.
   4.196 -// This is also where we clean out any unused references.
   4.197 -// Note that while we delete nodes from the _previous_versions
   4.198 -// array, we never delete the array itself until the klass is
   4.199 -// unloaded. The has_been_redefined() query depends on that fact.
   4.200 -//
   4.201 -void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
   4.202 -       BitMap* emcp_methods, int emcp_method_count) {
   4.203 -  assert(Thread::current()->is_VM_thread(),
   4.204 -         "only VMThread can add previous versions");
   4.205 -
   4.206 -  if (_previous_versions == NULL) {
   4.207 -    // This is the first previous version so make some space.
   4.208 -    // Start with 2 elements under the assumption that the class
   4.209 -    // won't be redefined much.
   4.210 -    _previous_versions =  new (ResourceObj::C_HEAP, mtClass)
   4.211 -                            GrowableArray<PreviousVersionNode *>(2, true);
   4.212 -  }
   4.213 -
   4.214 -  ConstantPool* cp_ref = ikh->constants();
   4.215 -
   4.216 -  // RC_TRACE macro has an embedded ResourceMark
   4.217 -  RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
   4.218 -                        "on_stack=%d",
   4.219 -    ikh->external_name(), _previous_versions->length(), emcp_method_count,
   4.220 -    cp_ref->on_stack()));
   4.221 -
   4.222 -  // If the constant pool for this previous version of the class
   4.223 -  // is not marked as being on the stack, then none of the methods
   4.224 -  // in this previous version of the class are on the stack so
   4.225 -  // we don't need to create a new PreviousVersionNode. However,
   4.226 -  // we still need to examine older previous versions below.
   4.227 -  Array<Method*>* old_methods = ikh->methods();
   4.228 -
   4.229 -  if (cp_ref->on_stack()) {
   4.230 -    PreviousVersionNode * pv_node = NULL;
   4.231 -    if (emcp_method_count == 0) {
   4.232 -      // non-shared ConstantPool gets a reference
   4.233 -      pv_node = new PreviousVersionNode(cp_ref, NULL);
   4.234 -      RC_TRACE(0x00000400,
   4.235 -          ("add: all methods are obsolete; flushing any EMCP refs"));
   4.236 -    } else {
   4.237 -      int local_count = 0;
   4.238 -      GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
   4.239 -          GrowableArray<Method*>(emcp_method_count, true);
   4.240 -      for (int i = 0; i < old_methods->length(); i++) {
   4.241 -        if (emcp_methods->at(i)) {
   4.242 -            // this old method is EMCP. Save it only if it's on the stack
   4.243 -            Method* old_method = old_methods->at(i);
   4.244 -            if (old_method->on_stack()) {
   4.245 -              method_refs->append(old_method);
   4.246 -            }
   4.247 -          if (++local_count >= emcp_method_count) {
   4.248 -            // no more EMCP methods so bail out now
   4.249 -            break;
   4.250 -          }
   4.251 -        }
   4.252 -      }
   4.253 -      // non-shared ConstantPool gets a reference
   4.254 -      pv_node = new PreviousVersionNode(cp_ref, method_refs);
   4.255 -    }
   4.256 -    // append new previous version.
   4.257 -    _previous_versions->append(pv_node);
   4.258 -  }
   4.259 -
   4.260 -  // Since the caller is the VMThread and we are at a safepoint, this
   4.261 -  // is a good time to clear out unused references.
   4.262 -
   4.263 -  RC_TRACE(0x00000400, ("add: previous version length=%d",
   4.264 -    _previous_versions->length()));
   4.265 -
   4.266 -  // Purge previous versions not executing on the stack
   4.267 -  purge_previous_versions_internal(this, emcp_method_count);
   4.268 -
   4.269 +void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
   4.270 +                                                int emcp_method_count) {
   4.271    int obsolete_method_count = old_methods->length() - emcp_method_count;
   4.272  
   4.273    if (emcp_method_count != 0 && obsolete_method_count != 0 &&
   4.274 -      _previous_versions->length() > 0) {
   4.275 +      _previous_versions != NULL) {
   4.276      // We have a mix of obsolete and EMCP methods so we have to
   4.277      // clear out any matching EMCP method entries the hard way.
   4.278      int local_count = 0;
   4.279      for (int i = 0; i < old_methods->length(); i++) {
   4.280 -      if (!emcp_methods->at(i)) {
   4.281 +      Method* old_method = old_methods->at(i);
   4.282 +      if (old_method->is_obsolete()) {
   4.283          // only obsolete methods are interesting
   4.284 -        Method* old_method = old_methods->at(i);
   4.285          Symbol* m_name = old_method->name();
   4.286          Symbol* m_signature = old_method->signature();
   4.287  
   4.288 -        // we might not have added the last entry
   4.289 -        for (int j = _previous_versions->length() - 1; j >= 0; j--) {
   4.290 -          // check the previous versions array for non executing obsolete methods
   4.291 -          PreviousVersionNode * pv_node = _previous_versions->at(j);
   4.292 -
   4.293 -          GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
   4.294 -          if (method_refs == NULL) {
   4.295 -            // We have run into a PreviousVersion generation where
   4.296 -            // all methods were made obsolete during that generation's
   4.297 -            // RedefineClasses() operation. At the time of that
   4.298 -            // operation, all EMCP methods were flushed so we don't
   4.299 -            // have to go back any further.
   4.300 -            //
   4.301 -            // A NULL method_refs is different than an empty method_refs.
   4.302 -            // We cannot infer any optimizations about older generations
   4.303 -            // from an empty method_refs for the current generation.
   4.304 -            break;
   4.305 -          }
   4.306 -
   4.307 -          for (int k = method_refs->length() - 1; k >= 0; k--) {
   4.308 +        // previous versions are linked together through the InstanceKlass
   4.309 +        int j = 0;
   4.310 +        for (InstanceKlass* prev_version = _previous_versions;
   4.311 +             prev_version != NULL;
   4.312 +             prev_version = prev_version->previous_versions(), j++) {
   4.313 +
   4.314 +          Array<Method*>* method_refs = prev_version->methods();
   4.315 +          for (int k = 0; k < method_refs->length(); k++) {
   4.316              Method* method = method_refs->at(k);
   4.317  
   4.318              if (!method->is_obsolete() &&
   4.319 @@ -3828,14 +3728,11 @@
   4.320                  method->signature() == m_signature) {
   4.321                // The current RedefineClasses() call has made all EMCP
   4.322                // versions of this method obsolete so mark it as obsolete
   4.323 -              // and remove the reference.
   4.324                RC_TRACE(0x00000400,
   4.325                  ("add: %s(%s): flush obsolete method @%d in version @%d",
   4.326                  m_name->as_C_string(), m_signature->as_C_string(), k, j));
   4.327  
   4.328                method->set_is_obsolete();
   4.329 -              // Leave obsolete methods on the previous version list to
   4.330 -              // clean up later.
   4.331                break;
   4.332              }
   4.333            }
   4.334 @@ -3843,9 +3740,9 @@
   4.335            // The previous loop may not find a matching EMCP method, but
   4.336            // that doesn't mean that we can optimize and not go any
   4.337            // further back in the PreviousVersion generations. The EMCP
   4.338 -          // method for this generation could have already been deleted,
   4.339 +          // method for this generation could have already been made obsolete,
   4.340            // but there still may be an older EMCP method that has not
   4.341 -          // been deleted.
   4.342 +          // been made obsolete.
   4.343          }
   4.344  
   4.345          if (++local_count >= obsolete_method_count) {
   4.346 @@ -3855,30 +3752,67 @@
   4.347        }
   4.348      }
   4.349    }
   4.350 -} // end add_previous_version()
   4.351 -
   4.352 -
   4.353 -// Determine if InstanceKlass has a previous version.
   4.354 -bool InstanceKlass::has_previous_version() const {
   4.355 -  return (_previous_versions != NULL && _previous_versions->length() > 0);
   4.356 -} // end has_previous_version()
   4.357 -
   4.358 -
   4.359 -InstanceKlass* InstanceKlass::get_klass_version(int version) {
   4.360 -  if (constants()->version() == version) {
   4.361 -    return this;
   4.362 +}
   4.363 +
   4.364 +// Save the scratch_class as the previous version if any of the methods are running.
   4.365 +// The previous_versions are used to set breakpoints in EMCP methods and they are
   4.366 +// also used to clean MethodData links to redefined methods that are no longer running.
   4.367 +void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
   4.368 +                                         int emcp_method_count) {
   4.369 +  assert(Thread::current()->is_VM_thread(),
   4.370 +         "only VMThread can add previous versions");
   4.371 +
   4.372 +  // RC_TRACE macro has an embedded ResourceMark
   4.373 +  RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
   4.374 +    scratch_class->external_name(), emcp_method_count));
   4.375 +
   4.376 +  // Clean out old previous versions
   4.377 +  purge_previous_versions(this);
   4.378 +
   4.379 +  // Mark newly obsolete methods in remaining previous versions.  An EMCP method from
   4.380 +  // a previous redefinition may be made obsolete by this redefinition.
   4.381 +  Array<Method*>* old_methods = scratch_class->methods();
   4.382 +  mark_newly_obsolete_methods(old_methods, emcp_method_count);
   4.383 +
   4.384 +  // If the constant pool for this previous version of the class
   4.385 +  // is not marked as being on the stack, then none of the methods
   4.386 +  // in this previous version of the class are on the stack so
   4.387 +  // we don't need to add this as a previous version.
   4.388 +  ConstantPool* cp_ref = scratch_class->constants();
   4.389 +  if (!cp_ref->on_stack()) {
   4.390 +    RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
   4.391 +    return;
   4.392    }
   4.393 -  PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
   4.394 -  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
   4.395 -       pv_node != NULL; pv_node = pvw.next_previous_version()) {
   4.396 -    ConstantPool* prev_cp = pv_node->prev_constant_pool();
   4.397 -    if (prev_cp->version() == version) {
   4.398 -      return prev_cp->pool_holder();
   4.399 +
   4.400 +  if (emcp_method_count != 0) {
   4.401 +    // At least one method is still running, check for EMCP methods
   4.402 +    for (int i = 0; i < old_methods->length(); i++) {
   4.403 +      Method* old_method = old_methods->at(i);
   4.404 +      if (!old_method->is_obsolete() && old_method->on_stack()) {
   4.405 +        // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
   4.406 +        // we can add breakpoints for it.
   4.407 +
   4.408 +        // We set the method->on_stack bit during safepoints for class redefinition and
   4.409 +        // class unloading and use this bit to set the is_running_emcp bit.
   4.410 +        // After the safepoint, the on_stack bit is cleared and the running emcp
   4.411 +        // method may exit.   If so, we would set a breakpoint in a method that
   4.412 +        // is never reached, but this won't be noticeable to the programmer.
   4.413 +        old_method->set_running_emcp(true);
   4.414 +        RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
   4.415 +                              old_method->name_and_sig_as_C_string(), old_method));
   4.416 +      } else if (!old_method->is_obsolete()) {
   4.417 +        RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
   4.418 +                              old_method->name_and_sig_as_C_string(), old_method));
   4.419 +      }
   4.420      }
   4.421    }
   4.422 -  return NULL; // None found
   4.423 -}
   4.424 -
   4.425 +
   4.426 +  // Add previous version if any methods are still running.
   4.427 +  RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
   4.428 +  assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
   4.429 +  scratch_class->link_previous_versions(previous_versions());
   4.430 +  link_previous_versions(scratch_class());
   4.431 +} // end add_previous_version()
   4.432  
   4.433  Method* InstanceKlass::method_with_idnum(int idnum) {
   4.434    Method* m = NULL;
   4.435 @@ -3936,61 +3870,3 @@
   4.436  unsigned char * InstanceKlass::get_cached_class_file_bytes() {
   4.437    return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
   4.438  }
   4.439 -
   4.440 -
   4.441 -// Construct a PreviousVersionNode entry for the array hung off
   4.442 -// the InstanceKlass.
   4.443 -PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
   4.444 -  GrowableArray<Method*>* prev_EMCP_methods) {
   4.445 -
   4.446 -  _prev_constant_pool = prev_constant_pool;
   4.447 -  _prev_EMCP_methods = prev_EMCP_methods;
   4.448 -}
   4.449 -
   4.450 -
   4.451 -// Destroy a PreviousVersionNode
   4.452 -PreviousVersionNode::~PreviousVersionNode() {
   4.453 -  if (_prev_constant_pool != NULL) {
   4.454 -    _prev_constant_pool = NULL;
   4.455 -  }
   4.456 -
   4.457 -  if (_prev_EMCP_methods != NULL) {
   4.458 -    delete _prev_EMCP_methods;
   4.459 -  }
   4.460 -}
   4.461 -
   4.462 -// Construct a helper for walking the previous versions array
   4.463 -PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
   4.464 -  _thread = thread;
   4.465 -  _previous_versions = ik->previous_versions();
   4.466 -  _current_index = 0;
   4.467 -  _current_p = NULL;
   4.468 -  _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
   4.469 -}
   4.470 -
   4.471 -
   4.472 -// Return the interesting information for the next previous version
   4.473 -// of the klass. Returns NULL if there are no more previous versions.
   4.474 -PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
   4.475 -  if (_previous_versions == NULL) {
   4.476 -    // no previous versions so nothing to return
   4.477 -    return NULL;
   4.478 -  }
   4.479 -
   4.480 -  _current_p = NULL;  // reset to NULL
   4.481 -  _current_constant_pool_handle = NULL;
   4.482 -
   4.483 -  int length = _previous_versions->length();
   4.484 -
   4.485 -  while (_current_index < length) {
   4.486 -    PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
   4.487 -
   4.488 -    // Save a handle to the constant pool for this previous version,
   4.489 -    // which keeps all the methods from being deallocated.
   4.490 -    _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
   4.491 -    _current_p = pv_node;
   4.492 -    return pv_node;
   4.493 -  }
   4.494 -
   4.495 -  return NULL;
   4.496 -} // end next_previous_version()
     5.1 --- a/src/share/vm/oops/instanceKlass.hpp	Tue Apr 08 09:51:25 2014 +0200
     5.2 +++ b/src/share/vm/oops/instanceKlass.hpp	Mon Jan 08 08:32:04 2018 -0800
     5.3 @@ -88,7 +88,6 @@
     5.4  class fieldDescriptor;
     5.5  class DepChange;
     5.6  class nmethodBucket;
     5.7 -class PreviousVersionNode;
     5.8  class JvmtiCachedClassFieldMap;
     5.9  class MemberNameTable;
    5.10  
    5.11 @@ -235,7 +234,8 @@
    5.12      _misc_is_anonymous             = 1 << 3, // has embedded _host_klass field
    5.13      _misc_is_contended             = 1 << 4, // marked with contended annotation
    5.14      _misc_has_default_methods      = 1 << 5, // class/superclass/implemented interfaces has default methods
    5.15 -    _misc_declares_default_methods = 1 << 6  // directly declares default methods (any access)
    5.16 +    _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access)
    5.17 +    _misc_has_been_redefined       = 1 << 7  // class has been redefined
    5.18    };
    5.19    u2              _misc_flags;
    5.20    u2              _minor_version;        // minor version number of class file
    5.21 @@ -250,9 +250,8 @@
    5.22    nmethodBucket*  _dependencies;         // list of dependent nmethods
    5.23    nmethod*        _osr_nmethods_head;    // Head of list of on-stack replacement nmethods for this class
    5.24    BreakpointInfo* _breakpoints;          // bpt lists, managed by Method*
    5.25 -  // Array of interesting part(s) of the previous version(s) of this
    5.26 -  // InstanceKlass. See PreviousVersionWalker below.
    5.27 -  GrowableArray<PreviousVersionNode *>* _previous_versions;
    5.28 +  // Linked instanceKlasses of previous versions
    5.29 +  InstanceKlass* _previous_versions;
    5.30    // JVMTI fields can be moved to their own structure - see 6315920
    5.31    // JVMTI: cached class file, before retransformable agent modified it in CFLH
    5.32    JvmtiCachedClassFileData* _cached_class_file;
    5.33 @@ -664,21 +663,31 @@
    5.34    }
    5.35  
    5.36    // RedefineClasses() support for previous versions:
    5.37 -  void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
    5.38 -         int emcp_method_count);
    5.39 -  // If the _previous_versions array is non-NULL, then this klass
    5.40 -  // has been redefined at least once even if we aren't currently
    5.41 -  // tracking a previous version.
    5.42 -  bool has_been_redefined() const { return _previous_versions != NULL; }
    5.43 -  bool has_previous_version() const;
    5.44 +  void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
    5.45 +
    5.46 +  InstanceKlass* previous_versions() const { return _previous_versions; }
    5.47 +
    5.48 +  bool has_been_redefined() const {
    5.49 +    return (_misc_flags & _misc_has_been_redefined) != 0;
    5.50 +  }
    5.51 +  void set_has_been_redefined() {
    5.52 +    _misc_flags |= _misc_has_been_redefined;
    5.53 +  }
    5.54 +
    5.55    void init_previous_versions() {
    5.56      _previous_versions = NULL;
    5.57    }
    5.58 -  GrowableArray<PreviousVersionNode *>* previous_versions() const {
    5.59 -    return _previous_versions;
    5.60 +
    5.61 +
    5.62 +  InstanceKlass* get_klass_version(int version) {
    5.63 +    for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) {
    5.64 +      if (ik->constants()->version() == version) {
    5.65 +        return ik;
    5.66 +      }
    5.67 +    }
    5.68 +    return NULL;
    5.69    }
    5.70  
    5.71 -  InstanceKlass* get_klass_version(int version);
    5.72    static void purge_previous_versions(InstanceKlass* ik);
    5.73  
    5.74    // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
    5.75 @@ -1119,6 +1128,10 @@
    5.76  
    5.77    // Free CHeap allocated fields.
    5.78    void release_C_heap_structures();
    5.79 +
    5.80 +  // RedefineClasses support
    5.81 +  void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
    5.82 +  void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
    5.83  public:
    5.84    // CDS support - remove and restore oops from metadata. Oops are not shared.
    5.85    virtual void remove_unshareable_info();
    5.86 @@ -1217,62 +1230,6 @@
    5.87  };
    5.88  
    5.89  
    5.90 -// If breakpoints are more numerous than just JVMTI breakpoints,
    5.91 -// consider compressing this data structure.
    5.92 -// It is currently a simple linked list defined in method.hpp.
    5.93 -
    5.94 -class BreakpointInfo;
    5.95 -
    5.96 -
    5.97 -// A collection point for interesting information about the previous
    5.98 -// version(s) of an InstanceKlass.  A GrowableArray of PreviousVersionNodes
    5.99 -// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
   5.100 -class PreviousVersionNode : public CHeapObj<mtClass> {
   5.101 - private:
   5.102 -  ConstantPool*    _prev_constant_pool;
   5.103 -
   5.104 -  // If the previous version of the InstanceKlass doesn't have any
   5.105 -  // EMCP methods, then _prev_EMCP_methods will be NULL. If all the
   5.106 -  // EMCP methods have been collected, then _prev_EMCP_methods can
   5.107 -  // have a length of zero.
   5.108 -  GrowableArray<Method*>* _prev_EMCP_methods;
   5.109 -
   5.110 -public:
   5.111 -  PreviousVersionNode(ConstantPool* prev_constant_pool,
   5.112 -                      GrowableArray<Method*>* prev_EMCP_methods);
   5.113 -  ~PreviousVersionNode();
   5.114 -  ConstantPool* prev_constant_pool() const {
   5.115 -    return _prev_constant_pool;
   5.116 -  }
   5.117 -  GrowableArray<Method*>* prev_EMCP_methods() const {
   5.118 -    return _prev_EMCP_methods;
   5.119 -  }
   5.120 -};
   5.121 -
   5.122 -
   5.123 -// Helper object for walking previous versions.
   5.124 -class PreviousVersionWalker : public StackObj {
   5.125 - private:
   5.126 -  Thread*                               _thread;
   5.127 -  GrowableArray<PreviousVersionNode *>* _previous_versions;
   5.128 -  int                                   _current_index;
   5.129 -
   5.130 -  // A pointer to the current node object so we can handle the deletes.
   5.131 -  PreviousVersionNode*                  _current_p;
   5.132 -
   5.133 -  // The constant pool handle keeps all the methods in this class from being
   5.134 -  // deallocated from the metaspace during class unloading.
   5.135 -  constantPoolHandle                    _current_constant_pool_handle;
   5.136 -
   5.137 - public:
   5.138 -  PreviousVersionWalker(Thread* thread, InstanceKlass *ik);
   5.139 -
   5.140 -  // Return the interesting information for the next previous version
   5.141 -  // of the klass. Returns NULL if there are no more previous versions.
   5.142 -  PreviousVersionNode* next_previous_version();
   5.143 -};
   5.144 -
   5.145 -
   5.146  //
   5.147  // nmethodBucket is used to record dependent nmethods for
   5.148  // deoptimization.  nmethod dependencies are actually <klass, method>
     6.1 --- a/src/share/vm/oops/klass.cpp	Tue Apr 08 09:51:25 2014 +0200
     6.2 +++ b/src/share/vm/oops/klass.cpp	Mon Jan 08 08:32:04 2018 -0800
     6.3 @@ -455,6 +455,12 @@
     6.4      if (clean_alive_klasses && current->oop_is_instance()) {
     6.5        InstanceKlass* ik = InstanceKlass::cast(current);
     6.6        ik->clean_weak_instanceklass_links(is_alive);
     6.7 +
     6.8 +      // JVMTI RedefineClasses creates previous versions that are not in
     6.9 +      // the class hierarchy, so process them here.
    6.10 +      while ((ik = ik->previous_versions()) != NULL) {
    6.11 +        ik->clean_weak_instanceklass_links(is_alive);
    6.12 +      }
    6.13      }
    6.14    }
    6.15  }
     7.1 --- a/src/share/vm/oops/method.cpp	Tue Apr 08 09:51:25 2014 +0200
     7.2 +++ b/src/share/vm/oops/method.cpp	Mon Jan 08 08:32:04 2018 -0800
     7.3 @@ -91,6 +91,7 @@
     7.4    set_hidden(false);
     7.5    set_dont_inline(false);
     7.6    set_has_injected_profile(false);
     7.7 +  set_running_emcp(false);
     7.8    set_method_data(NULL);
     7.9    clear_method_counters();
    7.10    set_vtable_index(Method::garbage_vtable_index);
     8.1 --- a/src/share/vm/oops/method.hpp	Tue Apr 08 09:51:25 2014 +0200
     8.2 +++ b/src/share/vm/oops/method.hpp	Mon Jan 08 08:32:04 2018 -0800
     8.3 @@ -111,6 +111,7 @@
     8.4                      _caller_sensitive     : 1,
     8.5                      _force_inline         : 1,
     8.6                      _hidden               : 1,
     8.7 +                    _running_emcp         : 1,
     8.8                      _dont_inline          : 1,
     8.9                      _has_injected_profile : 1,
    8.10                                            : 2;
    8.11 @@ -711,6 +712,21 @@
    8.12    void set_is_obsolete()                            { _access_flags.set_is_obsolete(); }
    8.13    bool is_deleted() const                           { return access_flags().is_deleted(); }
    8.14    void set_is_deleted()                             { _access_flags.set_is_deleted(); }
    8.15 +
    8.16 +  bool is_running_emcp() const {
    8.17 +    // EMCP methods are old but not obsolete or deleted. Equivalent
    8.18 +    // Modulo Constant Pool means the method is equivalent except
    8.19 +    // the constant pool and instructions that access the constant
    8.20 +    // pool might be different.
    8.21 +    // If a breakpoint is set in a redefined method, its EMCP methods that are
    8.22 +    // still running must have a breakpoint also.
    8.23 +    return _running_emcp;
    8.24 +  }
    8.25 +
    8.26 +  void set_running_emcp(bool x) {
    8.27 +    _running_emcp = x;
    8.28 +  }
    8.29 +
    8.30    bool on_stack() const                             { return access_flags().on_stack(); }
    8.31    void set_on_stack(const bool value);
    8.32  
     9.1 --- a/src/share/vm/prims/jvmtiImpl.cpp	Tue Apr 08 09:51:25 2014 +0200
     9.2 +++ b/src/share/vm/prims/jvmtiImpl.cpp	Mon Jan 08 08:32:04 2018 -0800
     9.3 @@ -282,39 +282,22 @@
     9.4  void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
     9.5    ((Method*)_method->*meth_act)(_bci);
     9.6  
     9.7 -  // add/remove breakpoint to/from versions of the method that
     9.8 -  // are EMCP. Directly or transitively obsolete methods are
     9.9 -  // not saved in the PreviousVersionNodes.
    9.10 +  // add/remove breakpoint to/from versions of the method that are EMCP.
    9.11    Thread *thread = Thread::current();
    9.12    instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
    9.13    Symbol* m_name = _method->name();
    9.14    Symbol* m_signature = _method->signature();
    9.15  
    9.16    // search previous versions if they exist
    9.17 -  PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
    9.18 -  for (PreviousVersionNode * pv_node = pvw.next_previous_version();
    9.19 -       pv_node != NULL; pv_node = pvw.next_previous_version()) {
    9.20 -    GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
    9.21 -
    9.22 -    if (methods == NULL) {
    9.23 -      // We have run into a PreviousVersion generation where
    9.24 -      // all methods were made obsolete during that generation's
    9.25 -      // RedefineClasses() operation. At the time of that
    9.26 -      // operation, all EMCP methods were flushed so we don't
    9.27 -      // have to go back any further.
    9.28 -      //
    9.29 -      // A NULL methods array is different than an empty methods
    9.30 -      // array. We cannot infer any optimizations about older
    9.31 -      // generations from an empty methods array for the current
    9.32 -      // generation.
    9.33 -      break;
    9.34 -    }
    9.35 +  for (InstanceKlass* pv_node = ikh->previous_versions();
    9.36 +       pv_node != NULL;
    9.37 +       pv_node = pv_node->previous_versions()) {
    9.38 +    Array<Method*>* methods = pv_node->methods();
    9.39  
    9.40      for (int i = methods->length() - 1; i >= 0; i--) {
    9.41        Method* method = methods->at(i);
    9.42 -      // obsolete methods that are running are not deleted from
    9.43 -      // previous version array, but they are skipped here.
    9.44 -      if (!method->is_obsolete() &&
    9.45 +      // Only set breakpoints in running EMCP methods.
    9.46 +      if (method->is_running_emcp() &&
    9.47            method->name() == m_name &&
    9.48            method->signature() == m_signature) {
    9.49          RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
    10.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Tue Apr 08 09:51:25 2014 +0200
    10.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Jan 08 08:32:04 2018 -0800
    10.3 @@ -3435,13 +3435,12 @@
    10.4      }
    10.5  
    10.6      // the previous versions' constant pool caches may need adjustment
    10.7 -    PreviousVersionWalker pvw(_thread, ik);
    10.8 -    for (PreviousVersionNode * pv_node = pvw.next_previous_version();
    10.9 -         pv_node != NULL; pv_node = pvw.next_previous_version()) {
   10.10 -      other_cp = pv_node->prev_constant_pool();
   10.11 -      cp_cache = other_cp->cache();
   10.12 +    for (InstanceKlass* pv_node = ik->previous_versions();
   10.13 +         pv_node != NULL;
   10.14 +         pv_node = pv_node->previous_versions()) {
   10.15 +      cp_cache = pv_node->constants()->cache();
   10.16        if (cp_cache != NULL) {
   10.17 -        cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed);
   10.18 +        cp_cache->adjust_method_entries(pv_node, &trace_name_printed);
   10.19        }
   10.20      }
   10.21    }
   10.22 @@ -3461,9 +3460,8 @@
   10.23    }
   10.24  }
   10.25  
   10.26 -void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
   10.27 -       BitMap *emcp_methods, int * emcp_method_count_p) {
   10.28 -  *emcp_method_count_p = 0;
   10.29 +int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
   10.30 +  int emcp_method_count = 0;
   10.31    int obsolete_count = 0;
   10.32    int old_index = 0;
   10.33    for (int j = 0; j < _matching_methods_length; ++j, ++old_index) {
   10.34 @@ -3537,9 +3535,9 @@
   10.35        // that we get from effectively overwriting the old methods
   10.36        // when the new methods are attached to the_class.
   10.37  
   10.38 -      // track which methods are EMCP for add_previous_version() call
   10.39 -      emcp_methods->set_bit(old_index);
   10.40 -      (*emcp_method_count_p)++;
   10.41 +      // Count number of methods that are EMCP.  The method will be marked
   10.42 +      // old but not obsolete if it is EMCP.
   10.43 +      emcp_method_count++;
   10.44  
   10.45        // An EMCP method is _not_ obsolete. An obsolete method has a
   10.46        // different jmethodID than the current method. An EMCP method
   10.47 @@ -3589,10 +3587,11 @@
   10.48                            old_method->name()->as_C_string(),
   10.49                            old_method->signature()->as_C_string()));
   10.50    }
   10.51 -  assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(),
   10.52 +  assert((emcp_method_count + obsolete_count) == _old_methods->length(),
   10.53      "sanity check");
   10.54 -  RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p,
   10.55 +  RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count,
   10.56      obsolete_count));
   10.57 +  return emcp_method_count;
   10.58  }
   10.59  
   10.60  // This internal class transfers the native function registration from old methods
   10.61 @@ -3973,11 +3972,8 @@
   10.62    old_constants->set_pool_holder(scratch_class());
   10.63  #endif
   10.64  
   10.65 -  // track which methods are EMCP for add_previous_version() call below
   10.66 -  BitMap emcp_methods(_old_methods->length());
   10.67 -  int emcp_method_count = 0;
   10.68 -  emcp_methods.clear();  // clears 0..(length() - 1)
   10.69 -  check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count);
   10.70 +  // track number of methods that are EMCP for add_previous_version() call below
   10.71 +  int emcp_method_count = check_methods_and_mark_as_obsolete();
   10.72    transfer_old_native_function_registrations(the_class);
   10.73  
   10.74    // The class file bytes from before any retransformable agents mucked
   10.75 @@ -4064,9 +4060,10 @@
   10.76      scratch_class->enclosing_method_method_index());
   10.77    scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
   10.78  
   10.79 +  the_class->set_has_been_redefined();
   10.80 +
   10.81    // keep track of previous versions of this class
   10.82 -  the_class->add_previous_version(scratch_class, &emcp_methods,
   10.83 -    emcp_method_count);
   10.84 +  the_class->add_previous_version(scratch_class, emcp_method_count);
   10.85  
   10.86    RC_TIMER_STOP(_timer_rsc_phase1);
   10.87    RC_TIMER_START(_timer_rsc_phase2);
    11.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp	Tue Apr 08 09:51:25 2014 +0200
    11.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp	Mon Jan 08 08:32:04 2018 -0800
    11.3 @@ -403,14 +403,9 @@
    11.4    // Change jmethodIDs to point to the new methods
    11.5    void update_jmethod_ids();
    11.6  
    11.7 -  // In addition to marking methods as obsolete, this routine
    11.8 -  // records which methods are EMCP (Equivalent Module Constant
    11.9 -  // Pool) in the emcp_methods BitMap and returns the number of
   11.10 -  // EMCP methods via emcp_method_count_p. This information is
   11.11 -  // used when information about the previous version of the_class
   11.12 -  // is squirreled away.
   11.13 -  void check_methods_and_mark_as_obsolete(BitMap *emcp_methods,
   11.14 -         int * emcp_method_count_p);
   11.15 +  // In addition to marking methods as old and/or obsolete, this routine
   11.16 +  // counts the number of methods that are EMCP (Equivalent Module Constant Pool).
   11.17 +  int check_methods_and_mark_as_obsolete();
   11.18    void transfer_old_native_function_registrations(instanceKlassHandle the_class);
   11.19  
   11.20    // Install the redefinition of a class
    12.1 --- a/test/runtime/RedefineFinalizer/RedefineFinalizer.java	Tue Apr 08 09:51:25 2014 +0200
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,64 +0,0 @@
    12.4 -/*
    12.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    12.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 - *
    12.8 - * This code is free software; you can redistribute it and/or modify it
    12.9 - * under the terms of the GNU General Public License version 2 only, as
   12.10 - * published by the Free Software Foundation.
   12.11 - *
   12.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
   12.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.14 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.15 - * version 2 for more details (a copy is included in the LICENSE file that
   12.16 - * accompanied this code).
   12.17 - *
   12.18 - * You should have received a copy of the GNU General Public License version
   12.19 - * 2 along with this work; if not, write to the Free Software Foundation,
   12.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.21 - *
   12.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.23 - * or visit www.oracle.com if you need additional information or have any
   12.24 - * questions.
   12.25 - */
   12.26 -
   12.27 -/*
   12.28 - * @test
   12.29 - * @bug 6904403
   12.30 - * @summary Don't assert if we redefine finalize method
   12.31 - * @library /testlibrary
   12.32 - * @build RedefineClassHelper
   12.33 - * @run main RedefineClassHelper
   12.34 - * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
   12.35 - */
   12.36 -
   12.37 -/*
   12.38 - * Regression test for hitting:
   12.39 - *
   12.40 - * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
   12.41 - *
   12.42 - * when redefining finalizer method
   12.43 - */
   12.44 -public class RedefineFinalizer {
   12.45 -
   12.46 -    public static String newB =
   12.47 -                "class RedefineFinalizer$B {" +
   12.48 -                "   protected void finalize() { " +
   12.49 -                "       System.out.println(\"Finalizer called\");" +
   12.50 -                "   }" +
   12.51 -                "}";
   12.52 -
   12.53 -    public static void main(String[] args) throws Exception {
   12.54 -        RedefineClassHelper.redefineClass(B.class, newB);
   12.55 -
   12.56 -        A a = new A();
   12.57 -    }
   12.58 -
   12.59 -    static class A extends B {
   12.60 -    }
   12.61 -
   12.62 -    static class B {
   12.63 -        protected void finalize() {
   12.64 -            // should be empty
   12.65 -        }
   12.66 -    }
   12.67 -}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/runtime/RedefineTests/RedefineFinalizer.java	Mon Jan 08 08:32:04 2018 -0800
    13.3 @@ -0,0 +1,64 @@
    13.4 +/*
    13.5 + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + *
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + *
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + *
   13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.23 + * or visit www.oracle.com if you need additional information or have any
   13.24 + * questions.
   13.25 + */
   13.26 +
   13.27 +/*
   13.28 + * @test
   13.29 + * @bug 6904403
   13.30 + * @summary Don't assert if we redefine finalize method
   13.31 + * @library /testlibrary
   13.32 + * @build RedefineClassHelper
   13.33 + * @run main RedefineClassHelper
   13.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
   13.35 + */
   13.36 +
   13.37 +/*
   13.38 + * Regression test for hitting:
   13.39 + *
   13.40 + * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
   13.41 + *
   13.42 + * when redefining finalizer method
   13.43 + */
   13.44 +public class RedefineFinalizer {
   13.45 +
   13.46 +    public static String newB =
   13.47 +                "class RedefineFinalizer$B {" +
   13.48 +                "   protected void finalize() { " +
   13.49 +                "       System.out.println(\"Finalizer called\");" +
   13.50 +                "   }" +
   13.51 +                "}";
   13.52 +
   13.53 +    public static void main(String[] args) throws Exception {
   13.54 +        RedefineClassHelper.redefineClass(B.class, newB);
   13.55 +
   13.56 +        A a = new A();
   13.57 +    }
   13.58 +
   13.59 +    static class A extends B {
   13.60 +    }
   13.61 +
   13.62 +    static class B {
   13.63 +        protected void finalize() {
   13.64 +            // should be empty
   13.65 +        }
   13.66 +    }
   13.67 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/runtime/RedefineTests/RedefineRunningMethods.java	Mon Jan 08 08:32:04 2018 -0800
    14.3 @@ -0,0 +1,143 @@
    14.4 +/*
    14.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + *
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + *
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + *
   14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.23 + * or visit www.oracle.com if you need additional information or have any
   14.24 + * questions.
   14.25 + */
   14.26 +
   14.27 +/*
   14.28 + * @test
   14.29 + * @bug 8055008
   14.30 + * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
   14.31 + * @library /testlibrary
   14.32 + * @build RedefineClassHelper
   14.33 + * @run main RedefineClassHelper
   14.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethods
   14.35 + */
   14.36 +public class RedefineRunningMethods {
   14.37 +
   14.38 +    public static String newB =
   14.39 +                "class RedefineRunningMethods$B {" +
   14.40 +                "   static int count1 = 0;" +
   14.41 +                "   static int count2 = 0;" +
   14.42 +                "   public static volatile boolean stop = false;" +
   14.43 +                "  static void localSleep() { " +
   14.44 +                "    try{ " +
   14.45 +                "      Thread.currentThread().sleep(10);" +
   14.46 +                "    } catch(InterruptedException ie) { " +
   14.47 +                "    } " +
   14.48 +                " } " +
   14.49 +                "   public static void infinite() { " +
   14.50 +                "       System.out.println(\"infinite called\");" +
   14.51 +                "   }" +
   14.52 +                "   public static void infinite_emcp() { " +
   14.53 +                "       while (!stop) { count2++; localSleep(); }" +
   14.54 +                "   }" +
   14.55 +                "}";
   14.56 +
   14.57 +    public static String evenNewerB =
   14.58 +                "class RedefineRunningMethods$B {" +
   14.59 +                "   static int count1 = 0;" +
   14.60 +                "   static int count2 = 0;" +
   14.61 +                "   public static volatile boolean stop = false;" +
   14.62 +                "  static void localSleep() { " +
   14.63 +                "    try{ " +
   14.64 +                "      Thread.currentThread().sleep(1);" +
   14.65 +                "    } catch(InterruptedException ie) { " +
   14.66 +                "    } " +
   14.67 +                " } " +
   14.68 +                "   public static void infinite() { }" +
   14.69 +                "   public static void infinite_emcp() { " +
   14.70 +                "       System.out.println(\"infinite_emcp now obsolete called\");" +
   14.71 +                "   }" +
   14.72 +                "}";
   14.73 +
   14.74 +    static class B {
   14.75 +        static int count1 = 0;
   14.76 +        static int count2 = 0;
   14.77 +        public static volatile boolean stop = false;
   14.78 +        static void localSleep() {
   14.79 +          try{
   14.80 +            Thread.currentThread().sleep(10);//sleep for 10 ms
   14.81 +          } catch(InterruptedException ie) {
   14.82 +          }
   14.83 +        }
   14.84 +
   14.85 +        public static void infinite() {
   14.86 +            while (!stop) { count1++; localSleep(); }
   14.87 +        }
   14.88 +        public static void infinite_emcp() {
   14.89 +            while (!stop) { count2++; localSleep(); }
   14.90 +        }
   14.91 +    }
   14.92 +
   14.93 +
   14.94 +    public static void main(String[] args) throws Exception {
   14.95 +
   14.96 +        new Thread() {
   14.97 +            public void run() {
   14.98 +                B.infinite();
   14.99 +            }
  14.100 +        }.start();
  14.101 +
  14.102 +        new Thread() {
  14.103 +            public void run() {
  14.104 +                B.infinite_emcp();
  14.105 +            }
  14.106 +        }.start();
  14.107 +
  14.108 +        RedefineClassHelper.redefineClass(B.class, newB);
  14.109 +
  14.110 +        System.gc();
  14.111 +
  14.112 +        B.infinite();
  14.113 +
  14.114 +        // Start a thread with the second version of infinite_emcp running
  14.115 +        new Thread() {
  14.116 +            public void run() {
  14.117 +                B.infinite_emcp();
  14.118 +            }
  14.119 +        }.start();
  14.120 +
  14.121 +        for (int i = 0; i < 20 ; i++) {
  14.122 +            String s = new String("some garbage");
  14.123 +            System.gc();
  14.124 +        }
  14.125 +
  14.126 +        RedefineClassHelper.redefineClass(B.class, evenNewerB);
  14.127 +        System.gc();
  14.128 +
  14.129 +        for (int i = 0; i < 20 ; i++) {
  14.130 +            B.infinite();
  14.131 +            String s = new String("some garbage");
  14.132 +            System.gc();
  14.133 +        }
  14.134 +
  14.135 +        B.infinite_emcp();
  14.136 +
  14.137 +        // purge should clean everything up.
  14.138 +        B.stop = true;
  14.139 +
  14.140 +        for (int i = 0; i < 20 ; i++) {
  14.141 +            B.infinite();
  14.142 +            String s = new String("some garbage");
  14.143 +            System.gc();
  14.144 +        }
  14.145 +    }
  14.146 +}

mercurial