src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
branchJEP-349-branch
changeset 58823 6a21dba79b81
parent 58157 9dca61a7df19
child 58837 2bfbb50dd97d
equal deleted inserted replaced
58806:a7d850b47b19 58823:6a21dba79b81
  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);