Fri, 26 Jan 2018 10:39:27 -0800
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
test/runtime/RedefineFinalizer/RedefineFinalizer.java | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Thu Jan 25 08:16:32 2018 -0800 1.2 +++ b/.hgtags Fri Jan 26 10:39:27 2018 -0800 1.3 @@ -1131,6 +1131,7 @@ 1.4 39e2895b795aded8b584626fb019d35f12e9d1e7 jdk8u162-b11 1.5 69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12 1.6 caac74fe3cfa9a8c859c28c97d1046a58252af27 jdk8u162-b31 1.7 +c9b7abadf150328d2187de05b9e8a9cba2486e47 jdk8u162-b32 1.8 a17bab9405474602b18cd62e060a09b17d6413ac jdk8u171-b00 1.9 ebfd57cc21e6b7f0c22b17c666b6b28c9340e207 jdk8u171-b01 1.10 1acd7c1b80241def8fac90f70b0df16356adad47 jdk8u171-b02
2.1 --- a/src/share/vm/classfile/metadataOnStackMark.cpp Thu Jan 25 08:16:32 2018 -0800 2.2 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp Fri Jan 26 10:39:27 2018 -0800 2.3 @@ -41,13 +41,13 @@ 2.4 // Walk metadata on the stack and mark it so that redefinition doesn't delete 2.5 // it. Class unloading also walks the previous versions and might try to 2.6 // delete it, so this class is used by class unloading also. 2.7 -MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { 2.8 +MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) { 2.9 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); 2.10 assert(_used_buffers == NULL, "sanity check"); 2.11 NOT_PRODUCT(_is_active = true;) 2.12 2.13 Threads::metadata_do(Metadata::mark_on_stack); 2.14 - if (visit_code_cache) { 2.15 + if (has_redefined_a_class) { 2.16 CodeCache::alive_nmethods_do(nmethod::mark_on_stack); 2.17 } 2.18 CompileBroker::mark_on_stack();
3.1 --- a/src/share/vm/classfile/metadataOnStackMark.hpp Thu Jan 25 08:16:32 2018 -0800 3.2 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp Fri Jan 26 10:39:27 2018 -0800 3.3 @@ -47,7 +47,7 @@ 3.4 static void retire_buffer(MetadataOnStackBuffer* buffer); 3.5 3.6 public: 3.7 - MetadataOnStackMark(bool visit_code_cache); 3.8 + MetadataOnStackMark(bool has_redefined_a_class); 3.9 ~MetadataOnStackMark(); 3.10 3.11 static void record(Metadata* m, Thread* thread);
4.1 --- a/src/share/vm/code/nmethod.cpp Thu Jan 25 08:16:32 2018 -0800 4.2 +++ b/src/share/vm/code/nmethod.cpp Fri Jan 26 10:39:27 2018 -0800 4.3 @@ -2172,7 +2172,7 @@ 4.4 "metadata must be found in exactly one place"); 4.5 if (r->metadata_is_immediate() && r->metadata_value() != NULL) { 4.6 Metadata* md = r->metadata_value(); 4.7 - f(md); 4.8 + if (md != _method) f(md); 4.9 } 4.10 } else if (iter.type() == relocInfo::virtual_call_type) { 4.11 // Check compiledIC holders associated with this nmethod 4.12 @@ -2198,7 +2198,7 @@ 4.13 f(md); 4.14 } 4.15 4.16 - // Visit metadata not embedded in the other places. 4.17 + // Call function Method*, not embedded in these other places. 4.18 if (_method != NULL) f(_method); 4.19 } 4.20
5.1 --- a/src/share/vm/oops/instanceKlass.cpp Thu Jan 25 08:16:32 2018 -0800 5.2 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Jan 26 10:39:27 2018 -0800 5.3 @@ -2582,16 +2582,6 @@ 5.4 assert(breakpoints() == 0x0, "should have cleared breakpoints"); 5.5 } 5.6 5.7 - // deallocate information about previous versions 5.8 - if (_previous_versions != NULL) { 5.9 - for (int i = _previous_versions->length() - 1; i >= 0; i--) { 5.10 - PreviousVersionNode * pv_node = _previous_versions->at(i); 5.11 - delete pv_node; 5.12 - } 5.13 - delete _previous_versions; 5.14 - _previous_versions = NULL; 5.15 - } 5.16 - 5.17 // deallocate the cached class file 5.18 if (_cached_class_file != NULL) { 5.19 os::free(_cached_class_file, mtClass); 5.20 @@ -3187,16 +3177,17 @@ 5.21 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); 5.22 { 5.23 bool have_pv = false; 5.24 - PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); 5.25 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 5.26 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 5.27 + // previous versions are linked together through the InstanceKlass 5.28 + for (InstanceKlass* pv_node = _previous_versions; 5.29 + pv_node != NULL; 5.30 + pv_node = pv_node->previous_versions()) { 5.31 if (!have_pv) 5.32 st->print(BULLET"previous version: "); 5.33 have_pv = true; 5.34 - pv_node->prev_constant_pool()->print_value_on(st); 5.35 + pv_node->constants()->print_value_on(st); 5.36 } 5.37 if (have_pv) st->cr(); 5.38 - } // pvw is cleaned up 5.39 + } 5.40 5.41 if (generic_signature() != NULL) { 5.42 st->print(BULLET"generic signature: "); 5.43 @@ -3610,205 +3601,126 @@ 5.44 // RedefineClasses() support for previous versions: 5.45 5.46 // Purge previous versions 5.47 -static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) { 5.48 +void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { 5.49 if (ik->previous_versions() != NULL) { 5.50 // This klass has previous versions so see what we can cleanup 5.51 // while it is safe to do so. 5.52 5.53 int deleted_count = 0; // leave debugging breadcrumbs 5.54 int live_count = 0; 5.55 - ClassLoaderData* loader_data = ik->class_loader_data() == NULL ? 5.56 - ClassLoaderData::the_null_class_loader_data() : 5.57 - ik->class_loader_data(); 5.58 + ClassLoaderData* loader_data = ik->class_loader_data(); 5.59 + assert(loader_data != NULL, "should never be null"); 5.60 5.61 // RC_TRACE macro has an embedded ResourceMark 5.62 - RC_TRACE(0x00000200, ("purge: %s: previous version length=%d", 5.63 - ik->external_name(), ik->previous_versions()->length())); 5.64 - 5.65 - for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) { 5.66 - // check the previous versions array 5.67 - PreviousVersionNode * pv_node = ik->previous_versions()->at(i); 5.68 - ConstantPool* cp_ref = pv_node->prev_constant_pool(); 5.69 - assert(cp_ref != NULL, "cp ref was unexpectedly cleared"); 5.70 - 5.71 - ConstantPool* pvcp = cp_ref; 5.72 + RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name())); 5.73 + 5.74 + // previous versions are linked together through the InstanceKlass 5.75 + InstanceKlass* pv_node = ik->previous_versions(); 5.76 + InstanceKlass* last = ik; 5.77 + int version = 0; 5.78 + 5.79 + // check the previous versions list 5.80 + for (; pv_node != NULL; ) { 5.81 + 5.82 + ConstantPool* pvcp = pv_node->constants(); 5.83 + assert(pvcp != NULL, "cp ref was unexpectedly cleared"); 5.84 + 5.85 + 5.86 if (!pvcp->on_stack()) { 5.87 // If the constant pool isn't on stack, none of the methods 5.88 - // are executing. Delete all the methods, the constant pool and 5.89 - // and this previous version node. 5.90 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 5.91 - if (method_refs != NULL) { 5.92 - for (int j = method_refs->length() - 1; j >= 0; j--) { 5.93 - Method* method = method_refs->at(j); 5.94 - assert(method != NULL, "method ref was unexpectedly cleared"); 5.95 - method_refs->remove_at(j); 5.96 - // method will be freed with associated class. 5.97 - } 5.98 - } 5.99 - // Remove the constant pool 5.100 - delete pv_node; 5.101 - // Since we are traversing the array backwards, we don't have to 5.102 - // do anything special with the index. 5.103 - ik->previous_versions()->remove_at(i); 5.104 + // are executing. Unlink this previous_version. 5.105 + // The previous version InstanceKlass is on the ClassLoaderData deallocate list 5.106 + // so will be deallocated during the next phase of class unloading. 5.107 + pv_node = pv_node->previous_versions(); 5.108 + last->link_previous_versions(pv_node); 5.109 deleted_count++; 5.110 + version++; 5.111 continue; 5.112 } else { 5.113 - RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i)); 5.114 + RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive", 5.115 + pv_node)); 5.116 assert(pvcp->pool_holder() != NULL, "Constant pool with no holder"); 5.117 guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack"); 5.118 live_count++; 5.119 } 5.120 5.121 - // At least one method is live in this previous version, clean out 5.122 - // the others or mark them as obsolete. 5.123 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 5.124 + // At least one method is live in this previous version so clean its MethodData. 5.125 + // Reset dead EMCP methods not to get breakpoints. 5.126 + // All methods are deallocated when all of the methods for this class are no 5.127 + // longer running. 5.128 + Array<Method*>* method_refs = pv_node->methods(); 5.129 if (method_refs != NULL) { 5.130 RC_TRACE(0x00000200, ("purge: previous methods length=%d", 5.131 method_refs->length())); 5.132 - for (int j = method_refs->length() - 1; j >= 0; j--) { 5.133 + for (int j = 0; j < method_refs->length(); j++) { 5.134 Method* method = method_refs->at(j); 5.135 - assert(method != NULL, "method ref was unexpectedly cleared"); 5.136 - 5.137 - // Remove the emcp method if it's not executing 5.138 - // If it's been made obsolete by a redefinition of a non-emcp 5.139 - // method, mark it as obsolete but leave it to clean up later. 5.140 + 5.141 if (!method->on_stack()) { 5.142 - method_refs->remove_at(j); 5.143 - } else if (emcp_method_count == 0) { 5.144 - method->set_is_obsolete(); 5.145 + // no breakpoints for non-running methods 5.146 + if (method->is_running_emcp()) { 5.147 + method->set_running_emcp(false); 5.148 + } 5.149 } else { 5.150 + assert (method->is_obsolete() || method->is_running_emcp(), 5.151 + "emcp method cannot run after emcp bit is cleared"); 5.152 // RC_TRACE macro has an embedded ResourceMark 5.153 RC_TRACE(0x00000200, 5.154 ("purge: %s(%s): prev method @%d in version @%d is alive", 5.155 method->name()->as_C_string(), 5.156 - method->signature()->as_C_string(), j, i)); 5.157 + method->signature()->as_C_string(), j, version)); 5.158 + if (method->method_data() != NULL) { 5.159 + // Clean out any weak method links for running methods 5.160 + // (also should include not EMCP methods) 5.161 + method->method_data()->clean_weak_method_links(); 5.162 + } 5.163 } 5.164 } 5.165 } 5.166 + // next previous version 5.167 + last = pv_node; 5.168 + pv_node = pv_node->previous_versions(); 5.169 + version++; 5.170 } 5.171 - assert(ik->previous_versions()->length() == live_count, "sanity check"); 5.172 RC_TRACE(0x00000200, 5.173 ("purge: previous version stats: live=%d, deleted=%d", live_count, 5.174 deleted_count)); 5.175 } 5.176 + 5.177 + // Clean MethodData of this class's methods so they don't refer to 5.178 + // old methods that are no longer running. 5.179 + Array<Method*>* methods = ik->methods(); 5.180 + int num_methods = methods->length(); 5.181 + for (int index2 = 0; index2 < num_methods; ++index2) { 5.182 + if (methods->at(index2)->method_data() != NULL) { 5.183 + methods->at(index2)->method_data()->clean_weak_method_links(); 5.184 + } 5.185 + } 5.186 } 5.187 5.188 -// External interface for use during class unloading. 5.189 -void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { 5.190 - // Call with >0 emcp methods since they are not currently being redefined. 5.191 - purge_previous_versions_internal(ik, 1); 5.192 -} 5.193 - 5.194 - 5.195 -// Potentially add an information node that contains pointers to the 5.196 -// interesting parts of the previous version of the_class. 5.197 -// This is also where we clean out any unused references. 5.198 -// Note that while we delete nodes from the _previous_versions 5.199 -// array, we never delete the array itself until the klass is 5.200 -// unloaded. The has_been_redefined() query depends on that fact. 5.201 -// 5.202 -void InstanceKlass::add_previous_version(instanceKlassHandle ikh, 5.203 - BitMap* emcp_methods, int emcp_method_count) { 5.204 - assert(Thread::current()->is_VM_thread(), 5.205 - "only VMThread can add previous versions"); 5.206 - 5.207 - if (_previous_versions == NULL) { 5.208 - // This is the first previous version so make some space. 5.209 - // Start with 2 elements under the assumption that the class 5.210 - // won't be redefined much. 5.211 - _previous_versions = new (ResourceObj::C_HEAP, mtClass) 5.212 - GrowableArray<PreviousVersionNode *>(2, true); 5.213 - } 5.214 - 5.215 - ConstantPool* cp_ref = ikh->constants(); 5.216 - 5.217 - // RC_TRACE macro has an embedded ResourceMark 5.218 - RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d " 5.219 - "on_stack=%d", 5.220 - ikh->external_name(), _previous_versions->length(), emcp_method_count, 5.221 - cp_ref->on_stack())); 5.222 - 5.223 - // If the constant pool for this previous version of the class 5.224 - // is not marked as being on the stack, then none of the methods 5.225 - // in this previous version of the class are on the stack so 5.226 - // we don't need to create a new PreviousVersionNode. However, 5.227 - // we still need to examine older previous versions below. 5.228 - Array<Method*>* old_methods = ikh->methods(); 5.229 - 5.230 - if (cp_ref->on_stack()) { 5.231 - PreviousVersionNode * pv_node = NULL; 5.232 - if (emcp_method_count == 0) { 5.233 - // non-shared ConstantPool gets a reference 5.234 - pv_node = new PreviousVersionNode(cp_ref, NULL); 5.235 - RC_TRACE(0x00000400, 5.236 - ("add: all methods are obsolete; flushing any EMCP refs")); 5.237 - } else { 5.238 - int local_count = 0; 5.239 - GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) 5.240 - GrowableArray<Method*>(emcp_method_count, true); 5.241 - for (int i = 0; i < old_methods->length(); i++) { 5.242 - if (emcp_methods->at(i)) { 5.243 - // this old method is EMCP. Save it only if it's on the stack 5.244 - Method* old_method = old_methods->at(i); 5.245 - if (old_method->on_stack()) { 5.246 - method_refs->append(old_method); 5.247 - } 5.248 - if (++local_count >= emcp_method_count) { 5.249 - // no more EMCP methods so bail out now 5.250 - break; 5.251 - } 5.252 - } 5.253 - } 5.254 - // non-shared ConstantPool gets a reference 5.255 - pv_node = new PreviousVersionNode(cp_ref, method_refs); 5.256 - } 5.257 - // append new previous version. 5.258 - _previous_versions->append(pv_node); 5.259 - } 5.260 - 5.261 - // Since the caller is the VMThread and we are at a safepoint, this 5.262 - // is a good time to clear out unused references. 5.263 - 5.264 - RC_TRACE(0x00000400, ("add: previous version length=%d", 5.265 - _previous_versions->length())); 5.266 - 5.267 - // Purge previous versions not executing on the stack 5.268 - purge_previous_versions_internal(this, emcp_method_count); 5.269 - 5.270 +void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods, 5.271 + int emcp_method_count) { 5.272 int obsolete_method_count = old_methods->length() - emcp_method_count; 5.273 5.274 if (emcp_method_count != 0 && obsolete_method_count != 0 && 5.275 - _previous_versions->length() > 0) { 5.276 + _previous_versions != NULL) { 5.277 // We have a mix of obsolete and EMCP methods so we have to 5.278 // clear out any matching EMCP method entries the hard way. 5.279 int local_count = 0; 5.280 for (int i = 0; i < old_methods->length(); i++) { 5.281 - if (!emcp_methods->at(i)) { 5.282 + Method* old_method = old_methods->at(i); 5.283 + if (old_method->is_obsolete()) { 5.284 // only obsolete methods are interesting 5.285 - Method* old_method = old_methods->at(i); 5.286 Symbol* m_name = old_method->name(); 5.287 Symbol* m_signature = old_method->signature(); 5.288 5.289 - // we might not have added the last entry 5.290 - for (int j = _previous_versions->length() - 1; j >= 0; j--) { 5.291 - // check the previous versions array for non executing obsolete methods 5.292 - PreviousVersionNode * pv_node = _previous_versions->at(j); 5.293 - 5.294 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 5.295 - if (method_refs == NULL) { 5.296 - // We have run into a PreviousVersion generation where 5.297 - // all methods were made obsolete during that generation's 5.298 - // RedefineClasses() operation. At the time of that 5.299 - // operation, all EMCP methods were flushed so we don't 5.300 - // have to go back any further. 5.301 - // 5.302 - // A NULL method_refs is different than an empty method_refs. 5.303 - // We cannot infer any optimizations about older generations 5.304 - // from an empty method_refs for the current generation. 5.305 - break; 5.306 - } 5.307 - 5.308 - for (int k = method_refs->length() - 1; k >= 0; k--) { 5.309 + // previous versions are linked together through the InstanceKlass 5.310 + int j = 0; 5.311 + for (InstanceKlass* prev_version = _previous_versions; 5.312 + prev_version != NULL; 5.313 + prev_version = prev_version->previous_versions(), j++) { 5.314 + 5.315 + Array<Method*>* method_refs = prev_version->methods(); 5.316 + for (int k = 0; k < method_refs->length(); k++) { 5.317 Method* method = method_refs->at(k); 5.318 5.319 if (!method->is_obsolete() && 5.320 @@ -3816,14 +3728,11 @@ 5.321 method->signature() == m_signature) { 5.322 // The current RedefineClasses() call has made all EMCP 5.323 // versions of this method obsolete so mark it as obsolete 5.324 - // and remove the reference. 5.325 RC_TRACE(0x00000400, 5.326 ("add: %s(%s): flush obsolete method @%d in version @%d", 5.327 m_name->as_C_string(), m_signature->as_C_string(), k, j)); 5.328 5.329 method->set_is_obsolete(); 5.330 - // Leave obsolete methods on the previous version list to 5.331 - // clean up later. 5.332 break; 5.333 } 5.334 } 5.335 @@ -3831,9 +3740,9 @@ 5.336 // The previous loop may not find a matching EMCP method, but 5.337 // that doesn't mean that we can optimize and not go any 5.338 // further back in the PreviousVersion generations. The EMCP 5.339 - // method for this generation could have already been deleted, 5.340 + // method for this generation could have already been made obsolete, 5.341 // but there still may be an older EMCP method that has not 5.342 - // been deleted. 5.343 + // been made obsolete. 5.344 } 5.345 5.346 if (++local_count >= obsolete_method_count) { 5.347 @@ -3843,30 +3752,67 @@ 5.348 } 5.349 } 5.350 } 5.351 -} // end add_previous_version() 5.352 - 5.353 - 5.354 -// Determine if InstanceKlass has a previous version. 5.355 -bool InstanceKlass::has_previous_version() const { 5.356 - return (_previous_versions != NULL && _previous_versions->length() > 0); 5.357 -} // end has_previous_version() 5.358 - 5.359 - 5.360 -InstanceKlass* InstanceKlass::get_klass_version(int version) { 5.361 - if (constants()->version() == version) { 5.362 - return this; 5.363 +} 5.364 + 5.365 +// Save the scratch_class as the previous version if any of the methods are running. 5.366 +// The previous_versions are used to set breakpoints in EMCP methods and they are 5.367 +// also used to clean MethodData links to redefined methods that are no longer running. 5.368 +void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, 5.369 + int emcp_method_count) { 5.370 + assert(Thread::current()->is_VM_thread(), 5.371 + "only VMThread can add previous versions"); 5.372 + 5.373 + // RC_TRACE macro has an embedded ResourceMark 5.374 + RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d", 5.375 + scratch_class->external_name(), emcp_method_count)); 5.376 + 5.377 + // Clean out old previous versions 5.378 + purge_previous_versions(this); 5.379 + 5.380 + // Mark newly obsolete methods in remaining previous versions. An EMCP method from 5.381 + // a previous redefinition may be made obsolete by this redefinition. 5.382 + Array<Method*>* old_methods = scratch_class->methods(); 5.383 + mark_newly_obsolete_methods(old_methods, emcp_method_count); 5.384 + 5.385 + // If the constant pool for this previous version of the class 5.386 + // is not marked as being on the stack, then none of the methods 5.387 + // in this previous version of the class are on the stack so 5.388 + // we don't need to add this as a previous version. 5.389 + ConstantPool* cp_ref = scratch_class->constants(); 5.390 + if (!cp_ref->on_stack()) { 5.391 + RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running")); 5.392 + return; 5.393 } 5.394 - PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); 5.395 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 5.396 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 5.397 - ConstantPool* prev_cp = pv_node->prev_constant_pool(); 5.398 - if (prev_cp->version() == version) { 5.399 - return prev_cp->pool_holder(); 5.400 + 5.401 + if (emcp_method_count != 0) { 5.402 + // At least one method is still running, check for EMCP methods 5.403 + for (int i = 0; i < old_methods->length(); i++) { 5.404 + Method* old_method = old_methods->at(i); 5.405 + if (!old_method->is_obsolete() && old_method->on_stack()) { 5.406 + // if EMCP method (not obsolete) is on the stack, mark as EMCP so that 5.407 + // we can add breakpoints for it. 5.408 + 5.409 + // We set the method->on_stack bit during safepoints for class redefinition and 5.410 + // class unloading and use this bit to set the is_running_emcp bit. 5.411 + // After the safepoint, the on_stack bit is cleared and the running emcp 5.412 + // method may exit. If so, we would set a breakpoint in a method that 5.413 + // is never reached, but this won't be noticeable to the programmer. 5.414 + old_method->set_running_emcp(true); 5.415 + RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT, 5.416 + old_method->name_and_sig_as_C_string(), old_method)); 5.417 + } else if (!old_method->is_obsolete()) { 5.418 + RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT, 5.419 + old_method->name_and_sig_as_C_string(), old_method)); 5.420 + } 5.421 } 5.422 } 5.423 - return NULL; // None found 5.424 -} 5.425 - 5.426 + 5.427 + // Add previous version if any methods are still running. 5.428 + RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack")); 5.429 + assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); 5.430 + scratch_class->link_previous_versions(previous_versions()); 5.431 + link_previous_versions(scratch_class()); 5.432 +} // end add_previous_version() 5.433 5.434 Method* InstanceKlass::method_with_idnum(int idnum) { 5.435 Method* m = NULL; 5.436 @@ -3924,61 +3870,3 @@ 5.437 unsigned char * InstanceKlass::get_cached_class_file_bytes() { 5.438 return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file); 5.439 } 5.440 - 5.441 - 5.442 -// Construct a PreviousVersionNode entry for the array hung off 5.443 -// the InstanceKlass. 5.444 -PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, 5.445 - GrowableArray<Method*>* prev_EMCP_methods) { 5.446 - 5.447 - _prev_constant_pool = prev_constant_pool; 5.448 - _prev_EMCP_methods = prev_EMCP_methods; 5.449 -} 5.450 - 5.451 - 5.452 -// Destroy a PreviousVersionNode 5.453 -PreviousVersionNode::~PreviousVersionNode() { 5.454 - if (_prev_constant_pool != NULL) { 5.455 - _prev_constant_pool = NULL; 5.456 - } 5.457 - 5.458 - if (_prev_EMCP_methods != NULL) { 5.459 - delete _prev_EMCP_methods; 5.460 - } 5.461 -} 5.462 - 5.463 -// Construct a helper for walking the previous versions array 5.464 -PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { 5.465 - _thread = thread; 5.466 - _previous_versions = ik->previous_versions(); 5.467 - _current_index = 0; 5.468 - _current_p = NULL; 5.469 - _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); 5.470 -} 5.471 - 5.472 - 5.473 -// Return the interesting information for the next previous version 5.474 -// of the klass. Returns NULL if there are no more previous versions. 5.475 -PreviousVersionNode* PreviousVersionWalker::next_previous_version() { 5.476 - if (_previous_versions == NULL) { 5.477 - // no previous versions so nothing to return 5.478 - return NULL; 5.479 - } 5.480 - 5.481 - _current_p = NULL; // reset to NULL 5.482 - _current_constant_pool_handle = NULL; 5.483 - 5.484 - int length = _previous_versions->length(); 5.485 - 5.486 - while (_current_index < length) { 5.487 - PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); 5.488 - 5.489 - // Save a handle to the constant pool for this previous version, 5.490 - // which keeps all the methods from being deallocated. 5.491 - _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); 5.492 - _current_p = pv_node; 5.493 - return pv_node; 5.494 - } 5.495 - 5.496 - return NULL; 5.497 -} // end next_previous_version()
6.1 --- a/src/share/vm/oops/instanceKlass.hpp Thu Jan 25 08:16:32 2018 -0800 6.2 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Jan 26 10:39:27 2018 -0800 6.3 @@ -88,7 +88,6 @@ 6.4 class fieldDescriptor; 6.5 class DepChange; 6.6 class nmethodBucket; 6.7 -class PreviousVersionNode; 6.8 class JvmtiCachedClassFieldMap; 6.9 class MemberNameTable; 6.10 6.11 @@ -235,7 +234,8 @@ 6.12 _misc_is_anonymous = 1 << 3, // has embedded _host_klass field 6.13 _misc_is_contended = 1 << 4, // marked with contended annotation 6.14 _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods 6.15 - _misc_declares_default_methods = 1 << 6 // directly declares default methods (any access) 6.16 + _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access) 6.17 + _misc_has_been_redefined = 1 << 7 // class has been redefined 6.18 }; 6.19 u2 _misc_flags; 6.20 u2 _minor_version; // minor version number of class file 6.21 @@ -250,9 +250,8 @@ 6.22 nmethodBucket* _dependencies; // list of dependent nmethods 6.23 nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class 6.24 BreakpointInfo* _breakpoints; // bpt lists, managed by Method* 6.25 - // Array of interesting part(s) of the previous version(s) of this 6.26 - // InstanceKlass. See PreviousVersionWalker below. 6.27 - GrowableArray<PreviousVersionNode *>* _previous_versions; 6.28 + // Linked instanceKlasses of previous versions 6.29 + InstanceKlass* _previous_versions; 6.30 // JVMTI fields can be moved to their own structure - see 6315920 6.31 // JVMTI: cached class file, before retransformable agent modified it in CFLH 6.32 JvmtiCachedClassFileData* _cached_class_file; 6.33 @@ -669,21 +668,31 @@ 6.34 } 6.35 6.36 // RedefineClasses() support for previous versions: 6.37 - void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods, 6.38 - int emcp_method_count); 6.39 - // If the _previous_versions array is non-NULL, then this klass 6.40 - // has been redefined at least once even if we aren't currently 6.41 - // tracking a previous version. 6.42 - bool has_been_redefined() const { return _previous_versions != NULL; } 6.43 - bool has_previous_version() const; 6.44 + void add_previous_version(instanceKlassHandle ikh, int emcp_method_count); 6.45 + 6.46 + InstanceKlass* previous_versions() const { return _previous_versions; } 6.47 + 6.48 + bool has_been_redefined() const { 6.49 + return (_misc_flags & _misc_has_been_redefined) != 0; 6.50 + } 6.51 + void set_has_been_redefined() { 6.52 + _misc_flags |= _misc_has_been_redefined; 6.53 + } 6.54 + 6.55 void init_previous_versions() { 6.56 _previous_versions = NULL; 6.57 } 6.58 - GrowableArray<PreviousVersionNode *>* previous_versions() const { 6.59 - return _previous_versions; 6.60 + 6.61 + 6.62 + InstanceKlass* get_klass_version(int version) { 6.63 + for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) { 6.64 + if (ik->constants()->version() == version) { 6.65 + return ik; 6.66 + } 6.67 + } 6.68 + return NULL; 6.69 } 6.70 6.71 - InstanceKlass* get_klass_version(int version); 6.72 static void purge_previous_versions(InstanceKlass* ik); 6.73 6.74 // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation 6.75 @@ -1124,6 +1133,10 @@ 6.76 6.77 // Free CHeap allocated fields. 6.78 void release_C_heap_structures(); 6.79 + 6.80 + // RedefineClasses support 6.81 + void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; } 6.82 + void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count); 6.83 public: 6.84 // CDS support - remove and restore oops from metadata. Oops are not shared. 6.85 virtual void remove_unshareable_info(); 6.86 @@ -1222,62 +1235,6 @@ 6.87 }; 6.88 6.89 6.90 -// If breakpoints are more numerous than just JVMTI breakpoints, 6.91 -// consider compressing this data structure. 6.92 -// It is currently a simple linked list defined in method.hpp. 6.93 - 6.94 -class BreakpointInfo; 6.95 - 6.96 - 6.97 -// A collection point for interesting information about the previous 6.98 -// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes 6.99 -// is attached to the InstanceKlass as needed. See PreviousVersionWalker below. 6.100 -class PreviousVersionNode : public CHeapObj<mtClass> { 6.101 - private: 6.102 - ConstantPool* _prev_constant_pool; 6.103 - 6.104 - // If the previous version of the InstanceKlass doesn't have any 6.105 - // EMCP methods, then _prev_EMCP_methods will be NULL. If all the 6.106 - // EMCP methods have been collected, then _prev_EMCP_methods can 6.107 - // have a length of zero. 6.108 - GrowableArray<Method*>* _prev_EMCP_methods; 6.109 - 6.110 -public: 6.111 - PreviousVersionNode(ConstantPool* prev_constant_pool, 6.112 - GrowableArray<Method*>* prev_EMCP_methods); 6.113 - ~PreviousVersionNode(); 6.114 - ConstantPool* prev_constant_pool() const { 6.115 - return _prev_constant_pool; 6.116 - } 6.117 - GrowableArray<Method*>* prev_EMCP_methods() const { 6.118 - return _prev_EMCP_methods; 6.119 - } 6.120 -}; 6.121 - 6.122 - 6.123 -// Helper object for walking previous versions. 6.124 -class PreviousVersionWalker : public StackObj { 6.125 - private: 6.126 - Thread* _thread; 6.127 - GrowableArray<PreviousVersionNode *>* _previous_versions; 6.128 - int _current_index; 6.129 - 6.130 - // A pointer to the current node object so we can handle the deletes. 6.131 - PreviousVersionNode* _current_p; 6.132 - 6.133 - // The constant pool handle keeps all the methods in this class from being 6.134 - // deallocated from the metaspace during class unloading. 6.135 - constantPoolHandle _current_constant_pool_handle; 6.136 - 6.137 - public: 6.138 - PreviousVersionWalker(Thread* thread, InstanceKlass *ik); 6.139 - 6.140 - // Return the interesting information for the next previous version 6.141 - // of the klass. Returns NULL if there are no more previous versions. 6.142 - PreviousVersionNode* next_previous_version(); 6.143 -}; 6.144 - 6.145 - 6.146 // 6.147 // nmethodBucket is used to record dependent nmethods for 6.148 // deoptimization. nmethod dependencies are actually <klass, method>
7.1 --- a/src/share/vm/oops/klass.cpp Thu Jan 25 08:16:32 2018 -0800 7.2 +++ b/src/share/vm/oops/klass.cpp Fri Jan 26 10:39:27 2018 -0800 7.3 @@ -455,6 +455,12 @@ 7.4 if (clean_alive_klasses && current->oop_is_instance()) { 7.5 InstanceKlass* ik = InstanceKlass::cast(current); 7.6 ik->clean_weak_instanceklass_links(is_alive); 7.7 + 7.8 + // JVMTI RedefineClasses creates previous versions that are not in 7.9 + // the class hierarchy, so process them here. 7.10 + while ((ik = ik->previous_versions()) != NULL) { 7.11 + ik->clean_weak_instanceklass_links(is_alive); 7.12 + } 7.13 } 7.14 } 7.15 }
8.1 --- a/src/share/vm/oops/method.cpp Thu Jan 25 08:16:32 2018 -0800 8.2 +++ b/src/share/vm/oops/method.cpp Fri Jan 26 10:39:27 2018 -0800 8.3 @@ -91,6 +91,7 @@ 8.4 set_hidden(false); 8.5 set_dont_inline(false); 8.6 set_has_injected_profile(false); 8.7 + set_running_emcp(false); 8.8 set_method_data(NULL); 8.9 clear_method_counters(); 8.10 set_vtable_index(Method::garbage_vtable_index);
9.1 --- a/src/share/vm/oops/method.hpp Thu Jan 25 08:16:32 2018 -0800 9.2 +++ b/src/share/vm/oops/method.hpp Fri Jan 26 10:39:27 2018 -0800 9.3 @@ -111,6 +111,7 @@ 9.4 _caller_sensitive : 1, 9.5 _force_inline : 1, 9.6 _hidden : 1, 9.7 + _running_emcp : 1, 9.8 _dont_inline : 1, 9.9 _has_injected_profile : 1, 9.10 : 2; 9.11 @@ -712,6 +713,21 @@ 9.12 void set_is_obsolete() { _access_flags.set_is_obsolete(); } 9.13 bool is_deleted() const { return access_flags().is_deleted(); } 9.14 void set_is_deleted() { _access_flags.set_is_deleted(); } 9.15 + 9.16 + bool is_running_emcp() const { 9.17 + // EMCP methods are old but not obsolete or deleted. Equivalent 9.18 + // Modulo Constant Pool means the method is equivalent except 9.19 + // the constant pool and instructions that access the constant 9.20 + // pool might be different. 9.21 + // If a breakpoint is set in a redefined method, its EMCP methods that are 9.22 + // still running must have a breakpoint also. 9.23 + return _running_emcp; 9.24 + } 9.25 + 9.26 + void set_running_emcp(bool x) { 9.27 + _running_emcp = x; 9.28 + } 9.29 + 9.30 bool on_stack() const { return access_flags().on_stack(); } 9.31 void set_on_stack(const bool value); 9.32
10.1 --- a/src/share/vm/oops/methodData.cpp Thu Jan 25 08:16:32 2018 -0800 10.2 +++ b/src/share/vm/oops/methodData.cpp Fri Jan 26 10:39:27 2018 -0800 10.3 @@ -1559,9 +1559,35 @@ 10.4 } 10.5 } 10.6 10.7 -// Remove SpeculativeTrapData entries that reference an unloaded 10.8 -// method 10.9 -void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { 10.10 +class CleanExtraDataClosure : public StackObj { 10.11 +public: 10.12 + virtual bool is_live(Method* m) = 0; 10.13 +}; 10.14 + 10.15 +// Check for entries that reference an unloaded method 10.16 +class CleanExtraDataKlassClosure : public CleanExtraDataClosure { 10.17 +private: 10.18 + BoolObjectClosure* _is_alive; 10.19 +public: 10.20 + CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {} 10.21 + bool is_live(Method* m) { 10.22 + return m->method_holder()->is_loader_alive(_is_alive); 10.23 + } 10.24 +}; 10.25 + 10.26 +// Check for entries that reference a redefined method 10.27 +class CleanExtraDataMethodClosure : public CleanExtraDataClosure { 10.28 +public: 10.29 + CleanExtraDataMethodClosure() {} 10.30 + bool is_live(Method* m) { 10.31 + return m->on_stack(); 10.32 + } 10.33 +}; 10.34 + 10.35 + 10.36 +// Remove SpeculativeTrapData entries that reference an unloaded or 10.37 +// redefined method 10.38 +void MethodData::clean_extra_data(CleanExtraDataClosure* cl) { 10.39 DataLayout* dp = extra_data_base(); 10.40 DataLayout* end = extra_data_limit(); 10.41 10.42 @@ -1572,7 +1598,7 @@ 10.43 SpeculativeTrapData* data = new SpeculativeTrapData(dp); 10.44 Method* m = data->method(); 10.45 assert(m != NULL, "should have a method"); 10.46 - if (!m->method_holder()->is_loader_alive(is_alive)) { 10.47 + if (!cl->is_live(m)) { 10.48 // "shift" accumulates the number of cells for dead 10.49 // SpeculativeTrapData entries that have been seen so 10.50 // far. Following entries must be shifted left by that many 10.51 @@ -1603,9 +1629,9 @@ 10.52 } 10.53 } 10.54 10.55 -// Verify there's no unloaded method referenced by a 10.56 +// Verify there's no unloaded or redefined method referenced by a 10.57 // SpeculativeTrapData entry 10.58 -void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { 10.59 +void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { 10.60 #ifdef ASSERT 10.61 DataLayout* dp = extra_data_base(); 10.62 DataLayout* end = extra_data_limit(); 10.63 @@ -1615,7 +1641,7 @@ 10.64 case DataLayout::speculative_trap_data_tag: { 10.65 SpeculativeTrapData* data = new SpeculativeTrapData(dp); 10.66 Method* m = data->method(); 10.67 - assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); 10.68 + assert(m != NULL && cl->is_live(m), "Method should exist"); 10.69 break; 10.70 } 10.71 case DataLayout::bit_data_tag: 10.72 @@ -1641,6 +1667,19 @@ 10.73 parameters->clean_weak_klass_links(is_alive); 10.74 } 10.75 10.76 - clean_extra_data(is_alive); 10.77 - verify_extra_data_clean(is_alive); 10.78 + CleanExtraDataKlassClosure cl(is_alive); 10.79 + clean_extra_data(&cl); 10.80 + verify_extra_data_clean(&cl); 10.81 } 10.82 + 10.83 +void MethodData::clean_weak_method_links() { 10.84 + for (ProfileData* data = first_data(); 10.85 + is_valid(data); 10.86 + data = next_data(data)) { 10.87 + data->clean_weak_method_links(); 10.88 + } 10.89 + 10.90 + CleanExtraDataMethodClosure cl; 10.91 + clean_extra_data(&cl); 10.92 + verify_extra_data_clean(&cl); 10.93 +}
11.1 --- a/src/share/vm/oops/methodData.hpp Thu Jan 25 08:16:32 2018 -0800 11.2 +++ b/src/share/vm/oops/methodData.hpp Fri Jan 26 10:39:27 2018 -0800 11.3 @@ -251,6 +251,9 @@ 11.4 11.5 // GC support 11.6 void clean_weak_klass_links(BoolObjectClosure* cl); 11.7 + 11.8 + // Redefinition support 11.9 + void clean_weak_method_links(); 11.10 }; 11.11 11.12 11.13 @@ -508,6 +511,9 @@ 11.14 // GC support 11.15 virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {} 11.16 11.17 + // Redefinition support 11.18 + virtual void clean_weak_method_links() {} 11.19 + 11.20 // CI translation: ProfileData can represent both MethodDataOop data 11.21 // as well as CIMethodData data. This function is provided for translating 11.22 // an oop in a ProfileData to the ci equivalent. Generally speaking, 11.23 @@ -2030,6 +2036,7 @@ 11.24 // 11.25 11.26 CC_INTERP_ONLY(class BytecodeInterpreter;) 11.27 +class CleanExtraDataClosure; 11.28 11.29 class MethodData : public Metadata { 11.30 friend class VMStructs; 11.31 @@ -2183,9 +2190,9 @@ 11.32 static bool profile_parameters_jsr292_only(); 11.33 static bool profile_all_parameters(); 11.34 11.35 - void clean_extra_data(BoolObjectClosure* is_alive); 11.36 + void clean_extra_data(CleanExtraDataClosure* cl); 11.37 void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); 11.38 - void verify_extra_data_clean(BoolObjectClosure* is_alive); 11.39 + void verify_extra_data_clean(CleanExtraDataClosure* cl); 11.40 11.41 public: 11.42 static int header_size() { 11.43 @@ -2477,6 +2484,8 @@ 11.44 static bool profile_return_jsr292_only(); 11.45 11.46 void clean_method_data(BoolObjectClosure* is_alive); 11.47 + 11.48 + void clean_weak_method_links(); 11.49 }; 11.50 11.51 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
12.1 --- a/src/share/vm/prims/jvmtiImpl.cpp Thu Jan 25 08:16:32 2018 -0800 12.2 +++ b/src/share/vm/prims/jvmtiImpl.cpp Fri Jan 26 10:39:27 2018 -0800 12.3 @@ -282,39 +282,22 @@ 12.4 void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { 12.5 ((Method*)_method->*meth_act)(_bci); 12.6 12.7 - // add/remove breakpoint to/from versions of the method that 12.8 - // are EMCP. Directly or transitively obsolete methods are 12.9 - // not saved in the PreviousVersionNodes. 12.10 + // add/remove breakpoint to/from versions of the method that are EMCP. 12.11 Thread *thread = Thread::current(); 12.12 instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder()); 12.13 Symbol* m_name = _method->name(); 12.14 Symbol* m_signature = _method->signature(); 12.15 12.16 // search previous versions if they exist 12.17 - PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh()); 12.18 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 12.19 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 12.20 - GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods(); 12.21 - 12.22 - if (methods == NULL) { 12.23 - // We have run into a PreviousVersion generation where 12.24 - // all methods were made obsolete during that generation's 12.25 - // RedefineClasses() operation. At the time of that 12.26 - // operation, all EMCP methods were flushed so we don't 12.27 - // have to go back any further. 12.28 - // 12.29 - // A NULL methods array is different than an empty methods 12.30 - // array. We cannot infer any optimizations about older 12.31 - // generations from an empty methods array for the current 12.32 - // generation. 12.33 - break; 12.34 - } 12.35 + for (InstanceKlass* pv_node = ikh->previous_versions(); 12.36 + pv_node != NULL; 12.37 + pv_node = pv_node->previous_versions()) { 12.38 + Array<Method*>* methods = pv_node->methods(); 12.39 12.40 for (int i = methods->length() - 1; i >= 0; i--) { 12.41 Method* method = methods->at(i); 12.42 - // obsolete methods that are running are not deleted from 12.43 - // previous version array, but they are skipped here. 12.44 - if (!method->is_obsolete() && 12.45 + // Only set breakpoints in running EMCP methods. 12.46 + if (method->is_running_emcp() && 12.47 method->name() == m_name && 12.48 method->signature() == m_signature) { 12.49 RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
13.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Jan 25 08:16:32 2018 -0800 13.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Jan 26 10:39:27 2018 -0800 13.3 @@ -3435,13 +3435,12 @@ 13.4 } 13.5 13.6 // the previous versions' constant pool caches may need adjustment 13.7 - PreviousVersionWalker pvw(_thread, ik); 13.8 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 13.9 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 13.10 - other_cp = pv_node->prev_constant_pool(); 13.11 - cp_cache = other_cp->cache(); 13.12 + for (InstanceKlass* pv_node = ik->previous_versions(); 13.13 + pv_node != NULL; 13.14 + pv_node = pv_node->previous_versions()) { 13.15 + cp_cache = pv_node->constants()->cache(); 13.16 if (cp_cache != NULL) { 13.17 - cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed); 13.18 + cp_cache->adjust_method_entries(pv_node, &trace_name_printed); 13.19 } 13.20 } 13.21 } 13.22 @@ -3461,9 +3460,8 @@ 13.23 } 13.24 } 13.25 13.26 -void VM_RedefineClasses::check_methods_and_mark_as_obsolete( 13.27 - BitMap *emcp_methods, int * emcp_method_count_p) { 13.28 - *emcp_method_count_p = 0; 13.29 +int VM_RedefineClasses::check_methods_and_mark_as_obsolete() { 13.30 + int emcp_method_count = 0; 13.31 int obsolete_count = 0; 13.32 int old_index = 0; 13.33 for (int j = 0; j < _matching_methods_length; ++j, ++old_index) { 13.34 @@ -3537,9 +3535,9 @@ 13.35 // that we get from effectively overwriting the old methods 13.36 // when the new methods are attached to the_class. 13.37 13.38 - // track which methods are EMCP for add_previous_version() call 13.39 - emcp_methods->set_bit(old_index); 13.40 - (*emcp_method_count_p)++; 13.41 + // Count number of methods that are EMCP. The method will be marked 13.42 + // old but not obsolete if it is EMCP. 13.43 + emcp_method_count++; 13.44 13.45 // An EMCP method is _not_ obsolete. An obsolete method has a 13.46 // different jmethodID than the current method. An EMCP method 13.47 @@ -3589,10 +3587,11 @@ 13.48 old_method->name()->as_C_string(), 13.49 old_method->signature()->as_C_string())); 13.50 } 13.51 - assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(), 13.52 + assert((emcp_method_count + obsolete_count) == _old_methods->length(), 13.53 "sanity check"); 13.54 - RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p, 13.55 + RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count, 13.56 obsolete_count)); 13.57 + return emcp_method_count; 13.58 } 13.59 13.60 // This internal class transfers the native function registration from old methods 13.61 @@ -3973,11 +3972,8 @@ 13.62 old_constants->set_pool_holder(scratch_class()); 13.63 #endif 13.64 13.65 - // track which methods are EMCP for add_previous_version() call below 13.66 - BitMap emcp_methods(_old_methods->length()); 13.67 - int emcp_method_count = 0; 13.68 - emcp_methods.clear(); // clears 0..(length() - 1) 13.69 - check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count); 13.70 + // track number of methods that are EMCP for add_previous_version() call below 13.71 + int emcp_method_count = check_methods_and_mark_as_obsolete(); 13.72 transfer_old_native_function_registrations(the_class); 13.73 13.74 // The class file bytes from before any retransformable agents mucked 13.75 @@ -4064,9 +4060,10 @@ 13.76 scratch_class->enclosing_method_method_index()); 13.77 scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx); 13.78 13.79 + the_class->set_has_been_redefined(); 13.80 + 13.81 // keep track of previous versions of this class 13.82 - the_class->add_previous_version(scratch_class, &emcp_methods, 13.83 - emcp_method_count); 13.84 + the_class->add_previous_version(scratch_class, emcp_method_count); 13.85 13.86 RC_TIMER_STOP(_timer_rsc_phase1); 13.87 RC_TIMER_START(_timer_rsc_phase2);
14.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Thu Jan 25 08:16:32 2018 -0800 14.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Fri Jan 26 10:39:27 2018 -0800 14.3 @@ -403,14 +403,9 @@ 14.4 // Change jmethodIDs to point to the new methods 14.5 void update_jmethod_ids(); 14.6 14.7 - // In addition to marking methods as obsolete, this routine 14.8 - // records which methods are EMCP (Equivalent Module Constant 14.9 - // Pool) in the emcp_methods BitMap and returns the number of 14.10 - // EMCP methods via emcp_method_count_p. This information is 14.11 - // used when information about the previous version of the_class 14.12 - // is squirreled away. 14.13 - void check_methods_and_mark_as_obsolete(BitMap *emcp_methods, 14.14 - int * emcp_method_count_p); 14.15 + // In addition to marking methods as old and/or obsolete, this routine 14.16 + // counts the number of methods that are EMCP (Equivalent Module Constant Pool). 14.17 + int check_methods_and_mark_as_obsolete(); 14.18 void transfer_old_native_function_registrations(instanceKlassHandle the_class); 14.19 14.20 // Install the redefinition of a class
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/compiler/profiling/spectrapredefineclass/Agent.java Fri Jan 26 10:39:27 2018 -0800 15.3 @@ -0,0 +1,142 @@ 15.4 +/* 15.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 + 15.27 +import java.security.*; 15.28 +import java.lang.instrument.*; 15.29 +import java.lang.reflect.*; 15.30 +import java.lang.management.ManagementFactory; 15.31 +import com.sun.tools.attach.VirtualMachine; 15.32 + 15.33 +class A { 15.34 + void m() { 15.35 + } 15.36 +} 15.37 + 15.38 +class B extends A { 15.39 + void m() { 15.40 + } 15.41 +} 15.42 + 15.43 +class C extends A { 15.44 + void m() { 15.45 + } 15.46 +} 15.47 + 15.48 +class Test { 15.49 + 15.50 + static public void m() throws Exception { 15.51 + for (int i = 0; i < 20000; i++) { 15.52 + m1(a); 15.53 + } 15.54 + for (int i = 0; i < 4; i++) { 15.55 + m1(b); 15.56 + } 15.57 + } 15.58 + 15.59 + static boolean m1(A a) { 15.60 + boolean res = Agent.m2(a); 15.61 + return res; 15.62 + } 15.63 + 15.64 + static public A a = new A(); 15.65 + static public B b = new B(); 15.66 + static public C c = new C(); 15.67 +} 15.68 + 15.69 +public class Agent implements ClassFileTransformer { 15.70 + 15.71 + 15.72 + static class MemoryChunk { 15.73 + MemoryChunk other; 15.74 + long[] array; 15.75 + MemoryChunk(MemoryChunk other) { 15.76 + other = other; 15.77 + array = new long[1024 * 1024 * 1024]; 15.78 + } 15.79 + } 15.80 + 15.81 + static public boolean m2(A a) { 15.82 + boolean res = false; 15.83 + if (a.getClass() == B.class) { 15.84 + a.m(); 15.85 + } else { 15.86 + res = true; 15.87 + } 15.88 + return res; 15.89 + } 15.90 + 15.91 + static public void main(String[] args) throws Exception { 15.92 + // Create speculative trap entries 15.93 + Test.m(); 15.94 + 15.95 + String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); 15.96 + int p = nameOfRunningVM.indexOf('@'); 15.97 + String pid = nameOfRunningVM.substring(0, p); 15.98 + 15.99 + // Make the nmethod go away 15.100 + for (int i = 0; i < 10; i++) { 15.101 + System.gc(); 15.102 + } 15.103 + 15.104 + // Redefine class 15.105 + try { 15.106 + VirtualMachine vm = VirtualMachine.attach(pid); 15.107 + vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", ""); 15.108 + vm.detach(); 15.109 + } catch (Exception e) { 15.110 + throw new RuntimeException(e); 15.111 + } 15.112 + 15.113 + Test.m(); 15.114 + // GC will hit dead method pointer 15.115 + for (int i = 0; i < 10; i++) { 15.116 + System.gc(); 15.117 + } 15.118 + } 15.119 + 15.120 + public synchronized byte[] transform(final ClassLoader classLoader, 15.121 + final String className, 15.122 + Class<?> classBeingRedefined, 15.123 + ProtectionDomain protectionDomain, 15.124 + byte[] classfileBuffer) { 15.125 + System.out.println("Transforming class " + className); 15.126 + return classfileBuffer; 15.127 + } 15.128 + 15.129 + public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) { 15.130 + 15.131 + try { 15.132 + instrumentation.retransformClasses(to_redefine); 15.133 + } catch (Exception e) { 15.134 + e.printStackTrace(); 15.135 + } 15.136 + 15.137 + } 15.138 + 15.139 + public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception { 15.140 + Agent transformer = new Agent(); 15.141 + instrumentation.addTransformer(transformer, true); 15.142 + 15.143 + redefine(agentArgs, instrumentation, Test.class); 15.144 + } 15.145 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/compiler/profiling/spectrapredefineclass/Launcher.java Fri Jan 26 10:39:27 2018 -0800 16.3 @@ -0,0 +1,47 @@ 16.4 +/* 16.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 +import java.io.PrintWriter; 16.27 +import com.oracle.java.testlibrary.*; 16.28 + 16.29 +/* 16.30 + * @test 16.31 + * @bug 8038636 16.32 + * @library /testlibrary 16.33 + * @build Agent 16.34 + * @run main ClassFileInstaller Agent 16.35 + * @run main Launcher 16.36 + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent 16.37 + */ 16.38 +public class Launcher { 16.39 + public static void main(String[] args) throws Exception { 16.40 + 16.41 + PrintWriter pw = new PrintWriter("MANIFEST.MF"); 16.42 + pw.println("Agent-Class: Agent"); 16.43 + pw.println("Can-Retransform-Classes: true"); 16.44 + pw.close(); 16.45 + 16.46 + ProcessBuilder pb = new ProcessBuilder(); 16.47 + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"}); 16.48 + pb.start().waitFor(); 16.49 + } 16.50 +}
17.1 --- a/test/runtime/RedefineFinalizer/RedefineFinalizer.java Thu Jan 25 08:16:32 2018 -0800 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,64 +0,0 @@ 17.4 -/* 17.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 17.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 - * 17.8 - * This code is free software; you can redistribute it and/or modify it 17.9 - * under the terms of the GNU General Public License version 2 only, as 17.10 - * published by the Free Software Foundation. 17.11 - * 17.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 17.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.15 - * version 2 for more details (a copy is included in the LICENSE file that 17.16 - * accompanied this code). 17.17 - * 17.18 - * You should have received a copy of the GNU General Public License version 17.19 - * 2 along with this work; if not, write to the Free Software Foundation, 17.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.21 - * 17.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.23 - * or visit www.oracle.com if you need additional information or have any 17.24 - * questions. 17.25 - */ 17.26 - 17.27 -/* 17.28 - * @test 17.29 - * @bug 6904403 17.30 - * @summary Don't assert if we redefine finalize method 17.31 - * @library /testlibrary 17.32 - * @build RedefineClassHelper 17.33 - * @run main RedefineClassHelper 17.34 - * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer 17.35 - */ 17.36 - 17.37 -/* 17.38 - * Regression test for hitting: 17.39 - * 17.40 - * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer 17.41 - * 17.42 - * when redefining finalizer method 17.43 - */ 17.44 -public class RedefineFinalizer { 17.45 - 17.46 - public static String newB = 17.47 - "class RedefineFinalizer$B {" + 17.48 - " protected void finalize() { " + 17.49 - " System.out.println(\"Finalizer called\");" + 17.50 - " }" + 17.51 - "}"; 17.52 - 17.53 - public static void main(String[] args) throws Exception { 17.54 - RedefineClassHelper.redefineClass(B.class, newB); 17.55 - 17.56 - A a = new A(); 17.57 - } 17.58 - 17.59 - static class A extends B { 17.60 - } 17.61 - 17.62 - static class B { 17.63 - protected void finalize() { 17.64 - // should be empty 17.65 - } 17.66 - } 17.67 -}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/test/runtime/RedefineTests/RedefineFinalizer.java Fri Jan 26 10:39:27 2018 -0800 18.3 @@ -0,0 +1,64 @@ 18.4 +/* 18.5 + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 18.7 + * 18.8 + * This code is free software; you can redistribute it and/or modify it 18.9 + * under the terms of the GNU General Public License version 2 only, as 18.10 + * published by the Free Software Foundation. 18.11 + * 18.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 18.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18.15 + * version 2 for more details (a copy is included in the LICENSE file that 18.16 + * accompanied this code). 18.17 + * 18.18 + * You should have received a copy of the GNU General Public License version 18.19 + * 2 along with this work; if not, write to the Free Software Foundation, 18.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18.21 + * 18.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 18.23 + * or visit www.oracle.com if you need additional information or have any 18.24 + * questions. 18.25 + */ 18.26 + 18.27 +/* 18.28 + * @test 18.29 + * @bug 6904403 18.30 + * @summary Don't assert if we redefine finalize method 18.31 + * @library /testlibrary 18.32 + * @build RedefineClassHelper 18.33 + * @run main RedefineClassHelper 18.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer 18.35 + */ 18.36 + 18.37 +/* 18.38 + * Regression test for hitting: 18.39 + * 18.40 + * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer 18.41 + * 18.42 + * when redefining finalizer method 18.43 + */ 18.44 +public class RedefineFinalizer { 18.45 + 18.46 + public static String newB = 18.47 + "class RedefineFinalizer$B {" + 18.48 + " protected void finalize() { " + 18.49 + " System.out.println(\"Finalizer called\");" + 18.50 + " }" + 18.51 + "}"; 18.52 + 18.53 + public static void main(String[] args) throws Exception { 18.54 + RedefineClassHelper.redefineClass(B.class, newB); 18.55 + 18.56 + A a = new A(); 18.57 + } 18.58 + 18.59 + static class A extends B { 18.60 + } 18.61 + 18.62 + static class B { 18.63 + protected void finalize() { 18.64 + // should be empty 18.65 + } 18.66 + } 18.67 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/test/runtime/RedefineTests/RedefineRunningMethods.java Fri Jan 26 10:39:27 2018 -0800 19.3 @@ -0,0 +1,143 @@ 19.4 +/* 19.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 19.7 + * 19.8 + * This code is free software; you can redistribute it and/or modify it 19.9 + * under the terms of the GNU General Public License version 2 only, as 19.10 + * published by the Free Software Foundation. 19.11 + * 19.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 19.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19.15 + * version 2 for more details (a copy is included in the LICENSE file that 19.16 + * accompanied this code). 19.17 + * 19.18 + * You should have received a copy of the GNU General Public License version 19.19 + * 2 along with this work; if not, write to the Free Software Foundation, 19.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19.21 + * 19.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19.23 + * or visit www.oracle.com if you need additional information or have any 19.24 + * questions. 19.25 + */ 19.26 + 19.27 +/* 19.28 + * @test 19.29 + * @bug 8055008 19.30 + * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop 19.31 + * @library /testlibrary 19.32 + * @build RedefineClassHelper 19.33 + * @run main RedefineClassHelper 19.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethods 19.35 + */ 19.36 +public class RedefineRunningMethods { 19.37 + 19.38 + public static String newB = 19.39 + "class RedefineRunningMethods$B {" + 19.40 + " static int count1 = 0;" + 19.41 + " static int count2 = 0;" + 19.42 + " public static volatile boolean stop = false;" + 19.43 + " static void localSleep() { " + 19.44 + " try{ " + 19.45 + " Thread.currentThread().sleep(10);" + 19.46 + " } catch(InterruptedException ie) { " + 19.47 + " } " + 19.48 + " } " + 19.49 + " public static void infinite() { " + 19.50 + " System.out.println(\"infinite called\");" + 19.51 + " }" + 19.52 + " public static void infinite_emcp() { " + 19.53 + " while (!stop) { count2++; localSleep(); }" + 19.54 + " }" + 19.55 + "}"; 19.56 + 19.57 + public static String evenNewerB = 19.58 + "class RedefineRunningMethods$B {" + 19.59 + " static int count1 = 0;" + 19.60 + " static int count2 = 0;" + 19.61 + " public static volatile boolean stop = false;" + 19.62 + " static void localSleep() { " + 19.63 + " try{ " + 19.64 + " Thread.currentThread().sleep(1);" + 19.65 + " } catch(InterruptedException ie) { " + 19.66 + " } " + 19.67 + " } " + 19.68 + " public static void infinite() { }" + 19.69 + " public static void infinite_emcp() { " + 19.70 + " System.out.println(\"infinite_emcp now obsolete called\");" + 19.71 + " }" + 19.72 + "}"; 19.73 + 19.74 + static class B { 19.75 + static int count1 = 0; 19.76 + static int count2 = 0; 19.77 + public static volatile boolean stop = false; 19.78 + static void localSleep() { 19.79 + try{ 19.80 + Thread.currentThread().sleep(10);//sleep for 10 ms 19.81 + } catch(InterruptedException ie) { 19.82 + } 19.83 + } 19.84 + 19.85 + public static void infinite() { 19.86 + while (!stop) { count1++; localSleep(); } 19.87 + } 19.88 + public static void infinite_emcp() { 19.89 + while (!stop) { count2++; localSleep(); } 19.90 + } 19.91 + } 19.92 + 19.93 + 19.94 + public static void main(String[] args) throws Exception { 19.95 + 19.96 + new Thread() { 19.97 + public void run() { 19.98 + B.infinite(); 19.99 + } 19.100 + }.start(); 19.101 + 19.102 + new Thread() { 19.103 + public void run() { 19.104 + B.infinite_emcp(); 19.105 + } 19.106 + }.start(); 19.107 + 19.108 + RedefineClassHelper.redefineClass(B.class, newB); 19.109 + 19.110 + System.gc(); 19.111 + 19.112 + B.infinite(); 19.113 + 19.114 + // Start a thread with the second version of infinite_emcp running 19.115 + new Thread() { 19.116 + public void run() { 19.117 + B.infinite_emcp(); 19.118 + } 19.119 + }.start(); 19.120 + 19.121 + for (int i = 0; i < 20 ; i++) { 19.122 + String s = new String("some garbage"); 19.123 + System.gc(); 19.124 + } 19.125 + 19.126 + RedefineClassHelper.redefineClass(B.class, evenNewerB); 19.127 + System.gc(); 19.128 + 19.129 + for (int i = 0; i < 20 ; i++) { 19.130 + B.infinite(); 19.131 + String s = new String("some garbage"); 19.132 + System.gc(); 19.133 + } 19.134 + 19.135 + B.infinite_emcp(); 19.136 + 19.137 + // purge should clean everything up. 19.138 + B.stop = true; 19.139 + 19.140 + for (int i = 0; i < 20 ; i++) { 19.141 + B.infinite(); 19.142 + String s = new String("some garbage"); 19.143 + System.gc(); 19.144 + } 19.145 + } 19.146 +}