1495 parser.set_klass_to_deallocate(ik); |
1495 parser.set_klass_to_deallocate(ik); |
1496 // now rewrite original pointer to newly created InstanceKlass |
1496 // now rewrite original pointer to newly created InstanceKlass |
1497 ik = new_ik; |
1497 ik = new_ik; |
1498 } |
1498 } |
1499 |
1499 |
1500 // During retransform/redefine, copy the Method specific trace flags |
|
1501 // from the previous ik ("the original klass") to the new ik ("the scratch_klass"). |
|
1502 // The open code for retransform/redefine does not know about these. |
|
1503 // In doing this migration here, we ensure the new Methods (defined in scratch klass) |
|
1504 // will carry over trace tags from the old Methods being replaced, |
|
1505 // ensuring flag/tag continuity while being transparent to open code. |
|
1506 static void copy_method_trace_flags(const InstanceKlass* the_original_klass, const InstanceKlass* the_scratch_klass) { |
|
1507 assert(the_original_klass != NULL, "invariant"); |
|
1508 assert(the_scratch_klass != NULL, "invariant"); |
|
1509 assert(the_original_klass->name() == the_scratch_klass->name(), "invariant"); |
|
1510 const Array<Method*>* old_methods = the_original_klass->methods(); |
|
1511 const Array<Method*>* new_methods = the_scratch_klass->methods(); |
|
1512 const bool equal_array_length = old_methods->length() == new_methods->length(); |
|
1513 // The Method array has the property of being sorted. |
|
1514 // If they are the same length, there is a one-to-one mapping. |
|
1515 // If they are unequal, there was a method added (currently only |
|
1516 // private static methods allowed to be added), use lookup. |
|
1517 for (int i = 0; i < old_methods->length(); ++i) { |
|
1518 const Method* const old_method = old_methods->at(i); |
|
1519 Method* const new_method = equal_array_length ? new_methods->at(i) : |
|
1520 the_scratch_klass->find_method(old_method->name(), old_method->signature()); |
|
1521 assert(new_method != NULL, "invariant"); |
|
1522 assert(new_method->name() == old_method->name(), "invariant"); |
|
1523 assert(new_method->signature() == old_method->signature(), "invariant"); |
|
1524 new_method->set_trace_flags(old_method->trace_flags()); |
|
1525 assert(new_method->trace_flags() == old_method->trace_flags(), "invariant"); |
|
1526 } |
|
1527 } |
|
1528 |
|
1529 static bool is_retransforming(const InstanceKlass* ik, TRAPS) { |
1500 static bool is_retransforming(const InstanceKlass* ik, TRAPS) { |
1530 assert(ik != NULL, "invariant"); |
1501 assert(ik != NULL, "invariant"); |
1531 assert(JdkJfrEvent::is_a(ik), "invariant"); |
1502 assert(JdkJfrEvent::is_a(ik), "invariant"); |
1532 Symbol* const name = ik->name(); |
1503 Symbol* const name = ik->name(); |
1533 assert(name != NULL, "invariant"); |
1504 assert(name != NULL, "invariant"); |
1534 Handle class_loader(THREAD, ik->class_loader()); |
1505 Handle class_loader(THREAD, ik->class_loader()); |
1535 Handle protection_domain(THREAD, ik->protection_domain()); |
1506 Handle protection_domain(THREAD, ik->protection_domain()); |
1536 // nota bene: use lock-free dictionary lookup |
1507 return SystemDictionary::find(name, class_loader, protection_domain, THREAD) != NULL; |
1537 const InstanceKlass* prev_ik = (const InstanceKlass*)SystemDictionary::find(name, class_loader, protection_domain, THREAD); |
|
1538 if (prev_ik == NULL) { |
|
1539 return false; |
|
1540 } |
|
1541 // an existing ik implies a retransform/redefine |
|
1542 assert(prev_ik != NULL, "invariant"); |
|
1543 assert(JdkJfrEvent::is_a(prev_ik), "invariant"); |
|
1544 copy_method_trace_flags(prev_ik, ik); |
|
1545 return true; |
|
1546 } |
1508 } |
1547 |
1509 |
1548 // target for JFR_ON_KLASS_CREATION hook |
1510 // target for JFR_ON_KLASS_CREATION hook |
1549 void JfrEventClassTransformer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS) { |
1511 void JfrEventClassTransformer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS) { |
1550 assert(ik != NULL, "invariant"); |
1512 assert(ik != NULL, "invariant"); |
1569 assert(JdkJfrEvent::is(new_ik), "invariant"); |
1531 assert(JdkJfrEvent::is(new_ik), "invariant"); |
1570 rewrite_klass_pointer(ik, new_ik, parser, THREAD); |
1532 rewrite_klass_pointer(ik, new_ik, parser, THREAD); |
1571 return; |
1533 return; |
1572 } |
1534 } |
1573 assert(JdkJfrEvent::is_subklass(ik), "invariant"); |
1535 assert(JdkJfrEvent::is_subklass(ik), "invariant"); |
1574 if (is_retransforming(ik, THREAD)) { |
1536 if (ik->is_abstract() || is_retransforming(ik, THREAD)) { |
1575 // not the initial klass load |
1537 // abstract and scratch classes are not instrumented |
1576 return; |
|
1577 } |
|
1578 if (ik->is_abstract()) { |
|
1579 // abstract classes are not instrumented |
|
1580 return; |
1538 return; |
1581 } |
1539 } |
1582 ResourceMark rm(THREAD); |
1540 ResourceMark rm(THREAD); |
1583 HandleMark hm(THREAD); |
1541 HandleMark hm(THREAD); |
1584 ClassFileStream* const new_stream = create_new_bytes_for_subklass(ik, parser, THREAD); |
1542 ClassFileStream* const new_stream = create_new_bytes_for_subklass(ik, parser, THREAD); |